|
1 | 1 | <template> |
2 | | - <div id="canvas" class="h-64" /> |
| 2 | + <div ref="container" class="h-64" /> |
3 | 3 | </template> |
4 | 4 |
|
5 | 5 | <script setup lang="ts"> |
6 | | -const { $p5 } = useNuxtApp(); |
| 6 | +import { onBeforeUnmount, onMounted, ref } from "vue"; |
7 | 7 |
|
8 | | -const { path, backgroundColor = 100 } = defineProps<{ |
9 | | - path: string; |
10 | | - backgroundColor?: Number; |
11 | | -}>(); |
| 8 | +const props = withDefaults( |
| 9 | + defineProps<{ |
| 10 | + path: string; |
| 11 | + backgroundColor?: number; |
| 12 | + }>(), |
| 13 | + { |
| 14 | + backgroundColor: 100, |
| 15 | + }, |
| 16 | +); |
12 | 17 |
|
13 | | -onMounted(() => { |
14 | | - console.log(backgroundColor); |
15 | | - const sketch = (s) => { |
16 | | - const c = document.getElementById("canvas"); |
| 18 | +const container = ref<HTMLElement | null>(null); |
| 19 | +let p5Instance: any = null; |
17 | 20 |
|
18 | | - const WIDTH = c.clientWidth; |
19 | | - const HEIGHT = c.clientHeight; |
| 21 | +onMounted(async () => { |
| 22 | + if (!container.value) { |
| 23 | + return; |
| 24 | + } |
20 | 25 |
|
| 26 | + const { $p5 } = useNuxtApp(); |
| 27 | + const p5 = await $p5(); |
| 28 | + const host = container.value; |
| 29 | +
|
| 30 | + const sketch = (s: any) => { |
21 | 31 | let model; |
22 | | - let angle; |
| 32 | + let angle = 0; |
23 | 33 | let rotate = true; |
24 | 34 |
|
| 35 | + const getSize = () => { |
| 36 | + return { |
| 37 | + width: host.clientWidth || 0, |
| 38 | + height: host.clientHeight || 0, |
| 39 | + }; |
| 40 | + }; |
| 41 | +
|
25 | 42 | s.preload = () => { |
26 | | - model = s.loadModel(path, true); |
| 43 | + model = s.loadModel(props.path, true); |
27 | 44 | }; |
28 | 45 |
|
29 | 46 | s.setup = () => { |
30 | | - s.createCanvas(WIDTH, HEIGHT, s.WEBGL); |
| 47 | + const { width, height } = getSize(); |
| 48 | + s.createCanvas(width, height, s.WEBGL); |
| 49 | + }; |
| 50 | +
|
| 51 | + s.windowResized = () => { |
| 52 | + const { width, height } = getSize(); |
| 53 | + s.resizeCanvas(width, height); |
31 | 54 | }; |
32 | 55 |
|
33 | 56 | s.mouseClicked = () => { |
34 | 57 | rotate = false; // disable object rotation on click |
35 | 58 | }; |
36 | 59 |
|
37 | 60 | s.draw = () => { |
38 | | - s.background(backgroundColor); |
| 61 | + const bg = Number(props.backgroundColor ?? 100); |
| 62 | +
|
| 63 | + s.background(bg); |
39 | 64 | s.lights(); |
40 | 65 |
|
41 | 66 | if (rotate) { |
42 | 67 | angle = s.frameCount * 0.005; |
43 | 68 | } |
| 69 | +
|
44 | 70 | s.rotateX(angle); |
45 | 71 | s.rotateY(angle); |
46 | 72 | s.orbitControl(); |
47 | 73 |
|
48 | | - s.model(model); |
| 74 | + if (model) { |
| 75 | + s.model(model); |
| 76 | + } |
49 | 77 | }; |
50 | 78 | }; |
51 | 79 |
|
52 | | - // eslint-disable-next-line no-new |
53 | | - new $p5(sketch, "canvas"); |
| 80 | + p5Instance = new p5(sketch, host); |
| 81 | +}); |
| 82 | +
|
| 83 | +onBeforeUnmount(() => { |
| 84 | + if (p5Instance) { |
| 85 | + p5Instance.remove?.(); |
| 86 | + p5Instance = null; |
| 87 | + } |
54 | 88 | }); |
55 | 89 | </script> |
0 commit comments