canvasengine 2.0.0-beta.2 → 2.0.0-beta.21
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/dist/index.d.ts +1289 -0
- package/dist/index.js +4248 -0
- package/dist/index.js.map +1 -0
- package/index.d.ts +4 -0
- package/package.json +5 -12
- package/src/components/Canvas.ts +53 -45
- package/src/components/Container.ts +2 -2
- package/src/components/DOMContainer.ts +123 -0
- package/src/components/DOMElement.ts +421 -0
- package/src/components/DisplayObject.ts +263 -189
- package/src/components/Graphic.ts +213 -36
- package/src/components/Mesh.ts +222 -0
- package/src/components/NineSliceSprite.ts +4 -1
- package/src/components/ParticleEmitter.ts +12 -8
- package/src/components/Sprite.ts +77 -14
- package/src/components/Text.ts +34 -14
- package/src/components/Video.ts +110 -0
- package/src/components/Viewport.ts +59 -43
- package/src/components/index.ts +6 -4
- package/src/components/types/DisplayObject.ts +30 -0
- package/src/directives/Drag.ts +357 -52
- package/src/directives/KeyboardControls.ts +3 -1
- package/src/directives/Sound.ts +94 -31
- package/src/directives/ViewportFollow.ts +35 -7
- package/src/engine/animation.ts +41 -5
- package/src/engine/bootstrap.ts +22 -3
- package/src/engine/directive.ts +2 -2
- package/src/engine/reactive.ts +337 -168
- package/src/engine/trigger.ts +65 -9
- package/src/engine/utils.ts +97 -9
- package/src/hooks/useProps.ts +1 -1
- package/src/index.ts +5 -1
- package/src/utils/RadialGradient.ts +29 -0
- package/src/utils/functions.ts +7 -0
- package/testing/index.ts +12 -0
- package/src/components/DrawMap/index.ts +0 -65
- package/src/components/Tilemap/Tile.ts +0 -79
- package/src/components/Tilemap/TileGroup.ts +0 -207
- package/src/components/Tilemap/TileLayer.ts +0 -163
- package/src/components/Tilemap/TileSet.ts +0 -41
- package/src/components/Tilemap/index.ts +0 -80
package/src/components/Sprite.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Howl } from 'howler';
|
|
2
|
+
import { computed, effect, isSignal, Signal } from "@signe/reactive";
|
|
2
3
|
import {
|
|
4
|
+
Application,
|
|
3
5
|
Assets,
|
|
4
6
|
Container,
|
|
5
7
|
Sprite as PixiSprite,
|
|
@@ -10,6 +12,7 @@ import { Subscription } from "rxjs";
|
|
|
10
12
|
import {
|
|
11
13
|
Element,
|
|
12
14
|
createComponent,
|
|
15
|
+
isElement,
|
|
13
16
|
registerComponent,
|
|
14
17
|
} from "../engine/reactive";
|
|
15
18
|
import { arrayEquals, isFunction } from "../engine/utils";
|
|
@@ -24,6 +27,7 @@ import {
|
|
|
24
27
|
import { ComponentFunction } from "../engine/signal";
|
|
25
28
|
import { DisplayObjectProps } from "./types/DisplayObject";
|
|
26
29
|
import { AnimatedSignal, isAnimatedSignal } from "../engine/animation";
|
|
30
|
+
import { Layout } from '@pixi/layout';
|
|
27
31
|
|
|
28
32
|
const log = console.log;
|
|
29
33
|
|
|
@@ -73,14 +77,25 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
73
77
|
private subscriptionSheet: Subscription[] = [];
|
|
74
78
|
private sheetParams: any = {};
|
|
75
79
|
private sheetCurrentAnimation: string = StandardAnimation.Stand;
|
|
80
|
+
private app: Application | null = null;
|
|
76
81
|
onFinish: () => void;
|
|
77
82
|
|
|
83
|
+
get renderer() {
|
|
84
|
+
return this.app?.renderer;
|
|
85
|
+
}
|
|
86
|
+
|
|
78
87
|
private currentAnimationContainer: Container | null = null;
|
|
79
88
|
|
|
80
89
|
private async createTextures(
|
|
81
90
|
options: Required<TextureOptionsMerging>
|
|
82
91
|
): Promise<Texture[][]> {
|
|
83
92
|
const { width, height, framesHeight, framesWidth, image, offset } = options;
|
|
93
|
+
|
|
94
|
+
if (!image || typeof image !== 'string' || image.trim() === '') {
|
|
95
|
+
console.warn('Invalid image path provided to createTextures:', image);
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
|
|
84
99
|
const texture = await Assets.load(image);
|
|
85
100
|
const spriteWidth = options.spriteWidth;
|
|
86
101
|
const spriteHeight = options.spriteHeight;
|
|
@@ -167,6 +182,7 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
167
182
|
const { props, propObservables } = params;
|
|
168
183
|
const tick: Signal = props.context.tick;
|
|
169
184
|
const sheet = props.sheet ?? {};
|
|
185
|
+
this.app = props.context.app();
|
|
170
186
|
if (sheet?.onFinish) {
|
|
171
187
|
this.onFinish = sheet.onFinish;
|
|
172
188
|
}
|
|
@@ -218,7 +234,7 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
218
234
|
this.sheetCurrentAnimation = StandardAnimation.Stand;
|
|
219
235
|
}
|
|
220
236
|
|
|
221
|
-
this.play(this.sheetCurrentAnimation, [this.sheetParams]);
|
|
237
|
+
if (this.spritesheet) this.play(this.sheetCurrentAnimation, [this.sheetParams]);
|
|
222
238
|
});
|
|
223
239
|
|
|
224
240
|
super.onMount(params);
|
|
@@ -227,6 +243,29 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
227
243
|
async onUpdate(props) {
|
|
228
244
|
super.onUpdate(props);
|
|
229
245
|
|
|
246
|
+
const setTexture = async (image: string) => {
|
|
247
|
+
if (!image || typeof image !== 'string' || image.trim() === '') {
|
|
248
|
+
console.warn('Invalid image path provided to setTexture:', image);
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const onProgress = this.fullProps.loader?.onProgress;
|
|
253
|
+
const texture = await Assets.load(image, (progress) => {
|
|
254
|
+
if (onProgress) onProgress(progress);
|
|
255
|
+
if (progress == 1) {
|
|
256
|
+
const onComplete = this.fullProps.loader?.onComplete;
|
|
257
|
+
if (onComplete) {
|
|
258
|
+
// hack to memoize the texture
|
|
259
|
+
setTimeout(() => {
|
|
260
|
+
onComplete(texture);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
return texture
|
|
267
|
+
}
|
|
268
|
+
|
|
230
269
|
const sheet = props.sheet;
|
|
231
270
|
if (sheet?.params) this.sheetParams = sheet?.params;
|
|
232
271
|
|
|
@@ -239,23 +278,36 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
239
278
|
|
|
240
279
|
if (props.scaleMode) this.baseTexture.scaleMode = props.scaleMode;
|
|
241
280
|
else if (props.image && this.fullProps.rectangle === undefined) {
|
|
242
|
-
|
|
281
|
+
const texture = await setTexture(this.fullProps.image);
|
|
282
|
+
if (texture) {
|
|
283
|
+
this.texture = texture;
|
|
284
|
+
}
|
|
243
285
|
} else if (props.texture) {
|
|
244
|
-
|
|
286
|
+
if (isElement(props.texture)) {
|
|
287
|
+
const textureInstance = props.texture.componentInstance;
|
|
288
|
+
textureInstance.subjectInit
|
|
289
|
+
.subscribe((value) => {
|
|
290
|
+
console.log('a', value?.width)
|
|
291
|
+
})
|
|
292
|
+
this.texture = this.renderer?.generateTexture(props.texture.componentInstance);
|
|
293
|
+
} else {
|
|
294
|
+
this.texture = props.texture;
|
|
295
|
+
}
|
|
245
296
|
}
|
|
246
|
-
|
|
247
297
|
if (props.rectangle !== undefined) {
|
|
248
298
|
const { x, y, width, height } = props.rectangle?.value ?? props.rectangle;
|
|
249
|
-
const texture = await
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
299
|
+
const texture = await setTexture(this.fullProps.image);
|
|
300
|
+
if (texture) {
|
|
301
|
+
this.texture = new Texture({
|
|
302
|
+
source: texture.source,
|
|
303
|
+
frame: new Rectangle(x, y, width, height),
|
|
304
|
+
});
|
|
305
|
+
}
|
|
254
306
|
}
|
|
255
307
|
}
|
|
256
308
|
|
|
257
|
-
onDestroy(): void {
|
|
258
|
-
super.onDestroy();
|
|
309
|
+
async onDestroy(parent: Element, afterDestroy: () => void): Promise<void> {
|
|
310
|
+
await super.onDestroy(parent);
|
|
259
311
|
this.subscriptionSheet.forEach((sub) => sub.unsubscribe());
|
|
260
312
|
this.subscriptionTick.unsubscribe();
|
|
261
313
|
if (this.currentAnimationContainer && this.parent instanceof Container) {
|
|
@@ -321,7 +373,12 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
321
373
|
const sound = this.currentAnimation.data.sound;
|
|
322
374
|
|
|
323
375
|
if (sound) {
|
|
324
|
-
|
|
376
|
+
new Howl({
|
|
377
|
+
src: sound,
|
|
378
|
+
autoplay: true,
|
|
379
|
+
loop: false,
|
|
380
|
+
volume: 1,
|
|
381
|
+
})
|
|
325
382
|
}
|
|
326
383
|
|
|
327
384
|
// Updates immediately to avoid flickering
|
|
@@ -440,7 +497,9 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
440
497
|
}
|
|
441
498
|
}
|
|
442
499
|
|
|
443
|
-
export interface CanvasSprite extends PixiSprite {
|
|
500
|
+
export interface CanvasSprite extends PixiSprite {
|
|
501
|
+
layout: Layout | null;
|
|
502
|
+
}
|
|
444
503
|
|
|
445
504
|
registerComponent("Sprite", CanvasSprite);
|
|
446
505
|
|
|
@@ -483,6 +542,10 @@ export interface SpritePropsWithSheet
|
|
|
483
542
|
params?: any;
|
|
484
543
|
onFinish?: () => void;
|
|
485
544
|
};
|
|
545
|
+
loader?: {
|
|
546
|
+
onProgress?: (progress: number) => void;
|
|
547
|
+
onComplete?: (texture: Texture) => void;
|
|
548
|
+
};
|
|
486
549
|
}
|
|
487
550
|
|
|
488
551
|
export type SpritePropTypes = SpritePropsWithImage | SpritePropsWithSheet;
|
package/src/components/Text.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { Text as PixiText, TextStyle } from "pixi.js";
|
|
2
|
-
import { createComponent, registerComponent } from "../engine/reactive";
|
|
3
|
-
import { DisplayObject } from "./DisplayObject";
|
|
2
|
+
import { createComponent, registerComponent, Element, Props } from "../engine/reactive";
|
|
3
|
+
import { DisplayObject, ComponentInstance } from "./DisplayObject";
|
|
4
4
|
import { DisplayObjectProps } from "./types/DisplayObject";
|
|
5
5
|
import { Signal } from "@signe/reactive";
|
|
6
|
-
import { on } from "../engine/trigger";
|
|
6
|
+
import { on, isTrigger } from "../engine/trigger";
|
|
7
7
|
|
|
8
8
|
enum TextEffect {
|
|
9
9
|
Typewriter = "typewriter",
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
interface TextProps extends DisplayObjectProps {
|
|
12
|
+
export interface TextProps extends DisplayObjectProps {
|
|
13
13
|
text?: string;
|
|
14
14
|
style?: Partial<TextStyle>;
|
|
15
15
|
color?: string;
|
|
@@ -21,6 +21,7 @@ interface TextProps extends DisplayObjectProps {
|
|
|
21
21
|
onComplete?: () => void;
|
|
22
22
|
skip?: () => void;
|
|
23
23
|
};
|
|
24
|
+
context?: any; // Ensure context is available, ideally typed from a base prop or injected
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
class CanvasText extends DisplayObject(PixiText) {
|
|
@@ -32,9 +33,15 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
32
33
|
private typewriterOptions: any = {};
|
|
33
34
|
private skipSignal?: () => void;
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Called when the component is mounted to the scene graph.
|
|
38
|
+
* Initializes the typewriter effect if configured.
|
|
39
|
+
* @param {Element<CanvasText>} element - The element being mounted with parent and props.
|
|
40
|
+
* @param {number} [index] - The index of the component among its siblings.
|
|
41
|
+
*/
|
|
42
|
+
async onMount(element: Element<CanvasText>, index?: number): Promise<void> {
|
|
43
|
+
const { props } = element;
|
|
44
|
+
await super.onMount(element, index);
|
|
38
45
|
const tick: Signal = props.context.tick;
|
|
39
46
|
|
|
40
47
|
if (props.text && props.typewriter) {
|
|
@@ -44,7 +51,7 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
44
51
|
// Set typewriter options
|
|
45
52
|
if (props.typewriter) {
|
|
46
53
|
this.typewriterOptions = props.typewriter;
|
|
47
|
-
if (this.typewriterOptions.skip) {
|
|
54
|
+
if (this.typewriterOptions.skip && isTrigger(this.typewriterOptions.skip)) {
|
|
48
55
|
on(this.typewriterOptions.skip, () => {
|
|
49
56
|
this.skipTypewriter();
|
|
50
57
|
});
|
|
@@ -65,8 +72,8 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
65
72
|
this.typewriterOptions = props.typewriter;
|
|
66
73
|
}
|
|
67
74
|
}
|
|
68
|
-
if (props.text) {
|
|
69
|
-
this.text = props.text;
|
|
75
|
+
if (props.text !== undefined) {
|
|
76
|
+
this.text = ''+props.text;
|
|
70
77
|
}
|
|
71
78
|
if (props.text !== undefined && props.text !== this.fullText && this.fullProps.typewriter) {
|
|
72
79
|
this.text = "";
|
|
@@ -130,13 +137,26 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
130
137
|
this.currentIndex = this.fullText.length;
|
|
131
138
|
}
|
|
132
139
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Called when the component is about to be destroyed.
|
|
142
|
+
* Unsubscribes from the tick observable.
|
|
143
|
+
* @param {Element<any>} parent - The parent element.
|
|
144
|
+
* @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
|
|
145
|
+
*/
|
|
146
|
+
async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {
|
|
147
|
+
const _afterDestroy = async () => {
|
|
148
|
+
if (this.subscriptionTick) {
|
|
149
|
+
this.subscriptionTick.unsubscribe();
|
|
150
|
+
}
|
|
151
|
+
if (afterDestroy) {
|
|
152
|
+
afterDestroy();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
await super.onDestroy(parent, _afterDestroy);
|
|
136
156
|
}
|
|
137
157
|
}
|
|
138
158
|
|
|
139
|
-
interface CanvasText extends PixiText {}
|
|
159
|
+
// interface CanvasText extends PixiText {} // Removed as it's redundant and causes type conflicts
|
|
140
160
|
|
|
141
161
|
registerComponent("Text", CanvasText);
|
|
142
162
|
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Texture } from "pixi.js";
|
|
2
|
+
import { h, mount } from "../engine/signal";
|
|
3
|
+
import { useDefineProps } from "../hooks/useProps";
|
|
4
|
+
import { Sprite } from "./Sprite";
|
|
5
|
+
import { effect, Signal, signal } from "@signe/reactive";
|
|
6
|
+
|
|
7
|
+
interface VideoProps {
|
|
8
|
+
src: string;
|
|
9
|
+
paused?: boolean;
|
|
10
|
+
loop?: boolean;
|
|
11
|
+
muted?: boolean;
|
|
12
|
+
loader?: {
|
|
13
|
+
onComplete?: (texture: Texture) => void;
|
|
14
|
+
onProgress?: (progress: number) => void;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function Video(props: VideoProps) {
|
|
19
|
+
const eventsMap = {
|
|
20
|
+
audioprocess: null,
|
|
21
|
+
canplay: null,
|
|
22
|
+
canplaythrough: null,
|
|
23
|
+
complete: null,
|
|
24
|
+
durationchange: null,
|
|
25
|
+
emptied: null,
|
|
26
|
+
ended: null,
|
|
27
|
+
loadeddata: null,
|
|
28
|
+
loadedmetadata: null,
|
|
29
|
+
pause: null,
|
|
30
|
+
play: null,
|
|
31
|
+
playing: null,
|
|
32
|
+
progress: null,
|
|
33
|
+
ratechange: null,
|
|
34
|
+
seeked: null,
|
|
35
|
+
seeking: null,
|
|
36
|
+
stalled: null,
|
|
37
|
+
suspend: null,
|
|
38
|
+
timeupdate: null,
|
|
39
|
+
volumechange: null,
|
|
40
|
+
waiting: null
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const video: Signal<HTMLVideoElement | null> = signal(null)
|
|
44
|
+
const defineProps = useDefineProps(props)
|
|
45
|
+
const { play, loop, muted } = defineProps({
|
|
46
|
+
play: {
|
|
47
|
+
type: Boolean,
|
|
48
|
+
default: true
|
|
49
|
+
},
|
|
50
|
+
loop: {
|
|
51
|
+
type: Boolean,
|
|
52
|
+
default: false
|
|
53
|
+
},
|
|
54
|
+
muted: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
default: false
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
effect(() => {
|
|
61
|
+
const _video = video()
|
|
62
|
+
const state = play()
|
|
63
|
+
if (_video && state !== undefined) {
|
|
64
|
+
if (state) {
|
|
65
|
+
_video.play()
|
|
66
|
+
} else {
|
|
67
|
+
_video.pause()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (_video && loop()) {
|
|
71
|
+
_video.loop = loop()
|
|
72
|
+
}
|
|
73
|
+
if (_video && muted()) {
|
|
74
|
+
_video.muted = muted()
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
mount(() => {
|
|
79
|
+
return () => {
|
|
80
|
+
for (let event in eventsMap) {
|
|
81
|
+
if (eventsMap[event]) {
|
|
82
|
+
video().removeEventListener(event, eventsMap[event])
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
return h(Sprite, {
|
|
89
|
+
...props,
|
|
90
|
+
image: props.src,
|
|
91
|
+
loader: {
|
|
92
|
+
onComplete: (texture) => {
|
|
93
|
+
const source = texture.source.resource
|
|
94
|
+
video.set(source)
|
|
95
|
+
if (props?.loader?.onComplete) {
|
|
96
|
+
props.loader.onComplete(texture)
|
|
97
|
+
}
|
|
98
|
+
for (let event in eventsMap) {
|
|
99
|
+
if (props[event]) {
|
|
100
|
+
const cb = (ev) => {
|
|
101
|
+
props[event](ev)
|
|
102
|
+
}
|
|
103
|
+
eventsMap[event] = cb
|
|
104
|
+
source.addEventListener(event, cb)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Viewport as PixiViewport } from 'pixi-viewport';
|
|
2
2
|
import { Subscription } from 'rxjs';
|
|
3
|
-
import { createComponent, registerComponent } from '../engine/reactive';
|
|
4
|
-
import { DisplayObject } from './DisplayObject';
|
|
5
|
-
import { effect } from '@signe/reactive';
|
|
3
|
+
import { createComponent, registerComponent, Element, Props } from '../engine/reactive';
|
|
4
|
+
import { DisplayObject, ComponentInstance } from './DisplayObject';
|
|
5
|
+
import { effect, Signal } from '@signe/reactive';
|
|
6
6
|
|
|
7
7
|
const EVENTS = [
|
|
8
8
|
'bounce-x-end',
|
|
@@ -28,6 +28,21 @@ const EVENTS = [
|
|
|
28
28
|
'zoomed-end'
|
|
29
29
|
]
|
|
30
30
|
|
|
31
|
+
export interface ViewportProps extends Props {
|
|
32
|
+
screenWidth?: number;
|
|
33
|
+
screenHeight?: number;
|
|
34
|
+
worldWidth?: number;
|
|
35
|
+
worldHeight?: number;
|
|
36
|
+
clamp?: boolean | {
|
|
37
|
+
left?: number;
|
|
38
|
+
right?: number;
|
|
39
|
+
top?: number;
|
|
40
|
+
bottom?: number;
|
|
41
|
+
};
|
|
42
|
+
context?: any;
|
|
43
|
+
[key: string]: any;
|
|
44
|
+
}
|
|
45
|
+
|
|
31
46
|
export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
32
47
|
private tickSubscription: Subscription
|
|
33
48
|
overrideProps = ['wheel']
|
|
@@ -48,16 +63,20 @@ export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
|
48
63
|
onInit(props) {
|
|
49
64
|
super.onInit(props)
|
|
50
65
|
for (let event of EVENTS) {
|
|
51
|
-
|
|
52
|
-
if (props[camelCaseEvent]) {
|
|
53
|
-
this.on(event, props[camelCaseEvent])
|
|
54
|
-
}
|
|
66
|
+
if (props[event]) this.on(event, props[event])
|
|
55
67
|
}
|
|
56
68
|
}
|
|
57
69
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Called when the component is mounted to the scene graph.
|
|
72
|
+
* Initializes viewport settings and subscriptions.
|
|
73
|
+
* @param {Element<CanvasViewport>} element - The element being mounted. Its `props` property (of type ViewportProps) contains component properties and context.
|
|
74
|
+
* @param {number} [index] - The index of the component among its siblings.
|
|
75
|
+
*/
|
|
76
|
+
async onMount(element: Element<CanvasViewport>, index?: number): Promise<void> {
|
|
77
|
+
await super.onMount(element, index);
|
|
78
|
+
const { props } = element;
|
|
79
|
+
const { tick, app, canvasSize } = props.context;
|
|
61
80
|
let isDragging = false
|
|
62
81
|
|
|
63
82
|
effect(() => {
|
|
@@ -65,18 +84,26 @@ export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
|
65
84
|
this.screenHeight = canvasSize().height
|
|
66
85
|
})
|
|
67
86
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
87
|
+
effect(() => {
|
|
88
|
+
const _app = app()
|
|
89
|
+
if (!_app) return
|
|
90
|
+
|
|
91
|
+
const renderer = _app.renderer
|
|
92
|
+
|
|
93
|
+
renderer.events.domElement.addEventListener(
|
|
94
|
+
'wheel',
|
|
95
|
+
this.input.wheelFunction
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
this.options.events = renderer.events
|
|
99
|
+
})
|
|
73
100
|
|
|
74
101
|
this.tickSubscription = tick.observable.subscribe(({ value }) => {
|
|
75
102
|
this.update(value.timestamp)
|
|
76
103
|
})
|
|
77
104
|
|
|
78
105
|
element.props.context.viewport = this
|
|
79
|
-
this.updateViewportSettings(
|
|
106
|
+
this.updateViewportSettings(props)
|
|
80
107
|
}
|
|
81
108
|
|
|
82
109
|
onUpdate(props) {
|
|
@@ -97,15 +124,11 @@ export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
|
97
124
|
if (props.worldHeight !== undefined) {
|
|
98
125
|
this.worldHeight = props.worldHeight
|
|
99
126
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// } else {
|
|
104
|
-
// this.drag(props.drag)
|
|
105
|
-
// }
|
|
106
|
-
// }
|
|
127
|
+
if (props.drag) {
|
|
128
|
+
this.drag(props.drag)
|
|
129
|
+
}
|
|
107
130
|
if (props.clamp) {
|
|
108
|
-
this.clamp(props.clamp)
|
|
131
|
+
this.clamp(props.clamp.value ?? props.clamp)
|
|
109
132
|
}
|
|
110
133
|
if (props.wheel) {
|
|
111
134
|
if (props.wheel === true) {
|
|
@@ -130,30 +153,23 @@ export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
|
130
153
|
}
|
|
131
154
|
}
|
|
132
155
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Called when the component is about to be destroyed.
|
|
158
|
+
* Unsubscribes from the tick observable.
|
|
159
|
+
* @param {Element<any>} parent - The parent element.
|
|
160
|
+
* @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
|
|
161
|
+
*/
|
|
162
|
+
async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {
|
|
163
|
+
const _afterDestroy = async () => {
|
|
164
|
+
this.tickSubscription.unsubscribe()
|
|
165
|
+
afterDestroy()
|
|
166
|
+
}
|
|
167
|
+
await super.onDestroy(parent, _afterDestroy);
|
|
136
168
|
}
|
|
137
169
|
}
|
|
138
170
|
|
|
139
|
-
export interface CanvasViewport extends PixiViewport { }
|
|
140
|
-
|
|
141
171
|
registerComponent('Viewport', CanvasViewport)
|
|
142
172
|
|
|
143
|
-
export interface ViewportProps {
|
|
144
|
-
screenWidth?: number;
|
|
145
|
-
screenHeight?: number;
|
|
146
|
-
worldWidth?: number;
|
|
147
|
-
worldHeight?: number;
|
|
148
|
-
clamp?: boolean | {
|
|
149
|
-
left?: number;
|
|
150
|
-
right?: number;
|
|
151
|
-
top?: number;
|
|
152
|
-
bottom?: number;
|
|
153
|
-
};
|
|
154
|
-
[key: string]: any;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
173
|
export function Viewport(props: ViewportProps) {
|
|
158
174
|
return createComponent('Viewport', props);
|
|
159
175
|
}
|
package/src/components/index.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
export { Canvas } from './Canvas'
|
|
2
2
|
export { Container } from './Container'
|
|
3
|
-
export { Graphics, Rect, Circle, Ellipse, Triangle, Svg
|
|
3
|
+
export { Graphics, Rect, Circle, Ellipse, Triangle, Svg } from './Graphic'
|
|
4
|
+
export { Mesh } from './Mesh'
|
|
4
5
|
export { Scene } from './Scene'
|
|
5
6
|
export { ParticlesEmitter } from './ParticleEmitter'
|
|
6
7
|
export { Sprite } from './Sprite'
|
|
8
|
+
export { Video } from './Video'
|
|
7
9
|
export { Text } from './Text'
|
|
8
|
-
export { TiledMap } from './Tilemap'
|
|
9
10
|
export { TilingSprite } from './TilingSprite'
|
|
10
11
|
export { Viewport } from './Viewport'
|
|
11
|
-
export { ImageMap } from './DrawMap'
|
|
12
12
|
export { NineSliceSprite } from './NineSliceSprite'
|
|
13
|
-
export { ComponentInstance } from './DisplayObject'
|
|
13
|
+
export { type ComponentInstance } from './DisplayObject'
|
|
14
|
+
export { DOMContainer } from './DOMContainer'
|
|
15
|
+
export { DOMElement } from './DOMElement'
|
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
import * as PIXI from "pixi.js";
|
|
2
2
|
import { SignalOrPrimitive } from ".";
|
|
3
|
+
import { DragProps } from "../../directives/Drag";
|
|
4
|
+
import { ViewportFollowProps } from "../../directives/ViewportFollow";
|
|
3
5
|
|
|
4
6
|
export type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse';
|
|
5
7
|
export type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
|
|
6
8
|
export type AlignContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
|
|
7
9
|
export type Size = number | `${number}%`
|
|
8
10
|
export type EdgeSize = SignalOrPrimitive<Size | [Size, Size] | [Size, Size, Size, Size]>
|
|
11
|
+
export type ObjectFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
|
|
12
|
+
export type ObjectPosition = string;
|
|
13
|
+
export type TransformOrigin = string;
|
|
14
|
+
export type PositionType = 'relative' | 'absolute' | 'static';
|
|
9
15
|
|
|
10
16
|
export interface DisplayObjectProps {
|
|
17
|
+
attach?: any;
|
|
11
18
|
ref?: string;
|
|
12
19
|
x?: SignalOrPrimitive<number>;
|
|
13
20
|
y?: SignalOrPrimitive<number>;
|
|
14
21
|
width?: SignalOrPrimitive<Size>;
|
|
15
22
|
height?: SignalOrPrimitive<Size>;
|
|
23
|
+
minWidth?: SignalOrPrimitive<Size>;
|
|
24
|
+
minHeight?: SignalOrPrimitive<Size>;
|
|
25
|
+
maxWidth?: SignalOrPrimitive<Size>;
|
|
26
|
+
maxHeight?: SignalOrPrimitive<Size>;
|
|
27
|
+
aspectRatio?: SignalOrPrimitive<number>;
|
|
28
|
+
flexGrow?: SignalOrPrimitive<number>;
|
|
29
|
+
flexShrink?: SignalOrPrimitive<number>;
|
|
30
|
+
flexBasis?: SignalOrPrimitive<Size>;
|
|
31
|
+
rowGap?: SignalOrPrimitive<number>;
|
|
32
|
+
columnGap?: SignalOrPrimitive<number>;
|
|
33
|
+
positionType?: PositionType;
|
|
34
|
+
top?: SignalOrPrimitive<Size>;
|
|
35
|
+
right?: SignalOrPrimitive<Size>;
|
|
36
|
+
bottom?: SignalOrPrimitive<Size>;
|
|
37
|
+
left?: SignalOrPrimitive<Size>;
|
|
38
|
+
objectFit?: ObjectFit;
|
|
39
|
+
objectPosition?: ObjectPosition;
|
|
40
|
+
transformOrigin?: TransformOrigin;
|
|
16
41
|
children?: any[];
|
|
17
42
|
flexDirection?: FlexDirection;
|
|
18
43
|
justifyContent?: JustifyContent;
|
|
@@ -36,6 +61,11 @@ export interface DisplayObjectProps {
|
|
|
36
61
|
blendMode?: SignalOrPrimitive<PIXI.BLEND_MODES>;
|
|
37
62
|
blur?: SignalOrPrimitive<number>;
|
|
38
63
|
|
|
64
|
+
// Directives
|
|
65
|
+
drag?: DragProps;
|
|
66
|
+
viewportFollow?: ViewportFollowProps;
|
|
67
|
+
|
|
68
|
+
// Events
|
|
39
69
|
click?: PIXI.FederatedEventHandler;
|
|
40
70
|
mousedown?: PIXI.FederatedEventHandler;
|
|
41
71
|
mouseenter?: PIXI.FederatedEventHandler;
|