route-graphics 0.0.34 → 0.1.0
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 +40 -1171
- package/dist/RouteGraphics.js +106 -106
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,1231 +1,100 @@
|
|
|
1
|
+
# Route Graphics
|
|
1
2
|
|
|
2
|
-
|
|
3
|
+
Route Graphics is a declarative 2D UI/rendering system built on PixiJS. You describe states with JSON, then Route Graphics handles element lifecycle, animations, audio, and interaction events for you.
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
This README stays intentionally short. The hosted docs are the source of truth for setup guides, node reference pages, events, asset loading, plugin authoring, and live examples.
|
|
5
6
|
|
|
6
|
-
##
|
|
7
|
+
## Start Here
|
|
7
8
|
|
|
8
|
-
- [
|
|
9
|
+
- [Documentation](http://route-graphics.routevn.com/docs/introduction/introduction/)
|
|
10
|
+
- [Playground](http://route-graphics.routevn.com/playground/)
|
|
9
11
|
- [Tasks & Roadmap](http://route-graphics.routevn.com/tasks)
|
|
10
12
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
### How It Works
|
|
14
|
-
|
|
15
|
-
Route Graphics follows a **render cycle** where:
|
|
16
|
-
|
|
17
|
-
1. **Parser Functions** convert your JSON input into Computed Nodes
|
|
18
|
-
2. **Element Functions** handle the lifecycle:
|
|
19
|
-
- **Add Functions**: Create new visual elements when they appear in the state
|
|
20
|
-
- **Update Functions**: Modify existing elements when their properties change
|
|
21
|
-
- **Delete Functions**: Remove elements when they're no longer in the state
|
|
22
|
-
3. **Animation Functions** apply smooth transitions between states
|
|
23
|
-
4. **Audio Functions** handle sound effects and background music
|
|
24
|
-
|
|
25
|
-
## API Reference
|
|
26
|
-
|
|
27
|
-
### createRouteGraphics()
|
|
28
|
-
|
|
29
|
-
Creates and returns a RouteGraphics instance.
|
|
30
|
-
|
|
31
|
-
```javascript
|
|
32
|
-
const app = createRouteGraphics();
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Instance Methods
|
|
36
|
-
|
|
37
|
-
#### `init(options)`
|
|
38
|
-
|
|
39
|
-
Initialize the RouteGraphics application.
|
|
40
|
-
|
|
41
|
-
**Parameters:**
|
|
42
|
-
- `options` (Object)
|
|
43
|
-
- `width` (number) - Canvas width
|
|
44
|
-
- `height` (number) - Canvas height
|
|
45
|
-
- `backgroundColor` (number, optional) - Background color as hex (e.g., `0x000000`)
|
|
46
|
-
- `debug` (boolean, optional) - Enable debug mode (default: `false`)
|
|
47
|
-
- `eventHandler` (Function) - Callback for events `(eventName, payload) => void`
|
|
48
|
-
- `plugins` (Object)
|
|
49
|
-
- `elements` (Array) - Element plugins to register
|
|
50
|
-
- `animations` (Array) - Animation plugins to register
|
|
51
|
-
- `audio` (Array) - Audio plugins to register
|
|
52
|
-
|
|
53
|
-
**Returns:** `Promise<RouteGraphicsInstance>`
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
#### `loadAssets(assetBufferMap)`
|
|
58
|
-
|
|
59
|
-
Load assets from pre-loaded buffer data.
|
|
60
|
-
|
|
61
|
-
**Parameters:**
|
|
62
|
-
- `assetBufferMap` (Object) - Map of asset key to `{ buffer: ArrayBuffer, type: string }`
|
|
63
|
-
- Example: `{ "hero": { buffer: ArrayBuffer, type: "image/png" } }`
|
|
64
|
-
|
|
65
|
-
**Returns:** `Promise<Array>` - Array of loaded assets
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
#### `render(state)`
|
|
70
|
-
|
|
71
|
-
Render the UI from a state object.
|
|
72
|
-
|
|
73
|
-
**Parameters:**
|
|
74
|
-
- `state` (RouteGraphicsState)
|
|
75
|
-
- `elements` (Array) - Array of element definitions
|
|
76
|
-
- `animations` (Array) - Array of animation definitions
|
|
77
|
-
- `audio` (Array) - Array of audio definitions
|
|
78
|
-
- `global` (Object, optional) - Global configuration
|
|
79
|
-
- `cursorStyles` (Object) - Custom cursor styles
|
|
80
|
-
- `keyboard` (Object) - Keyboard hotkey mappings
|
|
81
|
-
|
|
82
|
-
**Returns:** `void`
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
#### `parse(state)`
|
|
87
|
-
|
|
88
|
-
Parse elements from state object using registered parser plugins (without rendering).
|
|
89
|
-
|
|
90
|
-
**Parameters:**
|
|
91
|
-
- `state` (RouteGraphicsState) - State object containing element definitions
|
|
92
|
-
|
|
93
|
-
**Returns:** `RouteGraphicsState` - Parsed state with computed elements
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
#### `updatedBackgroundColor(color)`
|
|
98
|
-
|
|
99
|
-
Update the canvas background color.
|
|
100
|
-
|
|
101
|
-
**Parameters:**
|
|
102
|
-
- `color` (string) - New background color as hex (e.g., `"0xffffff"`)
|
|
103
|
-
|
|
104
|
-
**Returns:** `void`
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
#### `findElementByLabel(targetLabel)`
|
|
109
|
-
|
|
110
|
-
Find an element in the stage by its label.
|
|
111
|
-
|
|
112
|
-
**Parameters:**
|
|
113
|
-
- `targetLabel` (string) - Label to search for
|
|
114
|
-
|
|
115
|
-
**Returns:** `DisplayObject | null` - Found element or null
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
#### `extractBase64(element)`
|
|
120
|
-
|
|
121
|
-
Extract a base64 representation of an element.
|
|
122
|
-
|
|
123
|
-
**Parameters:**
|
|
124
|
-
- `element` (DisplayObject) - Element to extract
|
|
125
|
-
|
|
126
|
-
**Returns:** `Promise<string>` - Base64 string
|
|
127
|
-
|
|
128
|
-
---
|
|
129
|
-
|
|
130
|
-
#### `assignStageEvent(eventType, callback)`
|
|
131
|
-
|
|
132
|
-
Assign an event listener to the stage.
|
|
133
|
-
|
|
134
|
-
**Parameters:**
|
|
135
|
-
- `eventType` (string) - Event type (e.g., `"click"`, `"pointermove"`)
|
|
136
|
-
- `callback` (Function) - Event callback function
|
|
137
|
-
|
|
138
|
-
**Returns:** `void`
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
#### `destroy()`
|
|
143
|
-
|
|
144
|
-
Destroy the application and cleanup resources.
|
|
145
|
-
|
|
146
|
-
**Returns:** `void`
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
### Instance Properties
|
|
151
|
-
|
|
152
|
-
#### `canvas`
|
|
153
|
-
|
|
154
|
-
The HTML canvas element.
|
|
155
|
-
|
|
156
|
-
**Type:** `HTMLCanvasElement` (read-only)
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## Architecture Overview
|
|
161
|
-
|
|
162
|
-
Route Graphics follows a modular plugin architecture with three main plugin categories:
|
|
163
|
-
|
|
164
|
-
1. **Element Plugins** - Render visual elements with add/update/delete functions
|
|
165
|
-
2. **Audio Plugins** - Handle audio playback
|
|
166
|
-
3. **Animation Plugins** - Handle dynamic content and transitions
|
|
167
|
-
|
|
168
|
-
## Getting Started
|
|
169
|
-
|
|
170
|
-
### Installation
|
|
13
|
+
## Installation
|
|
171
14
|
|
|
172
15
|
```bash
|
|
173
16
|
bun install route-graphics
|
|
174
17
|
```
|
|
175
18
|
|
|
176
|
-
|
|
19
|
+
## Minimal Usage
|
|
177
20
|
|
|
178
21
|
```javascript
|
|
179
22
|
import createRouteGraphics, {
|
|
23
|
+
createAssetBufferManager,
|
|
180
24
|
textPlugin,
|
|
181
25
|
rectPlugin,
|
|
182
26
|
spritePlugin,
|
|
183
|
-
sliderPlugin,
|
|
184
27
|
containerPlugin,
|
|
185
|
-
textRevealingPlugin,
|
|
186
28
|
tweenPlugin,
|
|
187
29
|
soundPlugin,
|
|
188
|
-
|
|
189
|
-
} from 'route-graphics';
|
|
30
|
+
} from "route-graphics";
|
|
190
31
|
|
|
191
|
-
// Define assets with URL and type
|
|
192
32
|
const assets = {
|
|
193
|
-
"circle-red": {
|
|
194
|
-
|
|
195
|
-
type: "image/png",
|
|
196
|
-
},
|
|
197
|
-
"circle-blue": {
|
|
198
|
-
url: "/public/circle-blue.png",
|
|
199
|
-
type: "image/png",
|
|
200
|
-
},
|
|
201
|
-
"circle-green": {
|
|
202
|
-
url: "/public/circle-green.png",
|
|
203
|
-
type: "image/png",
|
|
204
|
-
},
|
|
205
|
-
"slider": {
|
|
206
|
-
url: "/public/slider.png",
|
|
207
|
-
type: "image/png",
|
|
208
|
-
},
|
|
209
|
-
"bgm-1": {
|
|
210
|
-
url: "/public/bgm-1.mp3",
|
|
211
|
-
type: "audio/mpeg",
|
|
212
|
-
},
|
|
213
|
-
"bgm-2": {
|
|
214
|
-
url: "/public/bgm-2.mp3",
|
|
215
|
-
type: "audio/mpeg",
|
|
216
|
-
}
|
|
33
|
+
"circle-red": { url: "/public/circle-red.png", type: "image/png" },
|
|
34
|
+
"bgm-1": { url: "/public/bgm-1.mp3", type: "audio/mpeg" },
|
|
217
35
|
};
|
|
218
36
|
|
|
219
|
-
// Load assets using asset buffer manager
|
|
220
37
|
const assetBufferManager = createAssetBufferManager();
|
|
221
38
|
await assetBufferManager.load(assets);
|
|
222
|
-
const assetBufferMap = assetBufferManager.getBufferMap();
|
|
223
39
|
|
|
224
|
-
// Create and initialize app
|
|
225
40
|
const app = createRouteGraphics();
|
|
226
41
|
await app.init({
|
|
227
42
|
width: 1280,
|
|
228
43
|
height: 720,
|
|
44
|
+
backgroundColor: 0x000000,
|
|
229
45
|
plugins: {
|
|
230
|
-
elements: [
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
spritePlugin,
|
|
234
|
-
sliderPlugin,
|
|
235
|
-
containerPlugin,
|
|
236
|
-
textRevealingPlugin
|
|
237
|
-
],
|
|
238
|
-
animations: [
|
|
239
|
-
tweenPlugin
|
|
240
|
-
],
|
|
241
|
-
audio: [
|
|
242
|
-
soundPlugin
|
|
243
|
-
],
|
|
46
|
+
elements: [textPlugin, rectPlugin, spritePlugin, containerPlugin],
|
|
47
|
+
animations: [tweenPlugin],
|
|
48
|
+
audio: [soundPlugin],
|
|
244
49
|
},
|
|
245
50
|
eventHandler: (eventName, payload) => {
|
|
246
|
-
console.log(
|
|
247
|
-
},
|
|
51
|
+
console.log(eventName, payload);
|
|
52
|
+
},
|
|
248
53
|
});
|
|
249
54
|
|
|
250
|
-
|
|
251
|
-
await app.loadAssets(assetBufferMap);
|
|
55
|
+
await app.loadAssets(assetBufferManager.getBufferMap());
|
|
252
56
|
document.body.appendChild(app.canvas);
|
|
253
57
|
|
|
254
|
-
// Render your UI
|
|
255
58
|
app.render({
|
|
59
|
+
id: "hello-state",
|
|
256
60
|
elements: [
|
|
257
61
|
{
|
|
258
|
-
id: "
|
|
259
|
-
type: "
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
imageSrc: "file:circle-blue",
|
|
267
|
-
soundSrc: "file:hover-sound"
|
|
62
|
+
id: "title",
|
|
63
|
+
type: "text",
|
|
64
|
+
x: 40,
|
|
65
|
+
y: 40,
|
|
66
|
+
content: "Hello Route Graphics",
|
|
67
|
+
textStyle: {
|
|
68
|
+
fill: "#ffffff",
|
|
69
|
+
fontSize: 36,
|
|
268
70
|
},
|
|
269
|
-
|
|
270
|
-
action: "handleClick",
|
|
271
|
-
soundSrc: "file:click-sound"
|
|
272
|
-
}
|
|
273
|
-
}
|
|
71
|
+
},
|
|
274
72
|
],
|
|
275
|
-
animations: [
|
|
276
|
-
|
|
277
|
-
id: "fadeIn",
|
|
278
|
-
targetId: "sprite1",
|
|
279
|
-
type: "tween",
|
|
280
|
-
properties: {
|
|
281
|
-
alpha: {
|
|
282
|
-
initialValue: 0,
|
|
283
|
-
keyframes: [
|
|
284
|
-
{ duration: 1000, value: 1, easing: "linear" }
|
|
285
|
-
]
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
],
|
|
290
|
-
audio: [
|
|
291
|
-
{
|
|
292
|
-
id: "bgMusic",
|
|
293
|
-
type: "sound",
|
|
294
|
-
src: "file:bgm-1",
|
|
295
|
-
volume: 600,
|
|
296
|
-
loop: true
|
|
297
|
-
}
|
|
298
|
-
]
|
|
299
|
-
});
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
## Architecture Overview
|
|
303
|
-
|
|
304
|
-
Route Graphics follows a modular plugin architecture with three main plugin categories:
|
|
305
|
-
|
|
306
|
-
1. **Parser Plugins** - Convert JSON to Computed Nodes
|
|
307
|
-
2. **Element Plugins** - Render visual elements (add/update/delete)
|
|
308
|
-
3. **Audio & Animation Plugins** - Handle dynamic content
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
### The Render Function
|
|
312
|
-
|
|
313
|
-
The main `render()` function is called whenever you want to update your interface. It automatically:
|
|
314
|
-
- Compares the previous state with the new state
|
|
315
|
-
- Determines which elements to add, update, or remove
|
|
316
|
-
- Executes the appropriate element functions
|
|
317
|
-
- Applies animations and audio effects
|
|
318
|
-
|
|
319
|
-
```javascript
|
|
320
|
-
// Initial render
|
|
321
|
-
routeGraphics.render(initialState);
|
|
322
|
-
|
|
323
|
-
// Update with new elements
|
|
324
|
-
routeGraphics.render(updatedState); // Automatically adds/updates/removes elements
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
**Example Lifecycle:**
|
|
328
|
-
```javascript
|
|
329
|
-
// State 1: Show a button
|
|
330
|
-
const state1 = {
|
|
331
|
-
elements: [{
|
|
332
|
-
id: "button1",
|
|
333
|
-
type: "rect",
|
|
334
|
-
width: 100, height: 40,
|
|
335
|
-
fill: "blue"
|
|
336
|
-
}]
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
// State 2: Button changes color and moves
|
|
340
|
-
const state2 = {
|
|
341
|
-
elements: [{
|
|
342
|
-
id: "button1",
|
|
343
|
-
type: "rect",
|
|
344
|
-
width: 100, height: 40,
|
|
345
|
-
fill: "red", // Update: color changes
|
|
346
|
-
x: 50, y: 50 // Update: position moves
|
|
347
|
-
}]
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
// State 3: Button is gone
|
|
351
|
-
const state3 = {
|
|
352
|
-
elements: [] // Delete: button1 is removed
|
|
353
|
-
};
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
## Element Plugins
|
|
357
|
-
|
|
358
|
-
Element plugins handle the creation, updating, and deletion of visual elements. Each plugin follows a consistent interface:
|
|
359
|
-
|
|
360
|
-
```javascript
|
|
361
|
-
createElementPlugin({
|
|
362
|
-
type: "element-type",
|
|
363
|
-
add: addFunction, // Create element
|
|
364
|
-
update: updateFunction, // Update existing element
|
|
365
|
-
delete: deleteFunction // Remove element
|
|
73
|
+
animations: [],
|
|
74
|
+
audio: [],
|
|
366
75
|
});
|
|
367
76
|
```
|
|
368
77
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
#### Sprite Plugin
|
|
372
|
-
Renders image-based sprites with rich interactions.
|
|
373
|
-
|
|
374
|
-
**Required Properties:**
|
|
375
|
-
- `id`, `type`, `x`, `y`, `width`, `height`
|
|
376
|
-
|
|
377
|
-
**Optional Properties:**
|
|
378
|
-
- `src`: Source of the sprite image (asset alias)
|
|
379
|
-
- `anchorX`, `anchorY`: Anchor points (default: 0)
|
|
380
|
-
- `alpha`: Opacity/transparency (0-1, default: 1)
|
|
381
|
-
|
|
382
|
-
**Events:**
|
|
383
|
-
- **click**: Triggered when sprite is clicked
|
|
384
|
-
- `src` (string, optional): Change sprite image
|
|
385
|
-
- `soundSrc` (string, optional): Play sound effect
|
|
386
|
-
- `actionPayload` (object, optional): Custom data sent to event handler
|
|
387
|
-
- **hover**: Triggered when mouse enters/exits sprite
|
|
388
|
-
- `src` (string, optional): Change sprite image
|
|
389
|
-
- `soundSrc` (string, optional): Play sound effect
|
|
390
|
-
- `cursor` (string, optional): CSS cursor style
|
|
391
|
-
- `actionPayload` (object, optional): Custom data sent to event handler
|
|
392
|
-
|
|
393
|
-
**Example:**
|
|
394
|
-
```yaml
|
|
395
|
-
id: character
|
|
396
|
-
type: sprite
|
|
397
|
-
x: 100
|
|
398
|
-
y: 100
|
|
399
|
-
width: 64
|
|
400
|
-
height: 64
|
|
401
|
-
src: hero-idle
|
|
402
|
-
hover:
|
|
403
|
-
src: hero-hover
|
|
404
|
-
cursor: pointer
|
|
405
|
-
soundSrc: hover-sound
|
|
406
|
-
actionPayload:
|
|
407
|
-
action: hoverHero
|
|
408
|
-
click:
|
|
409
|
-
src: hero-active
|
|
410
|
-
soundSrc: click-sound
|
|
411
|
-
actionPayload:
|
|
412
|
-
action: activateHero
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
**Event Data Structure:**
|
|
416
|
-
- **Click Event:**
|
|
417
|
-
```yaml
|
|
418
|
-
_event:
|
|
419
|
-
id: character
|
|
420
|
-
# All actionPayload properties are spread directly here
|
|
421
|
-
action: activateHero
|
|
422
|
-
```
|
|
423
|
-
- **Hover Event:**
|
|
424
|
-
```yaml
|
|
425
|
-
_event:
|
|
426
|
-
id: character
|
|
427
|
-
# All actionPayload properties are spread directly here
|
|
428
|
-
action: hoverHero
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
#### Text Plugin
|
|
432
|
-
Renders styled text with comprehensive formatting options.
|
|
433
|
-
|
|
434
|
-
**Required Properties:**
|
|
435
|
-
- `id`, `type`, `x`, `y`
|
|
436
|
-
|
|
437
|
-
**Optional Properties:**
|
|
438
|
-
- `content`: Text content to display (default: "")
|
|
439
|
-
- `width`: Width constraint for text wrapping
|
|
440
|
-
- `anchorX`, `anchorY`: Anchor points (default: 0)
|
|
441
|
-
- `alpha`: Opacity (0-1, default: 1)
|
|
442
|
-
- `textStyle`: Complete text styling object
|
|
443
|
-
|
|
444
|
-
**TextStyle Options:**
|
|
445
|
-
- `fill`: Text color (default: "black")
|
|
446
|
-
- `fontFamily`: Font family
|
|
447
|
-
- `fontSize`: Font size in pixels (default: 16)
|
|
448
|
-
- `align`: Text alignment ["left", "center", "right"] (default: "left")
|
|
449
|
-
- `lineHeight`: Line height (default: 1.2)
|
|
450
|
-
- `wordWrap`: Enable word wrapping (default: true)
|
|
451
|
-
- `breakWords`: Allow breaking words (default: true)
|
|
452
|
-
- `strokeColor`: Text outline color
|
|
453
|
-
- `strokeWidth`: Text outline width
|
|
454
|
-
|
|
455
|
-
**Events:**
|
|
456
|
-
- **click**: Triggered when text is clicked
|
|
457
|
-
- `textStyle` (object, optional): Change text styling
|
|
458
|
-
- `soundSrc` (string, optional): Play sound effect
|
|
459
|
-
- `actionPayload` (object, optional): Custom data sent to event handler
|
|
460
|
-
- **hover**: Triggered when mouse enters/exits text
|
|
461
|
-
- `textStyle` (object, optional): Change text styling
|
|
462
|
-
- `soundSrc` (string, optional): Play sound effect
|
|
463
|
-
- `cursor` (string, optional): CSS cursor style
|
|
464
|
-
- `actionPayload` (object, optional): Custom data sent to event handler
|
|
465
|
-
|
|
466
|
-
**Example:**
|
|
467
|
-
```yaml
|
|
468
|
-
id: title
|
|
469
|
-
type: text
|
|
470
|
-
x: 960
|
|
471
|
-
y: 100
|
|
472
|
-
content: Welcome to Route Graphics
|
|
473
|
-
textStyle:
|
|
474
|
-
fill: "#ffffff"
|
|
475
|
-
fontFamily: Arial
|
|
476
|
-
fontSize: 48
|
|
477
|
-
align: center
|
|
478
|
-
hover:
|
|
479
|
-
textStyle:
|
|
480
|
-
fill: "#ffff00"
|
|
481
|
-
cursor: pointer
|
|
482
|
-
soundSrc: hover-sound
|
|
483
|
-
actionPayload:
|
|
484
|
-
action: hoverTitle
|
|
485
|
-
click:
|
|
486
|
-
textStyle:
|
|
487
|
-
fill: "#00ff00"
|
|
488
|
-
soundSrc: click-sound
|
|
489
|
-
actionPayload:
|
|
490
|
-
action: clickTitle
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
**Event Data Structure:**
|
|
494
|
-
- **Click Event:**
|
|
495
|
-
```yaml
|
|
496
|
-
_event:
|
|
497
|
-
id: title
|
|
498
|
-
# All actionPayload properties are spread directly here
|
|
499
|
-
action: clickTitle
|
|
500
|
-
```
|
|
501
|
-
- **Hover Event:**
|
|
502
|
-
```yaml
|
|
503
|
-
_event:
|
|
504
|
-
id: title
|
|
505
|
-
# All actionPayload properties are spread directly here
|
|
506
|
-
action: hoverTitle
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
#### Rectangle Plugin
|
|
510
|
-
Creates filled and bordered rectangles with rotation support.
|
|
78
|
+
For complete usage details, go to:
|
|
511
79
|
|
|
512
|
-
|
|
513
|
-
-
|
|
80
|
+
- [Getting Started](http://route-graphics.routevn.com/docs/introduction/getting-started/)
|
|
81
|
+
- [Assets & Loading](http://route-graphics.routevn.com/docs/guides/assets-loading/)
|
|
82
|
+
- [Events & Render Complete](http://route-graphics.routevn.com/docs/guides/events-render-complete/)
|
|
83
|
+
- [Custom Plugins](http://route-graphics.routevn.com/docs/guides/custom-plugins/)
|
|
514
84
|
|
|
515
|
-
|
|
516
|
-
- `x`, `y`: Position (default: 0)
|
|
517
|
-
- `anchorX`, `anchorY`: Anchor points (default: 0)
|
|
518
|
-
- `alpha`: Opacity (0-1, default: 1)
|
|
519
|
-
- `fill`: Fill color (default: "white")
|
|
520
|
-
- `rotation`: Rotation in degrees (default: 0)
|
|
521
|
-
- `border`: Border styling object
|
|
522
|
-
|
|
523
|
-
**Border Options:**
|
|
524
|
-
- `width`: Border width in pixels (default: 0)
|
|
525
|
-
- `color`: Border color (default: "black")
|
|
526
|
-
- `alpha`: Border opacity (0-1, default: 1)
|
|
527
|
-
|
|
528
|
-
**Events:**
|
|
529
|
-
- **click**: Triggered when rectangle is clicked
|
|
530
|
-
- `soundSrc` (string, optional): Play sound effect
|
|
531
|
-
- `actionPayload` (object, optional): Custom data sent to event handler
|
|
532
|
-
- **hover**: Triggered when mouse enters/exits rectangle
|
|
533
|
-
- `soundSrc` (string, optional): Play sound effect
|
|
534
|
-
- `cursor` (string, optional): CSS cursor style
|
|
535
|
-
- `actionPayload` (object, optional): Custom data sent to event handler
|
|
536
|
-
|
|
537
|
-
**Example:**
|
|
538
|
-
```yaml
|
|
539
|
-
id: panel
|
|
540
|
-
type: rect
|
|
541
|
-
x: 50
|
|
542
|
-
y: 50
|
|
543
|
-
width: 400
|
|
544
|
-
height: 300
|
|
545
|
-
fill: "0x333333"
|
|
546
|
-
border:
|
|
547
|
-
width: 2
|
|
548
|
-
color: "0xffffff"
|
|
549
|
-
alpha: 0.8
|
|
550
|
-
alpha: 0.9
|
|
551
|
-
hover:
|
|
552
|
-
cursor: pointer
|
|
553
|
-
soundSrc: hover-sound
|
|
554
|
-
actionPayload:
|
|
555
|
-
action: hoverPanel
|
|
556
|
-
click:
|
|
557
|
-
soundSrc: click-sound
|
|
558
|
-
actionPayload:
|
|
559
|
-
action: clickPanel
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
**Event Data Structure:**
|
|
563
|
-
For an element with `actionPayload: { action: "clickPanel", panelType: "settings" }`:
|
|
564
|
-
|
|
565
|
-
- **Click Event:**
|
|
566
|
-
```yaml
|
|
567
|
-
_event:
|
|
568
|
-
id: panel
|
|
569
|
-
action: clickPanel
|
|
570
|
-
panelType: settings
|
|
571
|
-
```
|
|
572
|
-
|
|
573
|
-
- **Hover Event:**
|
|
574
|
-
```yaml
|
|
575
|
-
_event:
|
|
576
|
-
id: panel
|
|
577
|
-
action: hoverPanel
|
|
578
|
-
panelType: settings
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
#### Container Plugin
|
|
582
|
-
Groups and manages layout of multiple elements.
|
|
583
|
-
|
|
584
|
-
**Required Properties:**
|
|
585
|
-
- `id`, `type`, `x`, `y`
|
|
586
|
-
|
|
587
|
-
**Optional Properties:**
|
|
588
|
-
- `width`, `height`: Container dimensions (calculated from children if not set)
|
|
589
|
-
- `anchorX`, `anchorY`: Anchor points (must be 0, 0.5, or 1 for containers)
|
|
590
|
-
- `alpha`: Opacity (0-1, default: 1)
|
|
591
|
-
- `children`: Array of child elements (default: [])
|
|
592
|
-
- `direction`: Layout layout ["absolute", "horizontal", "vertical"] (default: "absolute")
|
|
593
|
-
- `gap`: Spacing between children in pixels (default: 0)
|
|
594
|
-
- `rotation`: Rotation in degrees (default: 0)
|
|
595
|
-
- `scroll`: Enable scrolling for overflow content (default: false)
|
|
596
|
-
- `anchorToBottom`: Start overflow content from the bottom/right edge (default: false, only when `scroll: true`)
|
|
597
|
-
|
|
598
|
-
**Events:** None
|
|
599
|
-
|
|
600
|
-
**Layout Directions:**
|
|
601
|
-
- `horizontal`: Left-to-right arrangement
|
|
602
|
-
- `vertical`: Top-to-bottom arrangement
|
|
603
|
-
|
|
604
|
-
**Example:**
|
|
605
|
-
```yaml
|
|
606
|
-
id: menu
|
|
607
|
-
type: container
|
|
608
|
-
x: 0
|
|
609
|
-
y: 0
|
|
610
|
-
width: 200
|
|
611
|
-
height: 400
|
|
612
|
-
direction: vertical
|
|
613
|
-
gap: 10
|
|
614
|
-
children:
|
|
615
|
-
- id: btn1
|
|
616
|
-
type: sprite
|
|
617
|
-
x: 0
|
|
618
|
-
y: 0
|
|
619
|
-
width: 200
|
|
620
|
-
height: 50
|
|
621
|
-
src: button-normal
|
|
622
|
-
- id: btn2
|
|
623
|
-
type: sprite
|
|
624
|
-
x: 0
|
|
625
|
-
y: 60
|
|
626
|
-
width: 200
|
|
627
|
-
height: 50
|
|
628
|
-
src: button-normal
|
|
629
|
-
```
|
|
630
|
-
|
|
631
|
-
**Message Feed Update Example:**
|
|
632
|
-
```yaml
|
|
633
|
-
states:
|
|
634
|
-
- elements:
|
|
635
|
-
- id: message-log
|
|
636
|
-
type: container
|
|
637
|
-
x: 50
|
|
638
|
-
y: 50
|
|
639
|
-
width: 500
|
|
640
|
-
height: 220
|
|
641
|
-
direction: vertical
|
|
642
|
-
gap: 8
|
|
643
|
-
scroll: true
|
|
644
|
-
anchorToBottom: true
|
|
645
|
-
children:
|
|
646
|
-
- id: message-1
|
|
647
|
-
type: text
|
|
648
|
-
x: 0
|
|
649
|
-
y: 0
|
|
650
|
-
content: "Hello"
|
|
651
|
-
- id: message-2
|
|
652
|
-
type: text
|
|
653
|
-
x: 0
|
|
654
|
-
y: 32
|
|
655
|
-
content: "How are you?"
|
|
656
|
-
- elements:
|
|
657
|
-
- id: message-log
|
|
658
|
-
type: container
|
|
659
|
-
x: 50
|
|
660
|
-
y: 50
|
|
661
|
-
width: 500
|
|
662
|
-
height: 220
|
|
663
|
-
direction: vertical
|
|
664
|
-
gap: 8
|
|
665
|
-
scroll: true
|
|
666
|
-
anchorToBottom: true
|
|
667
|
-
children:
|
|
668
|
-
- id: message-1
|
|
669
|
-
type: text
|
|
670
|
-
x: 0
|
|
671
|
-
y: 0
|
|
672
|
-
content: "Hello"
|
|
673
|
-
- id: message-2
|
|
674
|
-
type: text
|
|
675
|
-
x: 0
|
|
676
|
-
y: 32
|
|
677
|
-
content: "How are you?"
|
|
678
|
-
- id: message-3
|
|
679
|
-
type: text
|
|
680
|
-
x: 0
|
|
681
|
-
y: 64
|
|
682
|
-
content: "I'm fine."
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
#### Text Revealing Plugin
|
|
686
|
-
Animated text display with typewriter effects.
|
|
687
|
-
|
|
688
|
-
**Required Properties:**
|
|
689
|
-
- `id`, `type`, `x`, `y`
|
|
690
|
-
|
|
691
|
-
**Optional Properties:**
|
|
692
|
-
- `content`: Array of text segments with individual styling
|
|
693
|
-
- `width`: Width constraint for text wrapping
|
|
694
|
-
- `anchorX`, `anchorY`: Anchor points (default: 0)
|
|
695
|
-
- `alpha`: Opacity (0-1, default: 1)
|
|
696
|
-
- `textStyle`: Default text styling for all segments
|
|
697
|
-
- `speed`: Animation speed (default: 50)
|
|
698
|
-
- `revealEffect`: Animation type ["typewriter", "none"] (default: "typewriter")
|
|
699
|
-
- `indicator`: Continuation indicator settings
|
|
700
|
-
|
|
701
|
-
**Content Structure:**
|
|
702
|
-
```yaml
|
|
703
|
-
content:
|
|
704
|
-
- text: "Hello "
|
|
705
|
-
textStyle: # Optional individual styling
|
|
706
|
-
fill: red
|
|
707
|
-
furigana: # Optional Japanese annotations
|
|
708
|
-
text: "こ"
|
|
709
|
-
textStyle:
|
|
710
|
-
fontSize: 12
|
|
711
|
-
- text: "World!"
|
|
712
|
-
```
|
|
713
|
-
|
|
714
|
-
**Indicator Options:**
|
|
715
|
-
- `revealing`: `src`, `width`, `height` - indicator during animation
|
|
716
|
-
- `complete`: `src`, `width`, `height` - indicator when finished
|
|
717
|
-
- `offset`: Distance between text and indicator (default: 12)
|
|
718
|
-
|
|
719
|
-
**Events:** None (Text Revealing elements do not support events)
|
|
720
|
-
|
|
721
|
-
**Example:**
|
|
722
|
-
```yaml
|
|
723
|
-
id: story
|
|
724
|
-
type: textRevealing
|
|
725
|
-
x: 100
|
|
726
|
-
y: 200
|
|
727
|
-
content:
|
|
728
|
-
- text: "Hello "
|
|
729
|
-
textStyle:
|
|
730
|
-
fill: red
|
|
731
|
-
- text: "World!"
|
|
732
|
-
textStyle:
|
|
733
|
-
fill: blue
|
|
734
|
-
speed: 50
|
|
735
|
-
revealEffect: typewriter
|
|
736
|
-
```
|
|
737
|
-
|
|
738
|
-
#### Slider Plugin
|
|
739
|
-
Interactive slider controls for value input.
|
|
740
|
-
|
|
741
|
-
**Required Properties:**
|
|
742
|
-
- `id`, `type`, `x`, `y`, `direction`, `thumbSrc`, `barSrc`
|
|
743
|
-
|
|
744
|
-
**Optional Properties:**
|
|
745
|
-
- `anchorX`, `anchorY`: Anchor points (default: 0)
|
|
746
|
-
- `alpha`: Opacity (0-1, default: 1)
|
|
747
|
-
- `width`, `height`: Slider dimensions
|
|
748
|
-
- `min`: Minimum value (default: 0)
|
|
749
|
-
- `max`: Maximum value (default: 100)
|
|
750
|
-
- `step`: Value increment (default: 1, minimum: 0)
|
|
751
|
-
- `initialValue`: Starting value (default: 0)
|
|
752
|
-
|
|
753
|
-
**Events:**
|
|
754
|
-
- **hover**: Triggered when mouse enters/exits slider
|
|
755
|
-
- `thumbSrc` (string, optional): Change thumb sprite image
|
|
756
|
-
- `barSrc` (string, optional): Change bar sprite image
|
|
757
|
-
- `soundSrc` (string, optional): Play sound effect
|
|
758
|
-
- `cursor` (string, optional): CSS cursor style
|
|
759
|
-
- **change**: Triggered during slider drag with current value
|
|
760
|
-
- `actionPayload` (object, optional): Custom data sent to event handler
|
|
761
|
-
|
|
762
|
-
**Example:**
|
|
763
|
-
```yaml
|
|
764
|
-
id: volumeSlider
|
|
765
|
-
type: slider
|
|
766
|
-
x: 100
|
|
767
|
-
y: 500
|
|
768
|
-
direction: horizontal
|
|
769
|
-
thumbSrc: slider-thumb
|
|
770
|
-
barSrc: slider-bar
|
|
771
|
-
min: 0
|
|
772
|
-
max: 100
|
|
773
|
-
step: 1
|
|
774
|
-
initialValue: 50
|
|
775
|
-
hover:
|
|
776
|
-
thumbSrc: slider-thumb-hover
|
|
777
|
-
barSrc: slider-bar-hover
|
|
778
|
-
cursor: pointer
|
|
779
|
-
soundSrc: slider-hover
|
|
780
|
-
change:
|
|
781
|
-
actionPayload:
|
|
782
|
-
action: updateVolume
|
|
783
|
-
```
|
|
784
|
-
|
|
785
|
-
**Event Data Structure:**
|
|
786
|
-
- **Hover Event:** None (slider hover doesn't trigger event data)
|
|
787
|
-
- **Change Event:** For a slider with `actionPayload: { action: "updateVolume" }` and current value of 75:
|
|
788
|
-
```yaml
|
|
789
|
-
_event:
|
|
790
|
-
id: volumeSlider
|
|
791
|
-
value: 75
|
|
792
|
-
action: updateVolume
|
|
793
|
-
```
|
|
794
|
-
|
|
795
|
-
## Audio Plugin
|
|
796
|
-
|
|
797
|
-
Integrated audio system for sound effects and background music.
|
|
798
|
-
|
|
799
|
-
### Sound Plugin Properties
|
|
800
|
-
|
|
801
|
-
**Required Properties:**
|
|
802
|
-
- `id`, `type`, `src`
|
|
803
|
-
|
|
804
|
-
**Optional Properties:**
|
|
805
|
-
- `volume`: Volume level (default: 800, minimum: 0)
|
|
806
|
-
- `loop`: Whether to loop the audio (default: false)
|
|
807
|
-
- `delay`: Delay before playing in milliseconds (default: 0)
|
|
808
|
-
|
|
809
|
-
**Volume Details:**
|
|
810
|
-
- 0 = muted
|
|
811
|
-
- 1000 = original full volume
|
|
812
|
-
- Values above 1000 = amplified (may clip)
|
|
813
|
-
|
|
814
|
-
**Example:**
|
|
815
|
-
```yaml
|
|
816
|
-
id: bgMusic
|
|
817
|
-
type: sound
|
|
818
|
-
src: bgm-level1
|
|
819
|
-
volume: 800
|
|
820
|
-
loop: true
|
|
821
|
-
delay: 500
|
|
822
|
-
```
|
|
823
|
-
|
|
824
|
-
### Audio Integration
|
|
825
|
-
|
|
826
|
-
Audio integrates seamlessly with element interactions:
|
|
827
|
-
|
|
828
|
-
```yaml
|
|
829
|
-
id: button
|
|
830
|
-
type: sprite
|
|
831
|
-
# ... other properties
|
|
832
|
-
hover:
|
|
833
|
-
soundSrc: file:hover-sound # Plays on hover
|
|
834
|
-
click:
|
|
835
|
-
soundSrc: file:click-sound # Plays on click
|
|
836
|
-
```
|
|
837
|
-
|
|
838
|
-
## Animation System
|
|
839
|
-
|
|
840
|
-
Keyframe-based animation system for smooth transitions and effects.
|
|
841
|
-
|
|
842
|
-
### Tween Animation Plugin
|
|
843
|
-
|
|
844
|
-
**Properties:**
|
|
845
|
-
- `id`, `targetId`, `type`, `properties`
|
|
846
|
-
|
|
847
|
-
**Animatable Properties:**
|
|
848
|
-
- `alpha`, `x`, `y`, `scaleX`, `scaleY`, `rotation`
|
|
849
|
-
|
|
850
|
-
**Example:**
|
|
851
|
-
```yaml
|
|
852
|
-
id: fadeSlide
|
|
853
|
-
targetId: myElement
|
|
854
|
-
type: tween
|
|
855
|
-
properties:
|
|
856
|
-
alpha:
|
|
857
|
-
initialValue: 0
|
|
858
|
-
keyframes:
|
|
859
|
-
- duration: 500
|
|
860
|
-
value: 1
|
|
861
|
-
easing: linear
|
|
862
|
-
- duration: 1000
|
|
863
|
-
value: 0.5
|
|
864
|
-
easing: linear
|
|
865
|
-
x:
|
|
866
|
-
initialValue: 100
|
|
867
|
-
keyframes:
|
|
868
|
-
- duration: 1500
|
|
869
|
-
value: 500
|
|
870
|
-
easing: linear
|
|
871
|
-
```
|
|
872
|
-
|
|
873
|
-
## Creating Custom Plugins
|
|
874
|
-
|
|
875
|
-
The plugin system makes it easy to add new element types, animations, or audio handlers.
|
|
876
|
-
|
|
877
|
-
### Element Plugin Creation
|
|
878
|
-
|
|
879
|
-
```javascript
|
|
880
|
-
import { createElementPlugin } from 'route-graphics';
|
|
881
|
-
|
|
882
|
-
// Create custom element plugin
|
|
883
|
-
const customPlugin = createElementPlugin({
|
|
884
|
-
type: "myCustomElement",
|
|
885
|
-
add: ({ element, app }) => {
|
|
886
|
-
// Creation logic - return a PIXI display object
|
|
887
|
-
const graphics = new Graphics();
|
|
888
|
-
graphics.beginFill(element.fill || 0xffffff);
|
|
889
|
-
graphics.drawRect(element.x, element.y, element.width, element.height);
|
|
890
|
-
graphics.endFill();
|
|
891
|
-
return graphics;
|
|
892
|
-
},
|
|
893
|
-
update: ({ element, app, displayObject }) => {
|
|
894
|
-
// Update logic - modify the display object
|
|
895
|
-
if (displayObject) {
|
|
896
|
-
displayObject.x = element.x;
|
|
897
|
-
displayObject.y = element.y;
|
|
898
|
-
displayObject.alpha = element.alpha ?? 1;
|
|
899
|
-
}
|
|
900
|
-
},
|
|
901
|
-
delete: ({ element, app, displayObject }) => {
|
|
902
|
-
// Cleanup logic
|
|
903
|
-
if (displayObject) {
|
|
904
|
-
displayObject.destroy();
|
|
905
|
-
}
|
|
906
|
-
},
|
|
907
|
-
// Optional: Parse function for JSON to computed conversion
|
|
908
|
-
parse: (element) => {
|
|
909
|
-
// Parse JSON element to computed format
|
|
910
|
-
return {
|
|
911
|
-
...element,
|
|
912
|
-
parsed: true
|
|
913
|
-
};
|
|
914
|
-
}
|
|
915
|
-
});
|
|
916
|
-
|
|
917
|
-
// Register plugin in your app
|
|
918
|
-
await app.init({
|
|
919
|
-
// ... other config
|
|
920
|
-
plugins: {
|
|
921
|
-
elements: [
|
|
922
|
-
// ... existing plugins
|
|
923
|
-
customPlugin
|
|
924
|
-
],
|
|
925
|
-
animations: [/* ... */],
|
|
926
|
-
audio: [/* ... */]
|
|
927
|
-
}
|
|
928
|
-
});
|
|
929
|
-
```
|
|
930
|
-
|
|
931
|
-
### Animation Plugin Creation
|
|
932
|
-
|
|
933
|
-
```javascript
|
|
934
|
-
import { createAnimationPlugin } from 'route-graphics';
|
|
935
|
-
|
|
936
|
-
const customAnimationPlugin = createAnimationPlugin({
|
|
937
|
-
type: "myCustomAnimation",
|
|
938
|
-
add: ({ animation, app }) => {
|
|
939
|
-
// Animation creation logic
|
|
940
|
-
return {
|
|
941
|
-
animation,
|
|
942
|
-
startTime: Date.now(),
|
|
943
|
-
active: true
|
|
944
|
-
};
|
|
945
|
-
},
|
|
946
|
-
update: ({ animation, app, animationData }) => {
|
|
947
|
-
// Animation update logic
|
|
948
|
-
if (animationData.active) {
|
|
949
|
-
const elapsed = Date.now() - animationData.startTime;
|
|
950
|
-
if (elapsed >= animation.duration) {
|
|
951
|
-
animationData.active = false;
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
},
|
|
955
|
-
delete: ({ animation, app, animationData }) => {
|
|
956
|
-
// Animation cleanup logic
|
|
957
|
-
// Stop any ongoing animations
|
|
958
|
-
}
|
|
959
|
-
});
|
|
960
|
-
```
|
|
961
|
-
|
|
962
|
-
### Audio Plugin Creation
|
|
963
|
-
|
|
964
|
-
```javascript
|
|
965
|
-
import { createAudioPlugin } from 'route-graphics';
|
|
966
|
-
|
|
967
|
-
const customAudioPlugin = createAudioPlugin({
|
|
968
|
-
type: "myCustomAudio",
|
|
969
|
-
add: ({ audio, app }) => {
|
|
970
|
-
// Audio creation logic
|
|
971
|
-
return {
|
|
972
|
-
audio,
|
|
973
|
-
startTime: Date.now(),
|
|
974
|
-
playing: true
|
|
975
|
-
};
|
|
976
|
-
},
|
|
977
|
-
update: ({ audio, app, audioData }) => {
|
|
978
|
-
// Audio update logic
|
|
979
|
-
if (audioData.playing && Date.now() - audioData.startTime >= audio.delay) {
|
|
980
|
-
// Start playing after delay
|
|
981
|
-
}
|
|
982
|
-
},
|
|
983
|
-
delete: ({ audio, app, audioData }) => {
|
|
984
|
-
// Audio cleanup logic
|
|
985
|
-
// Stop audio playback
|
|
986
|
-
}
|
|
987
|
-
});
|
|
988
|
-
```
|
|
989
|
-
|
|
990
|
-
## Parser System
|
|
991
|
-
|
|
992
|
-
The parser system transforms your JSON input into Computed Nodes that the rendering engine can process. Each element plugin includes its own parser function that converts JSON definitions into the internal computed format.
|
|
993
|
-
|
|
994
|
-
### parseElements Function
|
|
995
|
-
|
|
996
|
-
```javascript
|
|
997
|
-
// Main parsing function that processes all elements
|
|
998
|
-
const parsedElements = parseElements({
|
|
999
|
-
JSONObject: [
|
|
1000
|
-
{
|
|
1001
|
-
id: "myButton",
|
|
1002
|
-
type: "sprite",
|
|
1003
|
-
x: 100,
|
|
1004
|
-
y: 100,
|
|
1005
|
-
width: 64,
|
|
1006
|
-
height: 64
|
|
1007
|
-
}
|
|
1008
|
-
],
|
|
1009
|
-
parserPlugins: [spritePlugin, textPlugin, ...]
|
|
1010
|
-
});
|
|
1011
|
-
```
|
|
1012
|
-
|
|
1013
|
-
### Parser Function Properties
|
|
1014
|
-
|
|
1015
|
-
**Parameters:**
|
|
1016
|
-
- `state`: The raw JSON element definition from the input
|
|
1017
|
-
- `parserPlugins`: Array of available parser plugins (useful for nested elements like containers)
|
|
1018
|
-
|
|
1019
|
-
**Returns:**
|
|
1020
|
-
- Computed node with processed properties ready for rendering
|
|
1021
|
-
|
|
1022
|
-
### Parser Function Example
|
|
1023
|
-
|
|
1024
|
-
```javascript
|
|
1025
|
-
const parseMyElement = ({ state, parserPlugins }) => {
|
|
1026
|
-
// Validate required properties
|
|
1027
|
-
if (!state.id || !state.type) {
|
|
1028
|
-
throw new Error('Missing required properties');
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
// Apply defaults and type conversion
|
|
1032
|
-
return {
|
|
1033
|
-
id: state.id,
|
|
1034
|
-
type: state.type,
|
|
1035
|
-
x: Math.round(state.x ?? 0),
|
|
1036
|
-
y: Math.round(state.y ?? 0),
|
|
1037
|
-
width: Math.round(state.width ?? 100),
|
|
1038
|
-
height: Math.round(state.height ?? 50),
|
|
1039
|
-
// Custom property with default
|
|
1040
|
-
customProperty: state.customProperty ?? "default",
|
|
1041
|
-
// Example: Hex color to number conversion
|
|
1042
|
-
color: state.color ? parseInt(state.color.replace('#', ''), 16) : 0x000000,
|
|
1043
|
-
};
|
|
1044
|
-
};
|
|
1045
|
-
```
|
|
1046
|
-
|
|
1047
|
-
## Asset Management
|
|
1048
|
-
|
|
1049
|
-
Route Graphics uses a sophisticated asset management system with aliasing.
|
|
1050
|
-
|
|
1051
|
-
### Asset Management
|
|
1052
|
-
|
|
1053
|
-
#### Loading Assets
|
|
1054
|
-
|
|
1055
|
-
Load assets using the `createAssetBufferManager`:
|
|
1056
|
-
|
|
1057
|
-
```javascript
|
|
1058
|
-
import { createAssetBufferManager } from 'route-graphics';
|
|
1059
|
-
|
|
1060
|
-
// Define assets with URL and type
|
|
1061
|
-
const assets = {
|
|
1062
|
-
"hero-sprite": {
|
|
1063
|
-
url: "./assets/hero.png",
|
|
1064
|
-
type: "image/png",
|
|
1065
|
-
},
|
|
1066
|
-
"background-image": {
|
|
1067
|
-
url: "./assets/background.jpg",
|
|
1068
|
-
type: "image/jpeg"
|
|
1069
|
-
},
|
|
1070
|
-
"bg-music": {
|
|
1071
|
-
url: "./audio/background.mp3",
|
|
1072
|
-
type: "audio/mpeg",
|
|
1073
|
-
},
|
|
1074
|
-
"click-sound": {
|
|
1075
|
-
url: "./audio/click.wav",
|
|
1076
|
-
type: "audio/wav"
|
|
1077
|
-
}
|
|
1078
|
-
};
|
|
1079
|
-
|
|
1080
|
-
// Load assets using asset buffer manager
|
|
1081
|
-
const assetBufferManager = createAssetBufferManager();
|
|
1082
|
-
await assetBufferManager.load(assets);
|
|
1083
|
-
const assetBufferMap = assetBufferManager.getBufferMap();
|
|
1084
|
-
|
|
1085
|
-
// Load assets into the app
|
|
1086
|
-
await app.loadAssets(assetBufferMap);
|
|
1087
|
-
```
|
|
1088
|
-
|
|
1089
|
-
#### Asset Aliases
|
|
1090
|
-
|
|
1091
|
-
Once loaded, assets are referenced by their alias keys:
|
|
1092
|
-
|
|
1093
|
-
```yaml
|
|
1094
|
-
id: hero
|
|
1095
|
-
type: sprite
|
|
1096
|
-
src: hero-sprite
|
|
1097
|
-
```
|
|
1098
|
-
|
|
1099
|
-
#### Supported Asset Types
|
|
1100
|
-
|
|
1101
|
-
- **Images**: PNG, JPG, JPEG, WebP
|
|
1102
|
-
- **Audio**: MP3, WAV, OGG
|
|
1103
|
-
- **Fonts**: TTF, OTF, WOFF
|
|
1104
|
-
|
|
1105
|
-
## Development & Testing
|
|
1106
|
-
|
|
1107
|
-
### Running Tests
|
|
85
|
+
## Development
|
|
1108
86
|
|
|
1109
87
|
```bash
|
|
1110
|
-
# Run
|
|
88
|
+
# Run tests
|
|
1111
89
|
bun run test
|
|
1112
|
-
```
|
|
1113
|
-
|
|
1114
|
-
### Playground (Rettangoli Sites)
|
|
1115
|
-
|
|
1116
|
-
The playground is managed as its own local Sites project in `playground/`.
|
|
1117
90
|
|
|
1118
|
-
|
|
1119
|
-
# Install playground deps
|
|
91
|
+
# Build the local docs/playground site
|
|
1120
92
|
cd playground
|
|
1121
93
|
bun install
|
|
1122
|
-
|
|
1123
|
-
# Start watch/dev server (default port 3001)
|
|
1124
|
-
bun run watch
|
|
1125
|
-
|
|
1126
|
-
# Build static output
|
|
1127
94
|
bun run build
|
|
1128
95
|
```
|
|
1129
96
|
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
- Sites config is YAML-only: `playground/sites.config.yaml`
|
|
1133
|
-
- Playground scripts live in `playground/package.json`
|
|
1134
|
-
- Template source of truth: `playground/data/templates.yaml`
|
|
1135
|
-
- Runtime template catalog: `playground/static/public/playground/templates.yaml`
|
|
1136
|
-
|
|
1137
|
-
### Code Quality
|
|
1138
|
-
|
|
1139
|
-
```bash
|
|
1140
|
-
# Build VT pages
|
|
1141
|
-
bun run vt:generate
|
|
1142
|
-
|
|
1143
|
-
# Capture screenshots with Docker
|
|
1144
|
-
bun run vt:screenshot
|
|
1145
|
-
|
|
1146
|
-
# Generate visual diff report
|
|
1147
|
-
bun run vt:report
|
|
1148
|
-
|
|
1149
|
-
# Accept expected diffs
|
|
1150
|
-
bun run vt:accept
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
# Fix linting issues
|
|
1154
|
-
bun run lint:fix
|
|
1155
|
-
|
|
1156
|
-
```
|
|
1157
|
-
|
|
1158
|
-
## Complete YAML Example
|
|
1159
|
-
|
|
1160
|
-
```yaml
|
|
1161
|
-
elements:
|
|
1162
|
-
- id: background
|
|
1163
|
-
type: sprite
|
|
1164
|
-
x: 0
|
|
1165
|
-
y: 0
|
|
1166
|
-
width: 1920
|
|
1167
|
-
height: 1080
|
|
1168
|
-
src: file:bg-image
|
|
1169
|
-
- id: title
|
|
1170
|
-
type: text
|
|
1171
|
-
x: 960
|
|
1172
|
-
y: 100
|
|
1173
|
-
content: Game Title
|
|
1174
|
-
textStyle:
|
|
1175
|
-
fill: "#ffffff"
|
|
1176
|
-
fontFamily: Arial
|
|
1177
|
-
fontSize: 64
|
|
1178
|
-
align: center
|
|
1179
|
-
- id: buttonContainer
|
|
1180
|
-
type: container
|
|
1181
|
-
x: 960
|
|
1182
|
-
y: 400
|
|
1183
|
-
width: 200
|
|
1184
|
-
height: 300
|
|
1185
|
-
direction: vertical
|
|
1186
|
-
gap: 20
|
|
1187
|
-
children:
|
|
1188
|
-
- id: startBtn
|
|
1189
|
-
type: sprite
|
|
1190
|
-
x: 0
|
|
1191
|
-
y: 0
|
|
1192
|
-
width: 200
|
|
1193
|
-
height: 50
|
|
1194
|
-
src: file:btn-normal
|
|
1195
|
-
hover:
|
|
1196
|
-
imageSrc: file:btn-hover
|
|
1197
|
-
soundSrc: file:hover-sound
|
|
1198
|
-
click:
|
|
1199
|
-
action: startGame
|
|
1200
|
-
soundSrc: file:click-sound
|
|
1201
|
-
animations:
|
|
1202
|
-
- id: titleFadeIn
|
|
1203
|
-
targetId: title
|
|
1204
|
-
type: tween
|
|
1205
|
-
properties:
|
|
1206
|
-
alpha:
|
|
1207
|
-
initialValue: 0
|
|
1208
|
-
keyframes:
|
|
1209
|
-
- duration: 2000
|
|
1210
|
-
value: 1
|
|
1211
|
-
easing: linear
|
|
1212
|
-
audio:
|
|
1213
|
-
- id: bgMusic
|
|
1214
|
-
type: sound
|
|
1215
|
-
src: file:background-music
|
|
1216
|
-
volume: 600
|
|
1217
|
-
loop: true
|
|
1218
|
-
```
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
## Schemas
|
|
1222
|
-
|
|
1223
|
-
All element types are defined with YAML schemas in the `src/schemas/` directory, providing:
|
|
1224
|
-
|
|
1225
|
-
- Type definitions and validation
|
|
1226
|
-
- Property documentation
|
|
1227
|
-
- Default values
|
|
1228
|
-
- Required field specifications
|
|
97
|
+
The docs site and playground source live under `playground/`.
|
|
1229
98
|
|
|
1230
99
|
## Community
|
|
1231
100
|
|