@canvas3/nuxt 0.1.32 → 0.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +242 -30
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -6
- package/dist/runtime/types/types.d.ts +0 -2
- package/package.json +1 -1
- package/dist/runtime/components/canvas3-image.vue +0 -76
- package/dist/runtime/components/canvas3-image.vue.d.ts +0 -8
- package/dist/runtime/components/canvas3-text.vue +0 -95
- package/dist/runtime/components/canvas3-text.vue.d.ts +0 -12
package/README.md
CHANGED
|
@@ -1,68 +1,280 @@
|
|
|
1
|
-
|
|
2
|
-
Get your module up and running quickly.
|
|
1
|
+
# Canvas3 Nuxt Module
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
- Name: My Module
|
|
6
|
-
- Package name: my-module
|
|
7
|
-
- Description: My new Nuxt module
|
|
8
|
-
-->
|
|
3
|
+
A Nuxt module that integrates ThreeJS into your Nuxt app, providing a smooth-scroll engine, WebGL image effects, scroll-triggered animations, and a shader/animation API — all wired together through Vue directives and a global `Canvas3` composable-like utility.
|
|
9
4
|
|
|
10
|
-
|
|
5
|
+
[✨ Example use cases](https://canvas3.vercel.app/)
|
|
11
6
|
|
|
12
|
-
|
|
7
|
+
## Features
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
- 🎬 **Smooth scroll engine** – Custom lerp-based scroll with speed tracking, fixed-to-parent elements, and mobile breakpoint handling.
|
|
10
|
+
- 🖼 **WebGL image replacement** – Turn any `<img>` into a shader-driven ThreeJS mesh via the `v-canvas3-image` directive.
|
|
11
|
+
- 👀 **Scroll-triggered activation** – Activate/deactivate elements (and their linked meshes) as they enter/leave the viewport with `v-canvas3-scroll-action`.
|
|
12
|
+
- 🎨 **Custom shader support** – Bring your own vertex/fragment shaders per mesh, plus a global post-processing scroll shader pass.
|
|
13
|
+
- ⏱ **Animation scheduler** – Register callbacks that run conditionally on scroll, resize, mouse move, or custom render triggers, avoiding unnecessary renders.
|
|
14
|
+
- 🖱 **Mouse-reactive uniforms** – Automatic `uMouse` / `uMouseMovement` uniforms updated on mouse movement for interactive shaders.
|
|
15
|
+
- 📱 **Responsive & reduced-motion aware** – Built-in `isMobile` / `prefersReducedMotion` / `disabled` options to gracefully degrade.
|
|
16
|
+
- 🧩 **Global utility API** – `Canvas3` import exposes scene, camera, renderer, mesh, and scroll controls anywhere in your app.
|
|
17
|
+
- 🏗 **Layout-based setup** – Ships a ready-to-use `canvas3` Nuxt layout that wraps your page content with the scroll/canvas containers.
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
## Quick Setup
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
Install the module to your Nuxt application with one command:
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
```bash
|
|
24
|
+
npx nuxi module add canvas3-nuxt
|
|
25
|
+
```
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
That's it! You can now use the Canvas3 module in your Nuxt app ✨
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
### 1. Use the `canvas3` layout
|
|
25
30
|
|
|
26
|
-
|
|
31
|
+
```vue
|
|
32
|
+
<!-- pages/index.vue -->
|
|
33
|
+
<script setup>
|
|
34
|
+
definePageMeta({ layout: 'canvas3' })
|
|
35
|
+
</script>
|
|
36
|
+
```
|
|
27
37
|
|
|
28
|
-
|
|
38
|
+
### 2. Enable Canvas3 in the layout
|
|
29
39
|
|
|
30
|
-
|
|
40
|
+
The layout exposes `canvas3enabled` and `canvas3options` props. Enable it once your options (shaders, fonts, etc.) are ready:
|
|
31
41
|
|
|
32
|
-
|
|
42
|
+
```vue
|
|
43
|
+
<!-- app.vue or a wrapping component -->
|
|
44
|
+
<template>
|
|
45
|
+
<NuxtLayout
|
|
46
|
+
:canvas3enabled="ready"
|
|
47
|
+
:canvas3options="canvas3Options"
|
|
48
|
+
@canvas3-ready="onReady"
|
|
49
|
+
>
|
|
50
|
+
<NuxtPage />
|
|
51
|
+
</NuxtLayout>
|
|
52
|
+
</template>
|
|
33
53
|
|
|
34
|
-
|
|
54
|
+
<script setup>
|
|
55
|
+
import { ref } from 'vue'
|
|
35
56
|
|
|
36
|
-
|
|
37
|
-
|
|
57
|
+
const ready = ref(false)
|
|
58
|
+
const canvas3Options = {
|
|
59
|
+
shaders: {
|
|
60
|
+
default: { vertexShader: defaultVert, fragmentShader: defaultFrag },
|
|
61
|
+
scroll: { vertexShader: scrollVert, fragmentShader: scrollFrag },
|
|
62
|
+
},
|
|
63
|
+
activateMeshOptions: {
|
|
64
|
+
image: { uAniInImage: { value: 1, duration: 1, ease: 'power2.out' } },
|
|
65
|
+
},
|
|
66
|
+
canvasElement: { zIndex: -1 },
|
|
67
|
+
prefersReducedMotion: false,
|
|
68
|
+
isMobile: false,
|
|
69
|
+
disabled: false,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function onReady() {
|
|
73
|
+
ready.value = true
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ready.value = true
|
|
77
|
+
</script>
|
|
38
78
|
```
|
|
39
|
-
|
|
79
|
+
|
|
80
|
+
## Directives
|
|
81
|
+
|
|
82
|
+
### `v-canvas3-image`
|
|
83
|
+
|
|
84
|
+
Converts an `<img>` element into a ThreeJS mesh rendered in sync with the DOM element's position, size, and scroll offset. The original image is hidden (opacity set to 0) and replaced visually by the WebGL mesh.
|
|
85
|
+
|
|
86
|
+
**Requirements:** must be applied to an `<img>` tag.
|
|
87
|
+
|
|
88
|
+
**Binding value** (`Canvas3ImageBinding`):
|
|
89
|
+
|
|
90
|
+
| Option | Type | Description |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| `shaderName` | `string` | Key of a custom shader registered in `canvas3Options.shaders`. Falls back to `shaders.default`. |
|
|
93
|
+
| `uniforms` | `MeshMaterialUniform` | Extra/overriding shader uniforms merged into the material on creation and reactively on update. |
|
|
94
|
+
| `activateMeshUniforms` | `MeshMaterialUniform` | Uniforms animated (0 → 1) when the mesh's linked scroll-action element becomes active/inactive. |
|
|
95
|
+
|
|
96
|
+
```vue
|
|
97
|
+
<template>
|
|
98
|
+
<img
|
|
99
|
+
src="/images/hero.jpg"
|
|
100
|
+
alt="Hero"
|
|
101
|
+
v-canvas3-image="{
|
|
102
|
+
shaderName: 'wave',
|
|
103
|
+
uniforms: {
|
|
104
|
+
vectorVNoise: { value: [2, 2], duration: 0 },
|
|
105
|
+
},
|
|
106
|
+
activateMeshUniforms: {
|
|
107
|
+
uAniInImage: { value: 1, duration: 1.2, ease: 'power2.out' },
|
|
108
|
+
},
|
|
109
|
+
}"
|
|
110
|
+
>
|
|
111
|
+
</template>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Behavior notes:
|
|
115
|
+
- Waits for the image to load (`complete`/`load` event) and for the canvas to be initiated before creating the mesh.
|
|
116
|
+
- Automatically re-creates the mesh if `src` changes.
|
|
117
|
+
- Cleans up (disposes geometry/material/texture, removes from scene) on unmount.
|
|
118
|
+
- Respects `canvas3options.disabled`, adding a `.reduced-motion` class instead of creating a mesh.
|
|
119
|
+
|
|
120
|
+
### `v-canvas3-scroll-action`
|
|
121
|
+
|
|
122
|
+
Marks an element to be tracked by the scroll engine. When the element enters/exits the configured viewport range, it toggles an `active` class, fires callbacks, and (optionally) activates any WebGL image meshes nested inside it (matched via `data-mesh-id`, set automatically by `v-canvas3-image`).
|
|
123
|
+
|
|
124
|
+
**Binding value** (`scrollActionBindOptionType`):
|
|
125
|
+
|
|
126
|
+
| Option | Type | Description |
|
|
127
|
+
|---|---|---|
|
|
128
|
+
| `activateOnce` | `boolean` | Once activated, the element is never deactivated again. |
|
|
129
|
+
| `trackOnly` | `boolean` | Skip class toggling and mesh activation; only fires callbacks/tracking. |
|
|
130
|
+
| `activeRange` | `number` | Fraction of viewport height used as the "active zone" (default `1`, i.e. full viewport). |
|
|
131
|
+
| `activeRangeMargin` | `number` | Extra pixel margin added to the active range for speed-tracking calculations. |
|
|
132
|
+
| `scrollSpeed` | `{ value: number }` | Applies a parallax translate based on scroll position, proportional to `value`. |
|
|
133
|
+
| `scrollSpeedSetTo` | `{ value: number, duration: number }` | Animates `scrollSpeed.value` to a new target over `duration` seconds via GSAP. |
|
|
134
|
+
| `fixToParent` | `{ containerId: string, fixPosition: number, margin: number }` | Pins the element's first child inside a container (by `id`) at a given viewport position while the container is in view. |
|
|
135
|
+
| `activateCallback` | `(item) => void` | Called when the element becomes active. |
|
|
136
|
+
| `deactivateCallback` | `(item) => void` | Called when the element becomes inactive (unless `activateOnce`). |
|
|
137
|
+
| `onScrollCallback` | `(item, scrollSpeed, currentPosition) => void` | Called continuously while the element is in view and the page is scrolling. |
|
|
138
|
+
|
|
139
|
+
```vue
|
|
140
|
+
<template>
|
|
141
|
+
<section
|
|
142
|
+
v-canvas3-scroll-action="{
|
|
143
|
+
activeRange: 0.8,
|
|
144
|
+
activateCallback: onSectionActive,
|
|
145
|
+
deactivateCallback: onSectionInactive,
|
|
146
|
+
}"
|
|
147
|
+
>
|
|
148
|
+
<img src="/images/panel.jpg" alt="Panel" v-canvas3-image="{}">
|
|
149
|
+
</section>
|
|
150
|
+
</template>
|
|
151
|
+
|
|
152
|
+
<script setup>
|
|
153
|
+
function onSectionActive(item) {
|
|
154
|
+
console.log('Section entered view', item.elNode)
|
|
155
|
+
}
|
|
156
|
+
function onSectionInactive(item) {
|
|
157
|
+
console.log('Section left view', item.elNode)
|
|
158
|
+
}
|
|
159
|
+
</script>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Parallax example:**
|
|
163
|
+
|
|
164
|
+
```vue
|
|
165
|
+
<div v-canvas3-scroll-action="{ scrollSpeed: { value: 0.3 } }">
|
|
166
|
+
<div>Moves at 0.3x scroll speed</div>
|
|
167
|
+
</div>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Pin-to-parent example:**
|
|
171
|
+
|
|
172
|
+
```vue
|
|
173
|
+
<div id="stickyContainer" style="height: 200vh;">
|
|
174
|
+
<div
|
|
175
|
+
v-canvas3-scroll-action="{
|
|
176
|
+
fixToParent: { containerId: 'stickyContainer', fixPosition: 0.5, margin: 0 },
|
|
177
|
+
}"
|
|
178
|
+
>
|
|
179
|
+
<div>Pinned child, centered at 50% viewport while parent is in view</div>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Global `Canvas3` Utility
|
|
185
|
+
|
|
186
|
+
The module auto-imports a `Canvas3` utility (via Nuxt's `addImports`) that exposes scene/camera/renderer access and imperative controls, independent of the directives.
|
|
187
|
+
|
|
188
|
+
| Method | Description |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `addMeshToScene(mesh)` | Adds a raw ThreeJS `Mesh` directly to the Canvas3 scene. |
|
|
191
|
+
| `getMeshFromSceneByName(name)` | Retrieves a scene object by its `name`. |
|
|
192
|
+
| `addImageAsMesh(imgEl, shaderName, meshId, uniforms, activateMeshUniforms)` | Lower-level API used internally by `v-canvas3-image`; can be called manually. |
|
|
193
|
+
| `removeMesh(id)` | Disposes and removes a mesh (and its material/texture) by id. |
|
|
194
|
+
| `getShaderMaterial(mesh)` | Type-casts and returns a mesh's `ShaderMaterial`. |
|
|
195
|
+
| `addAnimationToRender(name, setup)` | Registers a named animation callback (see below). |
|
|
196
|
+
| `removeAnimationFromRender(name)` | Unregisters a named animation callback. |
|
|
197
|
+
| `setAnimationsToRender(state)` | Globally toggles whether `onAnimationsRender` animations run. |
|
|
198
|
+
| `setAnimationToRender(name, state, id)` | Adds/removes an `animationId` driving a specific animation's `render` state. |
|
|
199
|
+
| `setRenderDisabled(state)` | Pauses/resumes the entire render loop. |
|
|
200
|
+
| `setMeshPositionsUpdate(state)` | Forces continuous recalculation of image mesh positions/sizes (e.g. during layout shifts). |
|
|
201
|
+
| `resizeOnChange()` | Recalculates canvas size, camera, and mesh positions — call on custom resize triggers. |
|
|
202
|
+
| `scrollTo(position, delay?)` | Smoothly animates scroll to a pixel position. |
|
|
203
|
+
| `scrollToTop(delay?)` | Smoothly animates scroll to the top. |
|
|
204
|
+
| `scrollToElBySelector(selector, delay?, margin?)` | Scrolls to an element matched by a CSS selector. |
|
|
205
|
+
| `getScrollPosition()` | Returns the current rendered scroll position. |
|
|
206
|
+
| `getScrollSpeed()` | Returns the current normalized scroll speed (0–1). |
|
|
207
|
+
| `getCamera()` | Returns the active `THREE.PerspectiveCamera`. |
|
|
208
|
+
| `getRenderer()` | Returns the active `THREE.WebGLRenderer`. |
|
|
209
|
+
| `getScene()` | Returns the active `THREE.Scene`. |
|
|
210
|
+
|
|
211
|
+
**Animation callback example:**
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
import { Canvas3 } from '#imports'
|
|
215
|
+
|
|
216
|
+
Canvas3.addAnimationToRender('rotateLogo', {
|
|
217
|
+
onScroll: false,
|
|
218
|
+
onResize: false,
|
|
219
|
+
onMouseMove: true,
|
|
220
|
+
onAnimationsRender: false,
|
|
221
|
+
render: false,
|
|
222
|
+
animationCallback: () => {
|
|
223
|
+
const mesh = Canvas3.getMeshFromSceneByName('logoMesh')
|
|
224
|
+
if (mesh) mesh.rotation.y += 0.01
|
|
225
|
+
},
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
// later, to stop it:
|
|
229
|
+
Canvas3.removeAnimationFromRender('rotateLogo')
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Manual scroll control example:**
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
import { Canvas3 } from '#imports'
|
|
236
|
+
|
|
237
|
+
function goToSection() {
|
|
238
|
+
Canvas3.scrollToElBySelector('#contact', 0, -80)
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Options Reference (`Canvas3OptionsType`)
|
|
243
|
+
|
|
244
|
+
| Option | Type | Description |
|
|
245
|
+
|---|---|---|
|
|
246
|
+
| `shaders` | `{ default: Shader, scroll?: Shader, [name]: Shader }` | Registry of vertex/fragment shader pairs. `default` is required; `scroll` enables the post-processing scroll-speed effect pass. |
|
|
247
|
+
| `activateMeshOptions.image` | `Record<string, MeshAnimation>` | Default in/out uniform animations applied to image meshes on activation (e.g. `uAniInImage`). |
|
|
248
|
+
| `canvasElement.zIndex` | `number` | z-index applied to the fixed WebGL canvas container. |
|
|
249
|
+
| `prefersReducedMotion` | `boolean` | Flag to adapt behavior for reduced-motion users. |
|
|
250
|
+
| `isMobile` | `boolean` | Flag to adapt behavior for mobile devices. |
|
|
251
|
+
| `disabled` | `boolean` | Globally disables mesh creation; `v-canvas3-image` falls back to a `.reduced-motion` class. |
|
|
40
252
|
|
|
41
253
|
## Contribution
|
|
42
254
|
|
|
43
255
|
<details>
|
|
44
256
|
<summary>Local development</summary>
|
|
45
|
-
|
|
257
|
+
|
|
46
258
|
```bash
|
|
47
259
|
# Install dependencies
|
|
48
260
|
npm install
|
|
49
|
-
|
|
261
|
+
|
|
50
262
|
# Generate type stubs
|
|
51
263
|
npm run dev:prepare
|
|
52
|
-
|
|
264
|
+
|
|
53
265
|
# Develop with the playground
|
|
54
266
|
npm run dev
|
|
55
|
-
|
|
267
|
+
|
|
56
268
|
# Build the playground
|
|
57
269
|
npm run dev:build
|
|
58
|
-
|
|
270
|
+
|
|
59
271
|
# Run ESLint
|
|
60
272
|
npm run lint
|
|
61
|
-
|
|
273
|
+
|
|
62
274
|
# Run Vitest
|
|
63
275
|
npm run test
|
|
64
276
|
npm run test:watch
|
|
65
|
-
|
|
277
|
+
|
|
66
278
|
# Release new version
|
|
67
279
|
npm run release
|
|
68
280
|
```
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addTemplate, addLayout,
|
|
1
|
+
import { defineNuxtModule, createResolver, addTemplate, addLayout, addPlugin, addTypeTemplate, addImports } from '@nuxt/kit';
|
|
2
2
|
|
|
3
3
|
const module$1 = defineNuxtModule({
|
|
4
4
|
meta: {
|
|
@@ -13,11 +13,6 @@ const module$1 = defineNuxtModule({
|
|
|
13
13
|
write: true
|
|
14
14
|
});
|
|
15
15
|
addLayout(canvas3Layout, "canvas3");
|
|
16
|
-
addComponent({
|
|
17
|
-
name: "Canvas3Image",
|
|
18
|
-
filePath: resolve("./runtime/components/canvas3-image.vue"),
|
|
19
|
-
global: true
|
|
20
|
-
});
|
|
21
16
|
addPlugin(resolve("./runtime/plugins/directives"));
|
|
22
17
|
addTypeTemplate({
|
|
23
18
|
filename: "types/canvas3-directives.d.ts",
|
|
@@ -83,9 +83,7 @@ export type scrollActionBindOptionType = {
|
|
|
83
83
|
deactivateCallback?: (item: ScrollActionType) => void;
|
|
84
84
|
onScrollCallback?: (item: ScrollActionType, scrollSpeed: number, currentPosition: number) => void;
|
|
85
85
|
activeRangeMargin?: number;
|
|
86
|
-
activeRangeOrigin?: number;
|
|
87
86
|
activeRange?: number;
|
|
88
|
-
bidirectionalActivation?: boolean;
|
|
89
87
|
};
|
|
90
88
|
export type ScrollActionBinding = {
|
|
91
89
|
elNode: HTMLElement;
|
package/package.json
CHANGED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="webgl-img-wrapper">
|
|
3
|
-
<img
|
|
4
|
-
ref="image"
|
|
5
|
-
class="webgl-img"
|
|
6
|
-
:class="{ 'reduced-motion': reducedMotion ?? null }"
|
|
7
|
-
:alt="props.options.alt"
|
|
8
|
-
:src="props.options.src"
|
|
9
|
-
:loading="props.options.loadStrategy"
|
|
10
|
-
@load="addImageToCanvas"
|
|
11
|
-
>
|
|
12
|
-
</div>
|
|
13
|
-
</template>
|
|
14
|
-
|
|
15
|
-
<script setup>
|
|
16
|
-
import { ref, computed, watch, onMounted, nextTick, onBeforeUnmount } from "vue";
|
|
17
|
-
import { Canvas3 } from "#canvas3-nuxt/utils/canvas3/canvas3";
|
|
18
|
-
const props = defineProps({
|
|
19
|
-
options: { type: Object, required: false, default: () => ({
|
|
20
|
-
alt: "",
|
|
21
|
-
src: "",
|
|
22
|
-
loadStrategy: "lazy",
|
|
23
|
-
shaderName: void 0,
|
|
24
|
-
uniforms: {},
|
|
25
|
-
activateMeshUniforms: {}
|
|
26
|
-
}) }
|
|
27
|
-
});
|
|
28
|
-
const reducedMotion = computed(() => Canvas3.options?.disabled ?? null);
|
|
29
|
-
const image = ref();
|
|
30
|
-
const generatedMeshId = "image_" + crypto.randomUUID();
|
|
31
|
-
const imgAddedToCanvas = ref(false);
|
|
32
|
-
const imgIsAdding = ref(false);
|
|
33
|
-
const addImageToCanvas = async () => {
|
|
34
|
-
if (imgAddedToCanvas.value || imgIsAdding.value) return;
|
|
35
|
-
imgIsAdding.value = true;
|
|
36
|
-
try {
|
|
37
|
-
await nextTick();
|
|
38
|
-
if (!image.value || Canvas3.canvasInitiated.value === false || Canvas3.options?.disabled || imgAddedToCanvas.value) return;
|
|
39
|
-
if (image.value.naturalWidth === 0) return;
|
|
40
|
-
image.value.dataset.meshId = generatedMeshId;
|
|
41
|
-
await Canvas3.addImageAsMesh(
|
|
42
|
-
image.value,
|
|
43
|
-
props.options.shaderName ?? null,
|
|
44
|
-
generatedMeshId,
|
|
45
|
-
props.options.uniforms ?? {},
|
|
46
|
-
props.options.activateMeshUniforms ?? {}
|
|
47
|
-
);
|
|
48
|
-
imgAddedToCanvas.value = true;
|
|
49
|
-
} finally {
|
|
50
|
-
imgIsAdding.value = false;
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
watch(() => Canvas3.canvasInitiated.value, (ready) => {
|
|
54
|
-
if (ready) addImageToCanvas();
|
|
55
|
-
});
|
|
56
|
-
watch(() => props.options.uniforms, (u) => {
|
|
57
|
-
if (u)
|
|
58
|
-
Canvas3.meshUniformsUpdate(generatedMeshId, u);
|
|
59
|
-
}, { deep: true });
|
|
60
|
-
watch(() => props.options.src, () => {
|
|
61
|
-
imgAddedToCanvas.value = false;
|
|
62
|
-
nextTick(() => {
|
|
63
|
-
if (image.value?.complete) addImageToCanvas();
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
onMounted(() => {
|
|
67
|
-
if (image.value?.complete) addImageToCanvas();
|
|
68
|
-
});
|
|
69
|
-
onBeforeUnmount(() => {
|
|
70
|
-
Canvas3.removeMesh(generatedMeshId);
|
|
71
|
-
});
|
|
72
|
-
</script>
|
|
73
|
-
|
|
74
|
-
<style scoped>
|
|
75
|
-
.webgl-img{max-height:100%;max-width:100%;opacity:0}.webgl-img.reduced-motion{height:100%;-o-object-fit:cover;object-fit:cover;opacity:1;width:100%}
|
|
76
|
-
</style>
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { Canvas3ImageBindType } from '#canvas3-nuxt/types/types';
|
|
2
|
-
type __VLS_Props = {
|
|
3
|
-
options?: Canvas3ImageBindType;
|
|
4
|
-
};
|
|
5
|
-
declare const _default: import("vue").DefineComponent<__VLS_Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
6
|
-
options: Canvas3ImageBindType;
|
|
7
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
-
export default _default;
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<span
|
|
3
|
-
ref="htmlEl"
|
|
4
|
-
class="text-wrapper"
|
|
5
|
-
:class="{ 'reduced-motion': reducedMotion }"
|
|
6
|
-
>
|
|
7
|
-
<slot />
|
|
8
|
-
</span>
|
|
9
|
-
</template>
|
|
10
|
-
|
|
11
|
-
<script setup>
|
|
12
|
-
import { ref, watch, onMounted, onBeforeUnmount, defineProps, computed } from "vue";
|
|
13
|
-
import { Canvas3 } from "#canvas3-nuxt/utils/canvas3/canvas3";
|
|
14
|
-
const props = defineProps({
|
|
15
|
-
options: {
|
|
16
|
-
type: {
|
|
17
|
-
shaderName: {
|
|
18
|
-
type: String,
|
|
19
|
-
default: null
|
|
20
|
-
},
|
|
21
|
-
theme: {
|
|
22
|
-
type: String,
|
|
23
|
-
default: "dark"
|
|
24
|
-
},
|
|
25
|
-
uniforms: {
|
|
26
|
-
type: Object,
|
|
27
|
-
default: () => {
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
activateMeshUniforms: {
|
|
31
|
-
type: Object,
|
|
32
|
-
default: () => {
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
default: () => ({
|
|
37
|
-
uniforms: {},
|
|
38
|
-
activateMeshUniforms: {}
|
|
39
|
-
})
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
const reducedMotion = computed(() => {
|
|
43
|
-
return Canvas3.options?.disabled ?? null;
|
|
44
|
-
});
|
|
45
|
-
const htmlEl = ref("htmlEl");
|
|
46
|
-
const meshId = "text" + crypto.randomUUID();
|
|
47
|
-
const getTrimmedText = () => {
|
|
48
|
-
let innerHTML = htmlEl.value.innerHTML;
|
|
49
|
-
if (innerHTML.includes("<!--]-->")) {
|
|
50
|
-
const start = innerHTML.indexOf("<!--[-->") + 8;
|
|
51
|
-
const end = innerHTML.indexOf("<!--]-->");
|
|
52
|
-
innerHTML = innerHTML.slice(start, end);
|
|
53
|
-
}
|
|
54
|
-
return innerHTML;
|
|
55
|
-
};
|
|
56
|
-
watch(
|
|
57
|
-
() => props.options.uniforms,
|
|
58
|
-
(uniforms) => {
|
|
59
|
-
if (Canvas3.options?.disabled)
|
|
60
|
-
return;
|
|
61
|
-
setTimeout(() => {
|
|
62
|
-
Canvas3.meshUniformsUpdate(meshId, uniforms);
|
|
63
|
-
}, 0);
|
|
64
|
-
},
|
|
65
|
-
{ deep: true }
|
|
66
|
-
);
|
|
67
|
-
onMounted(() => {
|
|
68
|
-
htmlEl.value.dataset.meshId = meshId;
|
|
69
|
-
});
|
|
70
|
-
onBeforeUnmount(() => {
|
|
71
|
-
Canvas3.removeMesh(meshId);
|
|
72
|
-
});
|
|
73
|
-
watch(
|
|
74
|
-
() => Canvas3.canvasInitiated.value,
|
|
75
|
-
(newVal) => {
|
|
76
|
-
if (Canvas3.options?.disabled || !newVal)
|
|
77
|
-
return;
|
|
78
|
-
setTimeout(() => {
|
|
79
|
-
Canvas3.addTextAsMSDF(
|
|
80
|
-
props.options.shaderName,
|
|
81
|
-
meshId,
|
|
82
|
-
htmlEl.value,
|
|
83
|
-
getTrimmedText(),
|
|
84
|
-
props.options.theme,
|
|
85
|
-
props.options.uniforms,
|
|
86
|
-
props.options.activateMeshUniforms
|
|
87
|
-
);
|
|
88
|
-
}, 0);
|
|
89
|
-
}
|
|
90
|
-
);
|
|
91
|
-
</script>
|
|
92
|
-
|
|
93
|
-
<style scoped>
|
|
94
|
-
.text-wrapper{display:inline-block;opacity:0}.text-wrapper.reduced-motion{opacity:1}
|
|
95
|
-
</style>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
declare var __VLS_1: {};
|
|
2
|
-
type __VLS_Slots = {} & {
|
|
3
|
-
default?: (props: typeof __VLS_1) => any;
|
|
4
|
-
};
|
|
5
|
-
declare const __VLS_component: import("vue").DefineSetupFnComponent<Record<string, any>, {}, {}, Record<string, any> & {}, import("vue").PublicProps>;
|
|
6
|
-
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
7
|
-
export default _default;
|
|
8
|
-
type __VLS_WithSlots<T, S> = T & {
|
|
9
|
-
new (): {
|
|
10
|
-
$slots: S;
|
|
11
|
-
};
|
|
12
|
-
};
|