canvasengine 2.0.0-beta.5 → 2.0.0-beta.50
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/components/Button.d.ts +185 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Canvas.d.ts +17 -0
- package/dist/components/Canvas.d.ts.map +1 -0
- package/dist/components/Container.d.ts +86 -0
- package/dist/components/Container.d.ts.map +1 -0
- package/dist/components/DOMContainer.d.ts +98 -0
- package/dist/components/DOMContainer.d.ts.map +1 -0
- package/dist/components/DOMElement.d.ts +54 -0
- package/dist/components/DOMElement.d.ts.map +1 -0
- package/dist/components/DOMSprite.d.ts +127 -0
- package/dist/components/DOMSprite.d.ts.map +1 -0
- package/dist/components/DisplayObject.d.ts +94 -0
- package/dist/components/DisplayObject.d.ts.map +1 -0
- package/dist/components/FocusContainer.d.ts +129 -0
- package/dist/components/FocusContainer.d.ts.map +1 -0
- package/dist/components/Graphic.d.ts +64 -0
- package/dist/components/Graphic.d.ts.map +1 -0
- package/dist/components/Joystick.d.ts +36 -0
- package/dist/components/Joystick.d.ts.map +1 -0
- package/dist/components/Mesh.d.ts +208 -0
- package/dist/components/Mesh.d.ts.map +1 -0
- package/dist/components/NineSliceSprite.d.ts +16 -0
- package/dist/components/NineSliceSprite.d.ts.map +1 -0
- package/dist/components/ParticleEmitter.d.ts +4 -0
- package/dist/components/ParticleEmitter.d.ts.map +1 -0
- package/dist/components/Scene.d.ts +2 -0
- package/dist/components/Scene.d.ts.map +1 -0
- package/dist/components/Sprite.d.ts +242 -0
- package/dist/components/Sprite.d.ts.map +1 -0
- package/dist/components/Text.d.ts +25 -0
- package/dist/components/Text.d.ts.map +1 -0
- package/dist/components/TilingSprite.d.ts +17 -0
- package/dist/components/TilingSprite.d.ts.map +1 -0
- package/dist/components/Video.d.ts +14 -0
- package/dist/components/Video.d.ts.map +1 -0
- package/dist/components/Viewport.d.ts +121 -0
- package/dist/components/Viewport.d.ts.map +1 -0
- package/dist/components/index.d.ts +20 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/types/DisplayObject.d.ts +106 -0
- package/dist/components/types/DisplayObject.d.ts.map +1 -0
- package/dist/components/types/MouseEvent.d.ts +4 -0
- package/dist/components/types/MouseEvent.d.ts.map +1 -0
- package/dist/components/types/Spritesheet.d.ts +248 -0
- package/dist/components/types/Spritesheet.d.ts.map +1 -0
- package/dist/components/types/index.d.ts +4 -0
- package/dist/components/types/index.d.ts.map +1 -0
- package/dist/directives/Controls.d.ts +112 -0
- package/dist/directives/Controls.d.ts.map +1 -0
- package/dist/directives/ControlsBase.d.ts +199 -0
- package/dist/directives/ControlsBase.d.ts.map +1 -0
- package/dist/directives/Drag.d.ts +69 -0
- package/dist/directives/Drag.d.ts.map +1 -0
- package/dist/directives/Flash.d.ts +116 -0
- package/dist/directives/Flash.d.ts.map +1 -0
- package/dist/directives/FocusNavigation.d.ts +52 -0
- package/dist/directives/FocusNavigation.d.ts.map +1 -0
- package/dist/directives/GamepadControls.d.ts +224 -0
- package/dist/directives/GamepadControls.d.ts.map +1 -0
- package/dist/directives/JoystickControls.d.ts +171 -0
- package/dist/directives/JoystickControls.d.ts.map +1 -0
- package/dist/directives/KeyboardControls.d.ts +219 -0
- package/dist/directives/KeyboardControls.d.ts.map +1 -0
- package/dist/directives/Scheduler.d.ts +35 -0
- package/dist/directives/Scheduler.d.ts.map +1 -0
- package/dist/directives/Shake.d.ts +98 -0
- package/dist/directives/Shake.d.ts.map +1 -0
- package/dist/directives/Sound.d.ts +25 -0
- package/dist/directives/Sound.d.ts.map +1 -0
- package/dist/directives/Transition.d.ts +10 -0
- package/dist/directives/Transition.d.ts.map +1 -0
- package/dist/directives/ViewportCull.d.ts +11 -0
- package/dist/directives/ViewportCull.d.ts.map +1 -0
- package/dist/directives/ViewportFollow.d.ts +18 -0
- package/dist/directives/ViewportFollow.d.ts.map +1 -0
- package/dist/directives/index.d.ts +13 -0
- package/dist/directives/index.d.ts.map +1 -0
- package/dist/engine/FocusManager.d.ts +174 -0
- package/dist/engine/FocusManager.d.ts.map +1 -0
- package/dist/engine/animation.d.ts +72 -0
- package/dist/engine/animation.d.ts.map +1 -0
- package/dist/engine/bootstrap.d.ts +48 -0
- package/dist/engine/bootstrap.d.ts.map +1 -0
- package/dist/engine/directive.d.ts +13 -0
- package/dist/engine/directive.d.ts.map +1 -0
- package/dist/engine/reactive.d.ts +134 -0
- package/dist/engine/reactive.d.ts.map +1 -0
- package/dist/engine/signal.d.ts +71 -0
- package/dist/engine/signal.d.ts.map +1 -0
- package/dist/engine/trigger.d.ts +54 -0
- package/dist/engine/trigger.d.ts.map +1 -0
- package/dist/engine/utils.d.ts +89 -0
- package/dist/engine/utils.d.ts.map +1 -0
- package/dist/hooks/addContext.d.ts +2 -0
- package/dist/hooks/addContext.d.ts.map +1 -0
- package/dist/hooks/useFocus.d.ts +60 -0
- package/dist/hooks/useFocus.d.ts.map +1 -0
- package/dist/hooks/useProps.d.ts +42 -0
- package/dist/hooks/useProps.d.ts.map +1 -0
- package/dist/hooks/useRef.d.ts +4 -0
- package/dist/hooks/useRef.d.ts.map +1 -0
- package/dist/index-DaGekQUW.js +2218 -0
- package/dist/index-DaGekQUW.js.map +1 -0
- package/dist/index.d.ts +19 -1099
- package/dist/index.d.ts.map +1 -0
- package/dist/index.global.js +5 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +11749 -2901
- package/dist/index.js.map +1 -1
- package/dist/utils/Ease.d.ts +17 -0
- package/dist/utils/Ease.d.ts.map +1 -0
- package/dist/utils/GlobalAssetLoader.d.ts +141 -0
- package/dist/utils/GlobalAssetLoader.d.ts.map +1 -0
- package/dist/utils/RadialGradient.d.ts +57 -0
- package/dist/utils/RadialGradient.d.ts.map +1 -0
- package/dist/utils/functions.d.ts +2 -0
- package/dist/utils/functions.d.ts.map +1 -0
- package/dist/utils/tabindex.d.ts +16 -0
- package/dist/utils/tabindex.d.ts.map +1 -0
- package/package.json +13 -7
- package/src/components/Button.ts +399 -0
- package/src/components/Canvas.ts +62 -46
- package/src/components/Container.ts +21 -2
- package/src/components/DOMContainer.ts +379 -0
- package/src/components/DOMElement.ts +556 -0
- package/src/components/DOMSprite.ts +1040 -0
- package/src/components/DisplayObject.ts +392 -201
- package/src/components/FocusContainer.ts +368 -0
- package/src/components/Graphic.ts +227 -66
- package/src/components/Joystick.ts +363 -0
- 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 +297 -31
- package/src/components/Text.ts +125 -18
- package/src/components/Video.ts +2 -2
- package/src/components/Viewport.ts +118 -63
- package/src/components/index.ts +9 -2
- package/src/components/types/DisplayObject.ts +41 -4
- package/src/components/types/Spritesheet.ts +0 -118
- package/src/directives/Controls.ts +254 -0
- package/src/directives/ControlsBase.ts +267 -0
- package/src/directives/Drag.ts +357 -52
- package/src/directives/Flash.ts +419 -0
- package/src/directives/FocusNavigation.ts +113 -0
- package/src/directives/GamepadControls.ts +537 -0
- package/src/directives/JoystickControls.ts +396 -0
- package/src/directives/KeyboardControls.ts +85 -430
- package/src/directives/Scheduler.ts +12 -4
- package/src/directives/Shake.ts +298 -0
- package/src/directives/Sound.ts +94 -31
- package/src/directives/ViewportFollow.ts +40 -9
- package/src/directives/index.ts +12 -6
- package/src/engine/FocusManager.ts +510 -0
- package/src/engine/animation.ts +175 -21
- package/src/engine/bootstrap.ts +93 -3
- package/src/engine/directive.ts +4 -4
- package/src/engine/reactive.ts +901 -161
- package/src/engine/signal.ts +113 -25
- package/src/engine/trigger.ts +34 -7
- package/src/engine/utils.ts +19 -3
- package/src/hooks/useFocus.ts +91 -0
- package/src/hooks/useProps.ts +1 -1
- package/src/index.ts +8 -2
- package/src/types/pixi-cull.d.ts +7 -0
- package/src/utils/GlobalAssetLoader.ts +257 -0
- package/src/utils/functions.ts +7 -0
- package/src/utils/tabindex.ts +70 -0
- package/testing/index.ts +35 -4
- package/tsconfig.json +18 -0
- package/vite.config.ts +39 -0
package/src/components/Text.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
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
|
+
import { Howl } from "howler";
|
|
7
8
|
|
|
8
9
|
enum TextEffect {
|
|
9
10
|
Typewriter = "typewriter",
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
interface TextProps extends DisplayObjectProps {
|
|
13
|
+
export interface TextProps extends DisplayObjectProps {
|
|
13
14
|
text?: string;
|
|
14
15
|
style?: Partial<TextStyle>;
|
|
15
16
|
color?: string;
|
|
@@ -20,7 +21,13 @@ interface TextProps extends DisplayObjectProps {
|
|
|
20
21
|
start?: () => void;
|
|
21
22
|
onComplete?: () => void;
|
|
22
23
|
skip?: () => void;
|
|
24
|
+
sound?: {
|
|
25
|
+
src: string;
|
|
26
|
+
volume?: number;
|
|
27
|
+
rate?: number;
|
|
28
|
+
};
|
|
23
29
|
};
|
|
30
|
+
context?: any; // Ensure context is available, ideally typed from a base prop or injected
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
class CanvasText extends DisplayObject(PixiText) {
|
|
@@ -31,10 +38,19 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
31
38
|
private _wordWrapWidth: number = 0;
|
|
32
39
|
private typewriterOptions: any = {};
|
|
33
40
|
private skipSignal?: () => void;
|
|
41
|
+
private typewriterSound?: Howl;
|
|
42
|
+
private lastSoundTime: number = 0;
|
|
43
|
+
private soundDuration: number = 0; // Duration of the sound in milliseconds
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Called when the component is mounted to the scene graph.
|
|
47
|
+
* Initializes the typewriter effect if configured.
|
|
48
|
+
* @param {Element<CanvasText>} element - The element being mounted with parent and props.
|
|
49
|
+
* @param {number} [index] - The index of the component among its siblings.
|
|
50
|
+
*/
|
|
51
|
+
async onMount(element: Element<any>, index?: number): Promise<void> {
|
|
52
|
+
const { props } = element;
|
|
53
|
+
await super.onMount(element, index);
|
|
38
54
|
const tick: Signal = props.context.tick;
|
|
39
55
|
|
|
40
56
|
if (props.text && props.typewriter) {
|
|
@@ -44,12 +60,18 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
44
60
|
// Set typewriter options
|
|
45
61
|
if (props.typewriter) {
|
|
46
62
|
this.typewriterOptions = props.typewriter;
|
|
47
|
-
if (this.typewriterOptions.skip) {
|
|
63
|
+
if (this.typewriterOptions.skip && isTrigger(this.typewriterOptions.skip)) {
|
|
48
64
|
on(this.typewriterOptions.skip, () => {
|
|
49
65
|
this.skipTypewriter();
|
|
50
66
|
});
|
|
51
67
|
}
|
|
68
|
+
// Initialize typewriter sound if configured
|
|
69
|
+
if (this.typewriterOptions.sound) {
|
|
70
|
+
this.initializeTypewriterSound();
|
|
71
|
+
}
|
|
52
72
|
}
|
|
73
|
+
// Update layout after initializing typewriter
|
|
74
|
+
this.updateLayout();
|
|
53
75
|
}
|
|
54
76
|
this.subscriptionTick = tick.observable.subscribe(() => {
|
|
55
77
|
if (props.typewriter) {
|
|
@@ -63,15 +85,21 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
63
85
|
if (props.typewriter) {
|
|
64
86
|
if (props.typewriter) {
|
|
65
87
|
this.typewriterOptions = props.typewriter;
|
|
88
|
+
// Reinitialize sound if sound configuration changed
|
|
89
|
+
if (props.typewriter.sound) {
|
|
90
|
+
this.initializeTypewriterSound();
|
|
91
|
+
}
|
|
66
92
|
}
|
|
67
93
|
}
|
|
68
|
-
if (props.text) {
|
|
69
|
-
this.text = props.text;
|
|
94
|
+
if (props.text !== undefined) {
|
|
95
|
+
this.text = ''+props.text;
|
|
70
96
|
}
|
|
71
97
|
if (props.text !== undefined && props.text !== this.fullText && this.fullProps.typewriter) {
|
|
72
98
|
this.text = "";
|
|
73
99
|
this.currentIndex = 0;
|
|
74
100
|
this.fullText = props.text;
|
|
101
|
+
// Update layout after resetting typewriter
|
|
102
|
+
this.updateLayout();
|
|
75
103
|
}
|
|
76
104
|
if (props.style) {
|
|
77
105
|
for (const key in props.style) {
|
|
@@ -90,6 +118,59 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
90
118
|
if (props.fontFamily) {
|
|
91
119
|
this.style.fontFamily = props.fontFamily;
|
|
92
120
|
}
|
|
121
|
+
|
|
122
|
+
// Use the centralized layout update method
|
|
123
|
+
this.updateLayout();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
get onCompleteCallback() {
|
|
127
|
+
return this.typewriterOptions.onComplete;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Initializes the typewriter sound effect using Howler.
|
|
132
|
+
* Creates a Howl instance with the configured sound settings.
|
|
133
|
+
* Calculates the sound duration to prevent overlapping sounds.
|
|
134
|
+
*/
|
|
135
|
+
private initializeTypewriterSound() {
|
|
136
|
+
if (!this.typewriterOptions.sound?.src) return;
|
|
137
|
+
|
|
138
|
+
this.typewriterSound = new Howl({
|
|
139
|
+
src: [this.typewriterOptions.sound.src],
|
|
140
|
+
volume: this.typewriterOptions.sound.volume ?? 0.5,
|
|
141
|
+
rate: this.typewriterOptions.sound.rate ?? 1.0,
|
|
142
|
+
preload: true,
|
|
143
|
+
onload: () => {
|
|
144
|
+
// Calculate sound duration in milliseconds
|
|
145
|
+
if (this.typewriterSound) {
|
|
146
|
+
const duration = this.typewriterSound.duration();
|
|
147
|
+
const rate = this.typewriterOptions.sound?.rate ?? 1.0;
|
|
148
|
+
this.soundDuration = (duration / rate) * 1000;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Plays the typewriter sound with duration-based cooldown to prevent overlapping sounds.
|
|
156
|
+
* @param {number} currentTime - The current timestamp to check against sound duration.
|
|
157
|
+
*/
|
|
158
|
+
private playTypewriterSound(currentTime: number) {
|
|
159
|
+
if (!this.typewriterSound || !this.typewriterOptions.sound) return;
|
|
160
|
+
|
|
161
|
+
// Check if enough time has passed since the last sound play
|
|
162
|
+
// Use the actual sound duration to prevent overlap
|
|
163
|
+
if (this.soundDuration > 0 && currentTime - this.lastSoundTime < this.soundDuration) return;
|
|
164
|
+
|
|
165
|
+
this.typewriterSound.play();
|
|
166
|
+
this.lastSoundTime = currentTime;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Updates the layout properties of the text component.
|
|
171
|
+
* This method ensures consistent width, height and word wrap behavior.
|
|
172
|
+
*/
|
|
173
|
+
private updateLayout() {
|
|
93
174
|
if (this._wordWrapWidth) {
|
|
94
175
|
this.setWidth(this._wordWrapWidth);
|
|
95
176
|
} else {
|
|
@@ -98,10 +179,6 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
98
179
|
this.setHeight(this.height);
|
|
99
180
|
}
|
|
100
181
|
|
|
101
|
-
get onCompleteCallback() {
|
|
102
|
-
return this.typewriterOptions.onComplete;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
182
|
private typewriterEffect() {
|
|
106
183
|
if (this.currentIndex < this.fullText.length) {
|
|
107
184
|
const nextIndex = Math.min(
|
|
@@ -111,6 +188,14 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
111
188
|
this.text = this.fullText.slice(0, nextIndex);
|
|
112
189
|
this.currentIndex = nextIndex;
|
|
113
190
|
|
|
191
|
+
// Play typewriter sound if configured
|
|
192
|
+
if (this.typewriterOptions.sound) {
|
|
193
|
+
this.playTypewriterSound(Date.now());
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Update layout after text change to maintain proper word wrap and dimensions
|
|
197
|
+
this.updateLayout();
|
|
198
|
+
|
|
114
199
|
// Check if typewriter effect is complete
|
|
115
200
|
if (
|
|
116
201
|
this.currentIndex === this.fullText.length &&
|
|
@@ -128,15 +213,37 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
128
213
|
}
|
|
129
214
|
this.text = this.fullText;
|
|
130
215
|
this.currentIndex = this.fullText.length;
|
|
216
|
+
|
|
217
|
+
// Update layout after setting full text to maintain proper word wrap and dimensions
|
|
218
|
+
this.updateLayout();
|
|
131
219
|
}
|
|
132
220
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
221
|
+
/**
|
|
222
|
+
* Called when the component is about to be destroyed.
|
|
223
|
+
* Unsubscribes from the tick observable and cleans up sound resources.
|
|
224
|
+
* @param {Element<any>} parent - The parent element.
|
|
225
|
+
* @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
|
|
226
|
+
*/
|
|
227
|
+
async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {
|
|
228
|
+
const _afterDestroy = async () => {
|
|
229
|
+
if (this.subscriptionTick) {
|
|
230
|
+
this.subscriptionTick.unsubscribe();
|
|
231
|
+
}
|
|
232
|
+
// Clean up typewriter sound
|
|
233
|
+
if (this.typewriterSound) {
|
|
234
|
+
this.typewriterSound.stop();
|
|
235
|
+
this.typewriterSound.unload();
|
|
236
|
+
this.typewriterSound = undefined;
|
|
237
|
+
}
|
|
238
|
+
if (afterDestroy) {
|
|
239
|
+
afterDestroy();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
await super.onDestroy(parent, _afterDestroy);
|
|
136
243
|
}
|
|
137
244
|
}
|
|
138
245
|
|
|
139
|
-
interface CanvasText extends PixiText {}
|
|
246
|
+
// interface CanvasText extends PixiText {} // Removed as it's redundant and causes type conflicts
|
|
140
247
|
|
|
141
248
|
registerComponent("Text", CanvasText);
|
|
142
249
|
|
package/src/components/Video.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Sprite } from "./Sprite";
|
|
|
5
5
|
import { effect, Signal, signal } from "@signe/reactive";
|
|
6
6
|
|
|
7
7
|
interface VideoProps {
|
|
8
|
-
|
|
8
|
+
src: string;
|
|
9
9
|
paused?: boolean;
|
|
10
10
|
loop?: boolean;
|
|
11
11
|
muted?: boolean;
|
|
@@ -87,7 +87,7 @@ export function Video(props: VideoProps) {
|
|
|
87
87
|
|
|
88
88
|
return h(Sprite, {
|
|
89
89
|
...props,
|
|
90
|
-
image: props.
|
|
90
|
+
image: props.src,
|
|
91
91
|
loader: {
|
|
92
92
|
onComplete: (texture) => {
|
|
93
93
|
const source = texture.source.resource
|
|
@@ -1,8 +1,9 @@
|
|
|
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
|
+
import { Graphics, Container, ContainerChild, IRenderLayer } from 'pixi.js';
|
|
6
7
|
|
|
7
8
|
const EVENTS = [
|
|
8
9
|
'bounce-x-end',
|
|
@@ -28,55 +29,102 @@ const EVENTS = [
|
|
|
28
29
|
'zoomed-end'
|
|
29
30
|
]
|
|
30
31
|
|
|
31
|
-
export
|
|
32
|
+
export interface ViewportProps extends Props {
|
|
33
|
+
screenWidth?: number;
|
|
34
|
+
screenHeight?: number;
|
|
35
|
+
worldWidth?: number;
|
|
36
|
+
worldHeight?: number;
|
|
37
|
+
clamp?: boolean | {
|
|
38
|
+
left?: number;
|
|
39
|
+
right?: number;
|
|
40
|
+
top?: number;
|
|
41
|
+
bottom?: number;
|
|
42
|
+
};
|
|
43
|
+
context?: any;
|
|
44
|
+
[key: string]: any;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class CanvasViewport extends DisplayObject(Container) {
|
|
32
48
|
private tickSubscription: Subscription
|
|
33
49
|
overrideProps = ['wheel']
|
|
50
|
+
#mask: Graphics
|
|
51
|
+
public viewport: PixiViewport
|
|
34
52
|
|
|
35
53
|
constructor() {
|
|
54
|
+
super()
|
|
36
55
|
const defaultOptions = {
|
|
37
56
|
noTicker: true,
|
|
38
57
|
events: {
|
|
39
58
|
domElement: {
|
|
40
|
-
addEventListener: () => {}
|
|
59
|
+
addEventListener: () => { }
|
|
41
60
|
}
|
|
42
61
|
},
|
|
43
62
|
}
|
|
44
63
|
// @ts-ignore
|
|
45
|
-
|
|
64
|
+
this.viewport = new PixiViewport(defaultOptions)
|
|
65
|
+
super.addChild(this.viewport)
|
|
66
|
+
|
|
67
|
+
this.#mask = new Graphics()
|
|
68
|
+
super.addChild(this.#mask)
|
|
69
|
+
this.mask = this.#mask
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
addChild<U extends any[]>(...children: U): U[0] {
|
|
73
|
+
return this.viewport.addChild(...children)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
addChildAt<T extends ContainerChild | IRenderLayer>(child: T, index: number): T {
|
|
77
|
+
return this.viewport.addChildAt(child, index) as T
|
|
46
78
|
}
|
|
47
79
|
|
|
48
80
|
onInit(props) {
|
|
49
81
|
super.onInit(props)
|
|
50
82
|
for (let event of EVENTS) {
|
|
51
|
-
|
|
52
|
-
if (props[camelCaseEvent]) {
|
|
53
|
-
this.on(event, props[camelCaseEvent])
|
|
54
|
-
}
|
|
83
|
+
if (props[event]) this.viewport.on(event, props[event])
|
|
55
84
|
}
|
|
56
85
|
}
|
|
57
86
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Called when the component is mounted to the scene graph.
|
|
89
|
+
* Initializes viewport settings and subscriptions.
|
|
90
|
+
* @param {Element<CanvasViewport>} element - The element being mounted. Its `props` property (of type ViewportProps) contains component properties and context.
|
|
91
|
+
* @param {number} [index] - The index of the component among its siblings.
|
|
92
|
+
*/
|
|
93
|
+
async onMount(element: Element<any>, index?: number): Promise<void> {
|
|
94
|
+
element.props.context.viewport = this.viewport
|
|
95
|
+
await super.onMount(element, index);
|
|
96
|
+
const { props } = element;
|
|
97
|
+
const { tick, app, canvasSize } = props.context;
|
|
98
|
+
|
|
99
|
+
effect(() => {
|
|
100
|
+
if (props.screenWidth === undefined) {
|
|
101
|
+
this.viewport.screenWidth = canvasSize().width
|
|
102
|
+
}
|
|
103
|
+
if (props.screenHeight === undefined) {
|
|
104
|
+
this.viewport.screenHeight = canvasSize().height
|
|
105
|
+
}
|
|
106
|
+
this.updateMask()
|
|
107
|
+
})
|
|
108
|
+
|
|
63
109
|
effect(() => {
|
|
64
|
-
|
|
65
|
-
|
|
110
|
+
const _app = app()
|
|
111
|
+
if (!_app) return
|
|
112
|
+
|
|
113
|
+
const renderer = _app.renderer
|
|
114
|
+
|
|
115
|
+
renderer.events.domElement.addEventListener(
|
|
116
|
+
'wheel',
|
|
117
|
+
this.viewport.input.wheelFunction
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
this.viewport.options.events = renderer.events
|
|
66
121
|
})
|
|
67
122
|
|
|
68
|
-
renderer.events.domElement.addEventListener(
|
|
69
|
-
'wheel',
|
|
70
|
-
this.input.wheelFunction
|
|
71
|
-
);
|
|
72
|
-
this.options.events = renderer.events
|
|
73
|
-
|
|
74
123
|
this.tickSubscription = tick.observable.subscribe(({ value }) => {
|
|
75
|
-
this.update(value.
|
|
124
|
+
this.viewport.update(value.deltaTime)
|
|
76
125
|
})
|
|
77
126
|
|
|
78
|
-
|
|
79
|
-
this.updateViewportSettings(element.props)
|
|
127
|
+
this.updateViewportSettings(props)
|
|
80
128
|
}
|
|
81
129
|
|
|
82
130
|
onUpdate(props) {
|
|
@@ -86,74 +134,81 @@ export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
|
86
134
|
|
|
87
135
|
private updateViewportSettings(props) {
|
|
88
136
|
if (props.screenWidth !== undefined) {
|
|
89
|
-
this.screenWidth = props.screenWidth
|
|
137
|
+
this.viewport.screenWidth = props.screenWidth
|
|
90
138
|
}
|
|
91
139
|
if (props.screenHeight !== undefined) {
|
|
92
|
-
this.screenHeight = props.screenHeight
|
|
140
|
+
this.viewport.screenHeight = props.screenHeight
|
|
93
141
|
}
|
|
142
|
+
this.updateMask()
|
|
94
143
|
if (props.worldWidth !== undefined) {
|
|
95
|
-
this.worldWidth = props.worldWidth
|
|
144
|
+
this.viewport.worldWidth = props.worldWidth
|
|
96
145
|
}
|
|
97
146
|
if (props.worldHeight !== undefined) {
|
|
98
|
-
this.worldHeight = props.worldHeight
|
|
147
|
+
this.viewport.worldHeight = props.worldHeight
|
|
148
|
+
}
|
|
149
|
+
if (props.drag) {
|
|
150
|
+
this.viewport.drag(props.drag)
|
|
99
151
|
}
|
|
100
|
-
// if (props.drag) {
|
|
101
|
-
// if (props.drag === true) {
|
|
102
|
-
|
|
103
|
-
// } else {
|
|
104
|
-
// this.drag(props.drag)
|
|
105
|
-
// }
|
|
106
|
-
// }
|
|
107
152
|
if (props.clamp) {
|
|
108
|
-
this.clamp(props.clamp)
|
|
153
|
+
this.viewport.clamp(props.clamp.value ?? props.clamp)
|
|
109
154
|
}
|
|
110
155
|
if (props.wheel) {
|
|
111
156
|
if (props.wheel === true) {
|
|
112
|
-
this.wheel()
|
|
157
|
+
this.viewport.wheel()
|
|
113
158
|
} else {
|
|
114
|
-
this.wheel(props.wheel)
|
|
159
|
+
this.viewport.wheel(props.wheel)
|
|
115
160
|
}
|
|
116
161
|
}
|
|
117
162
|
if (props.decelerate) {
|
|
118
163
|
if (props.decelerate === true) {
|
|
119
|
-
this.decelerate()
|
|
164
|
+
this.viewport.decelerate()
|
|
120
165
|
} else {
|
|
121
|
-
this.decelerate(props.decelerate)
|
|
166
|
+
this.viewport.decelerate(props.decelerate)
|
|
122
167
|
}
|
|
123
168
|
}
|
|
124
169
|
if (props.pinch) {
|
|
125
170
|
if (props.pinch === true) {
|
|
126
|
-
this.pinch()
|
|
171
|
+
this.viewport.pinch()
|
|
127
172
|
} else {
|
|
128
|
-
this.pinch(props.pinch)
|
|
173
|
+
this.viewport.pinch(props.pinch)
|
|
129
174
|
}
|
|
130
175
|
}
|
|
131
176
|
}
|
|
132
177
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
this.
|
|
178
|
+
private updateMask() {
|
|
179
|
+
if (!this.#mask) return
|
|
180
|
+
this.#mask.clear()
|
|
181
|
+
this.#mask.beginFill(0xffffff)
|
|
182
|
+
this.#mask.drawRect(0, 0, this.viewport.screenWidth, this.viewport.screenHeight)
|
|
183
|
+
this.#mask.endFill()
|
|
136
184
|
}
|
|
137
|
-
}
|
|
138
185
|
|
|
139
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Called when the component is about to be destroyed.
|
|
188
|
+
* Unsubscribes from the tick observable.
|
|
189
|
+
* @param {Element<any>} parent - The parent element.
|
|
190
|
+
* @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
|
|
191
|
+
*/
|
|
192
|
+
async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {
|
|
193
|
+
const _afterDestroy = async () => {
|
|
194
|
+
this.tickSubscription.unsubscribe()
|
|
195
|
+
afterDestroy()
|
|
196
|
+
}
|
|
197
|
+
await super.onDestroy(parent, _afterDestroy);
|
|
198
|
+
}
|
|
140
199
|
|
|
141
|
-
|
|
200
|
+
// Proxy methods for viewport plugins
|
|
201
|
+
follow(...args: any[]) {
|
|
202
|
+
return (this.viewport.follow as any)(...args)
|
|
203
|
+
}
|
|
142
204
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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;
|
|
205
|
+
get plugins() {
|
|
206
|
+
return this.viewport.plugins
|
|
207
|
+
}
|
|
155
208
|
}
|
|
156
209
|
|
|
210
|
+
registerComponent('Viewport', CanvasViewport)
|
|
211
|
+
|
|
157
212
|
export function Viewport(props: ViewportProps) {
|
|
158
213
|
return createComponent('Viewport', props);
|
|
159
|
-
}
|
|
214
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
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'
|
|
@@ -9,4 +10,10 @@ export { Text } from './Text'
|
|
|
9
10
|
export { TilingSprite } from './TilingSprite'
|
|
10
11
|
export { Viewport } from './Viewport'
|
|
11
12
|
export { NineSliceSprite } from './NineSliceSprite'
|
|
12
|
-
export { type ComponentInstance } from './DisplayObject'
|
|
13
|
+
export { type ComponentInstance } from './DisplayObject'
|
|
14
|
+
export { DOMContainer } from './DOMContainer'
|
|
15
|
+
export { DOMElement } from './DOMElement'
|
|
16
|
+
export { DOMSprite } from './DOMSprite'
|
|
17
|
+
export { Button, ButtonState, type ButtonProps, type ButtonStyle } from './Button'
|
|
18
|
+
export { Joystick, type JoystickSettings } from './Joystick'
|
|
19
|
+
export { FocusContainer, Navigation, type FocusContainerProps } from './FocusContainer'
|
|
@@ -1,18 +1,47 @@
|
|
|
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";
|
|
5
|
+
import { ShakeProps } from "../../directives/Shake";
|
|
6
|
+
import { FlashProps } from "../../directives/Flash";
|
|
3
7
|
|
|
4
8
|
export type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse';
|
|
5
9
|
export type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
|
|
6
10
|
export type AlignContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
|
|
7
11
|
export type Size = number | `${number}%`
|
|
8
12
|
export type EdgeSize = SignalOrPrimitive<Size | [Size, Size] | [Size, Size, Size, Size]>
|
|
13
|
+
export type ObjectFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
|
|
14
|
+
export type ObjectPosition = string;
|
|
15
|
+
export type TransformOrigin = string;
|
|
16
|
+
export type PositionType = 'relative' | 'absolute' | 'static';
|
|
17
|
+
|
|
18
|
+
export type ObservablePointSignal = [number, number] | SignalOrPrimitive<[number, number]> | { x: number, y: number } | SignalOrPrimitive<{ x: number, y: number }>;
|
|
9
19
|
|
|
10
20
|
export interface DisplayObjectProps {
|
|
21
|
+
attach?: any;
|
|
11
22
|
ref?: string;
|
|
12
23
|
x?: SignalOrPrimitive<number>;
|
|
13
24
|
y?: SignalOrPrimitive<number>;
|
|
14
25
|
width?: SignalOrPrimitive<Size>;
|
|
15
26
|
height?: SignalOrPrimitive<Size>;
|
|
27
|
+
minWidth?: SignalOrPrimitive<Size>;
|
|
28
|
+
minHeight?: SignalOrPrimitive<Size>;
|
|
29
|
+
maxWidth?: SignalOrPrimitive<Size>;
|
|
30
|
+
maxHeight?: SignalOrPrimitive<Size>;
|
|
31
|
+
aspectRatio?: SignalOrPrimitive<number>;
|
|
32
|
+
flexGrow?: SignalOrPrimitive<number>;
|
|
33
|
+
flexShrink?: SignalOrPrimitive<number>;
|
|
34
|
+
flexBasis?: SignalOrPrimitive<Size>;
|
|
35
|
+
rowGap?: SignalOrPrimitive<number>;
|
|
36
|
+
columnGap?: SignalOrPrimitive<number>;
|
|
37
|
+
positionType?: PositionType;
|
|
38
|
+
top?: SignalOrPrimitive<Size>;
|
|
39
|
+
right?: SignalOrPrimitive<Size>;
|
|
40
|
+
bottom?: SignalOrPrimitive<Size>;
|
|
41
|
+
left?: SignalOrPrimitive<Size>;
|
|
42
|
+
objectFit?: ObjectFit;
|
|
43
|
+
objectPosition?: ObjectPosition;
|
|
44
|
+
transformOrigin?: TransformOrigin;
|
|
16
45
|
children?: any[];
|
|
17
46
|
flexDirection?: FlexDirection;
|
|
18
47
|
justifyContent?: JustifyContent;
|
|
@@ -21,9 +50,9 @@ export interface DisplayObjectProps {
|
|
|
21
50
|
padding?: EdgeSize;
|
|
22
51
|
border?: EdgeSize;
|
|
23
52
|
absolute?: SignalOrPrimitive<boolean>;
|
|
24
|
-
scale?:
|
|
25
|
-
anchor?:
|
|
26
|
-
skew?:
|
|
53
|
+
scale?: ObservablePointSignal | number;
|
|
54
|
+
anchor?: ObservablePointSignal;
|
|
55
|
+
skew?: ObservablePointSignal;
|
|
27
56
|
tint?: SignalOrPrimitive<number>;
|
|
28
57
|
rotation?: SignalOrPrimitive<number>;
|
|
29
58
|
angle?: SignalOrPrimitive<number>;
|
|
@@ -31,11 +60,18 @@ export interface DisplayObjectProps {
|
|
|
31
60
|
roundPixels?: SignalOrPrimitive<boolean>;
|
|
32
61
|
cursor?: SignalOrPrimitive<string>;
|
|
33
62
|
visible?: SignalOrPrimitive<boolean>;
|
|
34
|
-
pivot?:
|
|
63
|
+
pivot?: ObservablePointSignal;
|
|
35
64
|
filters?: any[];
|
|
36
65
|
blendMode?: SignalOrPrimitive<PIXI.BLEND_MODES>;
|
|
37
66
|
blur?: SignalOrPrimitive<number>;
|
|
38
67
|
|
|
68
|
+
// Directives
|
|
69
|
+
drag?: DragProps;
|
|
70
|
+
viewportFollow?: ViewportFollowProps;
|
|
71
|
+
shake?: ShakeProps;
|
|
72
|
+
flash?: FlashProps;
|
|
73
|
+
|
|
74
|
+
// Events
|
|
39
75
|
click?: PIXI.FederatedEventHandler;
|
|
40
76
|
mousedown?: PIXI.FederatedEventHandler;
|
|
41
77
|
mouseenter?: PIXI.FederatedEventHandler;
|
|
@@ -66,4 +102,5 @@ export interface DisplayObjectProps {
|
|
|
66
102
|
touchmove?: PIXI.FederatedEventHandler;
|
|
67
103
|
touchstart?: PIXI.FederatedEventHandler;
|
|
68
104
|
wheel?: PIXI.FederatedEventHandler<PIXI.FederatedWheelEvent>;
|
|
105
|
+
tabindex?: SignalOrPrimitive<number>;
|
|
69
106
|
}
|