@vnejs/plugins.canvas.sprite 0.1.1
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/const/const.js +9 -0
- package/const/events.js +16 -0
- package/const/params.js +81 -0
- package/index.js +23 -0
- package/modules/change.js +56 -0
- package/modules/hide.js +44 -0
- package/modules/move.js +41 -0
- package/modules/preload.js +37 -0
- package/modules/show.js +48 -0
- package/modules/src.js +54 -0
- package/modules/state.js +89 -0
- package/modules/utils.js +10 -0
- package/package.json +17 -0
package/const/const.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const ACTIONS = { SHOW: "show", HIDE: "hide", CHANGE: "change", MOVE: "move" };
|
|
2
|
+
|
|
3
|
+
export const LINE_MOVE_REG = /^(?<id>[a-zA-Z_0-9-]+) move (?<position>[a-zA-Z_0-9-]+)( (?<duration>\d+))?( async)?$/;
|
|
4
|
+
export const LINE_SHOW_REG =
|
|
5
|
+
/^(?<id>[a-zA-Z_0-9-]+) show (?<position>[a-zA-Z_0-9-]+) {(?<variation>[a-zA-Z_0-9-/]+)}( (?<transition>[a-zA-Z_0-9-]+)[:](?<duration>\d+))?( async)?$/;
|
|
6
|
+
export const LINE_HIDE_REG = /^(?<id>[a-zA-Z_0-9-]+) hide( (?<transition>[a-zA-Z_0-9-]+)[:](?<duration>\d+))?( async)?$/;
|
|
7
|
+
export const LINE_CHANGE_REG = /^(?<id>[a-zA-Z_0-9-]+) change {(?<variation>[a-zA-Z_0-9-/]+)}( (?<duration>\d+))?( async)?$/;
|
|
8
|
+
|
|
9
|
+
export const LAYER_CHILD_TYPE = "sprite";
|
package/const/events.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const SUBSCRIBE_EVENTS = {
|
|
2
|
+
SHOW: "vne:layer_sprite:show",
|
|
3
|
+
HIDE: "vne:layer_sprite:hide",
|
|
4
|
+
MOVE: "vne:layer_sprite:move",
|
|
5
|
+
CHANGE: "vne:layer_sprite:change",
|
|
6
|
+
|
|
7
|
+
PRELOAD: "vne:layer_sprite:preload",
|
|
8
|
+
|
|
9
|
+
SRC_GET: "vne:layer_sprite:src_get",
|
|
10
|
+
|
|
11
|
+
STATE_UPDATE: "vne:layer_sprite:state_update",
|
|
12
|
+
STATE_GET: "vne:layer_sprite:state_get",
|
|
13
|
+
STATE_ADD: "vne:layer_sprite:state_add",
|
|
14
|
+
STATE_RM: "vne:layer_sprite:state_rm",
|
|
15
|
+
STATE_SETTED: "vne:layer_sprite:state_setted",
|
|
16
|
+
};
|
package/const/params.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export const TRANSITIONS_SHOW = {
|
|
2
|
+
opacity: () => ({ initialProps: { opacity: 0 }, finishProps: { opacity: 1 } }),
|
|
3
|
+
leftOpacity: ({ translateX = 0 }) => ({
|
|
4
|
+
initialProps: { opacity: 0, translateX: translateX ? `calc(${translateX} - 25%)` : "-25%" },
|
|
5
|
+
finishProps: { opacity: 1, translateX: translateX ?? "0%" },
|
|
6
|
+
}),
|
|
7
|
+
rightOpacity: ({ translateX = 0 }) => ({
|
|
8
|
+
initialProps: { opacity: 0, translateX: translateX ? `calc(${translateX} + 25%)` : "25%" },
|
|
9
|
+
finishProps: { opacity: 1, translateX: translateX ?? "0%" },
|
|
10
|
+
}),
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const TRANSITIONS_HIDE = {
|
|
14
|
+
opacity: () => ({ initialProps: {}, finishProps: { opacity: 0 } }),
|
|
15
|
+
leftOpacity: ({ translateX = 0 }) => ({
|
|
16
|
+
initialProps: { opacity: 1, translateX: translateX ?? "0%" },
|
|
17
|
+
finishProps: { opacity: 0, translateX: translateX ? `calc(${translateX} - 25%)` : "-25%" },
|
|
18
|
+
}),
|
|
19
|
+
rightOpacity: ({ translateX = 0 }) => ({
|
|
20
|
+
initialProps: { opacity: 1, translateX: translateX ?? "0%" },
|
|
21
|
+
finishProps: { opacity: 0, translateX: translateX ? `calc(${translateX} + 25%)` : "25%" },
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const POSITIONS = {
|
|
26
|
+
left: { left: "0%", bottom: 0, translateX: "0%", transformOriginX: "0%", transformOriginY: "100%" },
|
|
27
|
+
left10: { left: "0%", bottom: 0, translateX: "-10%", transformOriginX: "10%", transformOriginY: "100%" },
|
|
28
|
+
centerLeft: { left: "25%", bottom: 0, translateX: "-50%", transformOriginX: "50%", transformOriginY: "100%" },
|
|
29
|
+
center: { left: "50%", bottom: 0, translateX: "-50%", transformOriginX: "50%", transformOriginY: "100%" },
|
|
30
|
+
centerRight: { left: "75%", bottom: 0, translateX: "-50%", transformOriginX: "50%", transformOriginY: "100%" },
|
|
31
|
+
right: { left: "100%", bottom: 0, translateX: "-100%", transformOriginX: "100%", transformOriginY: "100%" },
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const mapEyes = (variation, parts, options) => {
|
|
35
|
+
if (options.blink === "close") return `${variation}/eyes/${parts.eyes}/closed`;
|
|
36
|
+
if (options.blink === "open") return `${variation}/eyes/${parts.eyes}/opened`;
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
src: [
|
|
40
|
+
{ url: `${variation}/eyes/${parts.eyes}/opened`, duration: 3000, randomDuration: 1000, transition: 600 },
|
|
41
|
+
{ url: `${variation}/eyes/${parts.eyes}/closed`, duration: 100, randomDuration: 0, transition: 400 },
|
|
42
|
+
{ url: `${variation}/eyes/${parts.eyes}/opened`, duration: 200, randomDuration: 300, transition: 600 },
|
|
43
|
+
{ url: `${variation}/eyes/${parts.eyes}/closed`, duration: 100, randomDuration: 0, transition: 400 },
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const mapMouth = (variation, parts, options) => {
|
|
49
|
+
const urlPrefix = `${variation}/mouth/${parts.mouth}`;
|
|
50
|
+
|
|
51
|
+
if (options.speak)
|
|
52
|
+
return {
|
|
53
|
+
src: [
|
|
54
|
+
{ url: `${urlPrefix}/closed`, duration: 100, transition: 300 },
|
|
55
|
+
{ url: `${urlPrefix}/opened`, duration: 50, transition: 300 },
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return `${urlPrefix}/closed`;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const SPRITE_INFO = {
|
|
63
|
+
co: {
|
|
64
|
+
mapParts: ({ emotion, eyes, mouth, hair, ...other } = {}) => ({
|
|
65
|
+
...(hair ? { hair_front: hair, hair_back: hair } : {}),
|
|
66
|
+
eyes: emotion || eyes,
|
|
67
|
+
mouth: emotion || mouth,
|
|
68
|
+
...other,
|
|
69
|
+
}),
|
|
70
|
+
getSrc: (variation = "", parts = {}, options = {}) =>
|
|
71
|
+
[
|
|
72
|
+
parts.hair_back && `${variation}/hair_back/${parts.hair_back}`,
|
|
73
|
+
`${variation}/index`,
|
|
74
|
+
parts.wear && `${variation}/wear/${parts.wear}`,
|
|
75
|
+
parts.eyes && mapEyes(variation, parts, options),
|
|
76
|
+
parts.mouth && mapMouth(variation, parts, options),
|
|
77
|
+
parts.hair_front && `${variation}/hair_front/${parts.hair_front}`,
|
|
78
|
+
parts.glasses && `${variation}/glasses/${parts.glasses}`,
|
|
79
|
+
].filter(Boolean),
|
|
80
|
+
},
|
|
81
|
+
};
|
package/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { regPlugin } from "@vnejs/shared";
|
|
2
|
+
|
|
3
|
+
import * as constants from "./const/const";
|
|
4
|
+
import { SUBSCRIBE_EVENTS } from "./const/events";
|
|
5
|
+
import * as params from "./const/params";
|
|
6
|
+
|
|
7
|
+
import { LayerSpriteSrc } from "./modules/src";
|
|
8
|
+
import { LayerSpriteShow } from "./modules/show";
|
|
9
|
+
import { LayerSpriteHide } from "./modules/hide";
|
|
10
|
+
import { LayerSpriteMove } from "./modules/move";
|
|
11
|
+
import { LayerSpriteState } from "./modules/state";
|
|
12
|
+
import { LayerSpriteChange } from "./modules/change";
|
|
13
|
+
import { LayerSpritePreload } from "./modules/preload";
|
|
14
|
+
|
|
15
|
+
regPlugin("LAYER_SPRITE", { constants, events: SUBSCRIBE_EVENTS, params }, [
|
|
16
|
+
LayerSpriteSrc,
|
|
17
|
+
LayerSpriteShow,
|
|
18
|
+
LayerSpriteHide,
|
|
19
|
+
LayerSpriteMove,
|
|
20
|
+
LayerSpriteState,
|
|
21
|
+
LayerSpriteChange,
|
|
22
|
+
LayerSpritePreload,
|
|
23
|
+
]);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Module } from "@vnejs/module";
|
|
2
|
+
|
|
3
|
+
import { getPromiseAndResolve } from "./utils";
|
|
4
|
+
|
|
5
|
+
const EMPTY_IMG = { src: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxIDEiLz4=" };
|
|
6
|
+
|
|
7
|
+
export class LayerSpriteChange extends Module {
|
|
8
|
+
name = "layer.sprite.change";
|
|
9
|
+
|
|
10
|
+
subscribe = () => {
|
|
11
|
+
this.on(this.EVENTS.LAYER_SPRITE.CHANGE, this.onChange);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
onChange = async ({ id, layer, variation, mediaType, duration = 0, args = {} } = {}) => {
|
|
15
|
+
if (!id || !layer || !variation || !mediaType) return;
|
|
16
|
+
|
|
17
|
+
await this.emit(this.EVENTS.LAYER_SPRITE.STATE_UPDATE, { id, variation, args });
|
|
18
|
+
|
|
19
|
+
const partsReal = await this.emitOne(this.EVENTS.LAYER_SPRITE.SRC_GET, { variation, args, mediaType });
|
|
20
|
+
|
|
21
|
+
if (!duration) return this.emitChildChange(layer, id, 0, { parts: partsReal, transition: 0, indexSrc: partsReal[0].src });
|
|
22
|
+
|
|
23
|
+
const parts = await this.getTransitionParts(layer, id, partsReal);
|
|
24
|
+
|
|
25
|
+
const { resolve: skipResolve, promise: skipPromise } = getPromiseAndResolve();
|
|
26
|
+
const propsChange = { parts, indexSrc: partsReal[0].src, transition: Number(duration) };
|
|
27
|
+
|
|
28
|
+
await this.emit(this.EVENTS.INTERACT.PUSH_POP, {
|
|
29
|
+
key: `${this.name}_${layer}_${variation}`,
|
|
30
|
+
skipHandler: () => this.emit(this.EVENTS.LAYER.FORCE_UPDATE, { layer }).then(skipResolve),
|
|
31
|
+
handler: () => Promise.race([this.emitChildChange(layer, id, Number(duration), propsChange), skipPromise]),
|
|
32
|
+
});
|
|
33
|
+
await this.emitChildChange(layer, id, 0, { parts: partsReal, transition: 0 });
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
getTransitionParts = async (layer, childId, partsReal) => {
|
|
37
|
+
const childOld = await this.emitReal(this.EVENTS.LAYER.CHILD_GET, { layer, childId });
|
|
38
|
+
|
|
39
|
+
if (childOld.parts.length === partsReal.length) return partsReal;
|
|
40
|
+
if (childOld.parts.length > partsReal.length) return [...partsReal, ...new Array(childOld.parts.length - partsReal.length).fill(EMPTY_IMG)];
|
|
41
|
+
|
|
42
|
+
await this.emitChildChange(layer, childId, 0, { parts: [...childOld.parts, ...new Array(partsReal.length - childOld.parts.length).fill(EMPTY_IMG)] });
|
|
43
|
+
await this.waitRerender();
|
|
44
|
+
return partsReal;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
getBoxProps = (position) => {
|
|
48
|
+
const positions = this.PARAMS.LAYER_SPRITE.POSITIONS;
|
|
49
|
+
const props = positions[position] || positions.left;
|
|
50
|
+
const scale = props.scale ?? 1;
|
|
51
|
+
|
|
52
|
+
return { ...props, scale: `calc(${100 * scale} * min(calc(1vw / var(--vne-canvas-width, 3840px)), calc(1vh / var(--vne-canvas-height, 2160px))))` };
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
emitChildChange = (layer, childId, duration, props) => this.emit(this.EVENTS.LAYER.CHILD_CHANGE, { layer, childId, duration, props });
|
|
56
|
+
}
|
package/modules/hide.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Module } from "@vnejs/module";
|
|
2
|
+
|
|
3
|
+
import { getPromiseAndResolve } from "./utils";
|
|
4
|
+
|
|
5
|
+
export class LayerSpriteHide extends Module {
|
|
6
|
+
name = "layer.sprite.hide";
|
|
7
|
+
|
|
8
|
+
subscribe = () => {
|
|
9
|
+
this.on(this.EVENTS.LAYER_SPRITE.HIDE, this.onHide);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
onHide = async ({ id, layer, transition, duration } = {}) => {
|
|
13
|
+
if (!id || !layer) return;
|
|
14
|
+
|
|
15
|
+
await this.emit(this.EVENTS.LAYER_SPRITE.STATE_RM, { id });
|
|
16
|
+
|
|
17
|
+
if (!transition || !duration || this.shared.viewForceAnimationSources.length) return this.emit(this.EVENTS.LAYER.CHILD_RM, { layer, childId: id });
|
|
18
|
+
|
|
19
|
+
const childOld = await this.emitReal(this.EVENTS.LAYER.CHILD_GET, { layer, childId: id });
|
|
20
|
+
|
|
21
|
+
const { initialProps = {}, finishProps = {} } = this.getTransitionProps(transition, childOld.boxProps);
|
|
22
|
+
const { resolve: skipResolve, promise: skipPromise } = getPromiseAndResolve();
|
|
23
|
+
|
|
24
|
+
const newBoxProps = { ...childOld.boxProps, transition: duration, ...initialProps };
|
|
25
|
+
|
|
26
|
+
await this.emit(this.EVENTS.LAYER.CHILD_CHANGE, { layer, childId: id, duration: 0, props: { boxProps: newBoxProps } });
|
|
27
|
+
|
|
28
|
+
await this.emit(this.EVENTS.INTERACT.PUSH_POP, {
|
|
29
|
+
key: `${this.name}_${layer}`,
|
|
30
|
+
skipHandler: () => this.emit(this.EVENTS.LAYER.FORCE_UPDATE, { layer }).then(skipResolve),
|
|
31
|
+
handler: () => Promise.race([this.emitChildChange(layer, id, duration, { boxProps: { ...newBoxProps, ...finishProps } }), skipPromise]),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return this.emit(this.EVENTS.LAYER.CHILD_RM, { layer, childId: id, duration: 0 });
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
emitChildChange = (layer, childId, duration, props) => this.emit(this.EVENTS.LAYER.CHILD_CHANGE, { layer, childId, duration, props });
|
|
38
|
+
|
|
39
|
+
getTransitionProps = (transition, boxProps) => {
|
|
40
|
+
const transitions = this.PARAMS.LAYER_SPRITE.TRANSITIONS_HIDE;
|
|
41
|
+
|
|
42
|
+
return transitions[transition] ? transitions[transition](boxProps) : transitions.opacity(boxProps);
|
|
43
|
+
};
|
|
44
|
+
}
|
package/modules/move.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Module } from "@vnejs/module";
|
|
2
|
+
|
|
3
|
+
import { getPromiseAndResolve, getScale } from "./utils";
|
|
4
|
+
|
|
5
|
+
export class LayerSpriteMove extends Module {
|
|
6
|
+
name = "layer.sprite.move";
|
|
7
|
+
|
|
8
|
+
subscribe = () => {
|
|
9
|
+
this.on(this.EVENTS.LAYER_SPRITE.MOVE, this.onMove);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
onMove = async ({ id, layer, position, duration } = {}) => {
|
|
13
|
+
if (!position || !id || !layer) return;
|
|
14
|
+
|
|
15
|
+
await this.emit(this.EVENTS.LAYER_SPRITE.STATE_UPDATE, { id, position });
|
|
16
|
+
|
|
17
|
+
if (!duration || this.shared.viewForceAnimationSources.length) return this.emitChildChange(layer, id, 0, { boxProps: this.getBoxProps(position) });
|
|
18
|
+
|
|
19
|
+
const childOld = await this.emitReal(this.EVENTS.LAYER.CHILD_GET, { layer, childId: id });
|
|
20
|
+
|
|
21
|
+
const newProps = { boxProps: { transition: duration, ...this.getBoxProps(position) } };
|
|
22
|
+
const { resolve: skipResolve, promise: skipPromise } = getPromiseAndResolve();
|
|
23
|
+
|
|
24
|
+
await this.emit(this.EVENTS.LAYER.CHILD_CHANGE, { layer, childId: id, duration: 0, props: { boxProps: { ...childOld.boxProps, transition: duration } } });
|
|
25
|
+
|
|
26
|
+
return this.emit(this.EVENTS.INTERACT.PUSH_POP, {
|
|
27
|
+
key: `${this.name}_${layer}_${id}`,
|
|
28
|
+
skipHandler: () => this.emit(this.EVENTS.LAYER.FORCE_UPDATE, { layer }).then(skipResolve),
|
|
29
|
+
handler: () => Promise.race([this.emitChildChange(layer, id, duration, newProps), skipPromise]),
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
emitChildChange = (layer, childId, duration, props) => this.emit(this.EVENTS.LAYER.CHILD_CHANGE, { layer, childId, duration, props });
|
|
34
|
+
|
|
35
|
+
getBoxProps = (position) => {
|
|
36
|
+
const positions = this.PARAMS.LAYER_SPRITE.POSITIONS;
|
|
37
|
+
const props = positions[position] || positions.left;
|
|
38
|
+
|
|
39
|
+
return { ...props, scale: getScale(props.scale ?? 1) };
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Module } from "@vnejs/module";
|
|
2
|
+
|
|
3
|
+
export class LayerSpritePreload extends Module {
|
|
4
|
+
name = "layer.sprite.preload";
|
|
5
|
+
|
|
6
|
+
subscribe = () => {
|
|
7
|
+
this.on(this.EVENTS.LAYER_SPRITE.PRELOAD, this.onSpriteGetSrc);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
onSpriteGetSrc = async ({ variation, args, mediaType, priority } = {}) => {
|
|
11
|
+
const { parts = {}, options = {} } = args;
|
|
12
|
+
|
|
13
|
+
if (!Object.keys(parts).length) return this.loadImageMedia(`${variation}/index`, mediaType, priority);
|
|
14
|
+
|
|
15
|
+
const spriteType = variation.split("/")[0];
|
|
16
|
+
const spriteInfo = this.PARAMS.LAYER_SPRITE.SPRITE_INFO[spriteType] || {};
|
|
17
|
+
const realParts = spriteInfo?.mapParts?.(parts) || parts;
|
|
18
|
+
|
|
19
|
+
return spriteInfo?.getSrc
|
|
20
|
+
? Promise.all(
|
|
21
|
+
spriteInfo.getSrc(variation, realParts, options).map(async (srcObj) => {
|
|
22
|
+
if (typeof srcObj === "string") return this.loadImageMedia(srcObj, mediaType, priority);
|
|
23
|
+
if (Array.isArray(srcObj?.src)) return Promise.all(srcObj.src.map((srcObj2) => this.loadImageMedia(srcObj2.url, mediaType)));
|
|
24
|
+
}),
|
|
25
|
+
)
|
|
26
|
+
: Promise.all([
|
|
27
|
+
this.loadImageMedia(`${variation}/index`, mediaType, priority),
|
|
28
|
+
...Object.entries(parts).map(([partName, partValue]) => this.loadImageMedia(`${variation}/${partName}/${partValue}`, mediaType, priority)),
|
|
29
|
+
]);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
loadImageMedia = (name, mediaType, priority) => {
|
|
33
|
+
const [type, quality] = [this.CONST.MEDIA.TYPES.IMAGE, this.shared.settings[this.SETTINGS.LAYER.QUALITY]];
|
|
34
|
+
|
|
35
|
+
return this.emitOne(this.EVENTS.MEDIA.LOAD, { type, quality, name, mediaType, priority });
|
|
36
|
+
};
|
|
37
|
+
}
|
package/modules/show.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Module } from "@vnejs/module";
|
|
2
|
+
|
|
3
|
+
import { getPromiseAndResolve, getScale } from "./utils";
|
|
4
|
+
|
|
5
|
+
export class LayerSpriteShow extends Module {
|
|
6
|
+
name = "layer.sprite.show";
|
|
7
|
+
|
|
8
|
+
subscribe = () => {
|
|
9
|
+
this.on(this.EVENTS.LAYER_SPRITE.SHOW, this.onShow);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
onShow = async ({ id, variation, layer, mediaType, position, transition, duration, args = {} } = {}) => {
|
|
13
|
+
const src = await this.emitOne(this.EVENTS.LAYER_SPRITE.SRC_GET, { variation, args, mediaType });
|
|
14
|
+
|
|
15
|
+
const boxProps = this.getBoxProps(position);
|
|
16
|
+
const childCommon = { type: this.CONST.LAYER_SPRITE.LAYER_CHILD_TYPE, id, variation, mediaType, args, parts: src, boxProps, indexSrc: src[0].src };
|
|
17
|
+
|
|
18
|
+
await this.emit(this.EVENTS.LAYER_SPRITE.STATE_ADD, { id, variation, layer, mediaType, position, args });
|
|
19
|
+
|
|
20
|
+
if (!duration || !transition || this.shared.viewForceAnimationSources.length) return this.emit(this.EVENTS.LAYER.CHILD_ADD, { layer, child: childCommon });
|
|
21
|
+
|
|
22
|
+
const { initialProps = {}, finishProps = {} } = this.getTransitionProps(transition, boxProps);
|
|
23
|
+
const { resolve: skipResolve, promise: skipPromise } = getPromiseAndResolve();
|
|
24
|
+
const newBoxProps = { ...boxProps, transition: duration, ...initialProps };
|
|
25
|
+
|
|
26
|
+
await this.emit(this.EVENTS.LAYER.CHILD_ADD, { layer, child: { ...childCommon, boxProps: newBoxProps } });
|
|
27
|
+
|
|
28
|
+
return this.emit(this.EVENTS.INTERACT.PUSH_POP, {
|
|
29
|
+
key: `${this.name}_${layer}_${variation}`,
|
|
30
|
+
skipHandler: () => this.emit(this.EVENTS.LAYER.FORCE_UPDATE, { layer }).then(skipResolve),
|
|
31
|
+
handler: () => Promise.race([this.emitChildChange(layer, id, duration, { boxProps: { ...newBoxProps, ...finishProps } }), skipPromise]),
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
getTransitionProps = (transition, boxProps) => {
|
|
36
|
+
const transitions = this.PARAMS.LAYER_SPRITE.TRANSITIONS_SHOW;
|
|
37
|
+
|
|
38
|
+
return transitions[transition] ? transitions[transition](boxProps) : transitions.opacity(boxProps);
|
|
39
|
+
};
|
|
40
|
+
getBoxProps = (position) => {
|
|
41
|
+
const positions = this.PARAMS.LAYER_SPRITE.POSITIONS;
|
|
42
|
+
const props = positions[position] || positions.left;
|
|
43
|
+
|
|
44
|
+
return { ...props, scale: getScale(props.scale ?? 1) };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
emitChildChange = (layer, childId, duration, props) => this.emit(this.EVENTS.LAYER.CHILD_CHANGE, { layer, childId, duration, props });
|
|
48
|
+
}
|
package/modules/src.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Module } from "@vnejs/module";
|
|
2
|
+
|
|
3
|
+
const imagesToSrcs = (q) => ({ src: q.src });
|
|
4
|
+
|
|
5
|
+
export class LayerSpriteSrc extends Module {
|
|
6
|
+
name = "layer.sprite.src";
|
|
7
|
+
|
|
8
|
+
subscribe = () => {
|
|
9
|
+
this.on(this.EVENTS.LAYER_SPRITE.SRC_GET, this.onSpriteGetSrc);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
onSpriteGetSrc = async ({ variation, args, mediaType } = {}) => {
|
|
13
|
+
const { parts = {}, options = {} } = args;
|
|
14
|
+
|
|
15
|
+
if (!Object.keys(parts).length) return [{ src: (await this.getImageMedia(`${variation}/index`, mediaType)).src }];
|
|
16
|
+
|
|
17
|
+
const spriteType = variation.split("/")[0];
|
|
18
|
+
|
|
19
|
+
const spriteInfo = this.PARAMS.LAYER_SPRITE.SPRITE_INFO[spriteType] || {};
|
|
20
|
+
|
|
21
|
+
const realParts = spriteInfo?.mapParts?.(parts) || parts;
|
|
22
|
+
|
|
23
|
+
if (spriteInfo?.getSrc) {
|
|
24
|
+
const partsPromises = spriteInfo.getSrc(variation, realParts, options).map(async (srcObj) => {
|
|
25
|
+
if (typeof srcObj === "string") return imagesToSrcs(await this.getImageMedia(srcObj, mediaType));
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(srcObj?.src)) {
|
|
28
|
+
const src = await Promise.all(
|
|
29
|
+
srcObj.src.map(async (srcObj2) => {
|
|
30
|
+
const src = await this.getImageMedia(srcObj2.url, mediaType);
|
|
31
|
+
|
|
32
|
+
return { ...srcObj2, url: src.src };
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
return { ...srcObj, src: src };
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return Promise.all(partsPromises);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const partsPromises = Object.entries(parts).map(([partName, partValue]) => this.getImageMedia(`${variation}/${partName}/${partValue}`, mediaType));
|
|
44
|
+
const src = await Promise.all([this.getImageMedia(`${variation}/index`, mediaType), ...partsPromises]);
|
|
45
|
+
|
|
46
|
+
return src.map(imagesToSrcs);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
getImageMedia = (name, mediaType) => {
|
|
50
|
+
const [type, quality] = [this.CONST.MEDIA.TYPES.IMAGE, this.shared.settings[this.SETTINGS.LAYER.QUALITY]];
|
|
51
|
+
|
|
52
|
+
return this.emitOne(this.EVENTS.MEDIA.GET, { name, mediaType, type, quality });
|
|
53
|
+
};
|
|
54
|
+
}
|
package/modules/state.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Module } from "@vnejs/module";
|
|
2
|
+
|
|
3
|
+
export class LayerSpriteState extends Module {
|
|
4
|
+
name = "layer.sprite.state";
|
|
5
|
+
|
|
6
|
+
subscribe = () => {
|
|
7
|
+
this.on(this.EVENTS.LAYER_SPRITE.STATE_UPDATE, this.onSpriteStateUpdate);
|
|
8
|
+
this.on(this.EVENTS.LAYER_SPRITE.STATE_GET, this.onSpriteStateGet);
|
|
9
|
+
this.on(this.EVENTS.LAYER_SPRITE.STATE_ADD, this.onSpriteStateAdd);
|
|
10
|
+
this.on(this.EVENTS.LAYER_SPRITE.STATE_RM, this.onSpriteStateRm);
|
|
11
|
+
|
|
12
|
+
this.on(this.EVENTS.STATE.SET, this.onStateSet);
|
|
13
|
+
this.on(this.EVENTS.STATE.CLEAR, this.onStateClear);
|
|
14
|
+
this.on(this.EVENTS.STATE.PRELOAD, this.onStatePreload);
|
|
15
|
+
|
|
16
|
+
this.on(this.EVENTS.MEMORY.CLEARED, this.onMemoryCleared);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
onSpriteStateUpdate = ({ id, ...sprite } = {}) => {
|
|
20
|
+
this.state.sprites = this.state.sprites.map((s) => (s.id === id ? { ...s, ...sprite } : s));
|
|
21
|
+
};
|
|
22
|
+
onSpriteStateAdd = ({ id, variation, layer, mediaType, position, args = {} } = {}) => {
|
|
23
|
+
this.state.sprites.push({ id, variation, layer, mediaType, position, args });
|
|
24
|
+
};
|
|
25
|
+
onSpriteStateRm = ({ id } = {}) => {
|
|
26
|
+
this.state.sprites = this.state.sprites.filter((e) => e.id !== id);
|
|
27
|
+
};
|
|
28
|
+
onSpriteStateGet = ({ id } = {}) => this.state.sprites.find((e) => e.id === id);
|
|
29
|
+
|
|
30
|
+
onStateSet = async ({ [this.name]: state }) => {
|
|
31
|
+
await this.preloadState(state);
|
|
32
|
+
|
|
33
|
+
const oldSpritesByLayer = this.state.sprites.reduce(this.getSpritesByLayerFromState, {});
|
|
34
|
+
const newSpritesByLayer = state.sprites.reduce(this.getSpritesByLayerFromState, {});
|
|
35
|
+
|
|
36
|
+
const [promises, uniqLayers, oldLayers, newLayers] = [[], new Set(), Object.keys(oldSpritesByLayer), Object.keys(newSpritesByLayer)];
|
|
37
|
+
|
|
38
|
+
oldLayers.length && uniqLayers.add(...oldLayers);
|
|
39
|
+
newLayers.length && uniqLayers.add(...newLayers);
|
|
40
|
+
|
|
41
|
+
Array.from(uniqLayers).forEach((layer) => {
|
|
42
|
+
const oldSprites = oldSpritesByLayer[layer] || [];
|
|
43
|
+
const newSprites = newSpritesByLayer[layer] || [];
|
|
44
|
+
|
|
45
|
+
newSprites.forEach((sprite) => {
|
|
46
|
+
if (!oldSprites.find((s) => s.id === sprite.id)) return promises.push(this.emitSpriteShow(sprite));
|
|
47
|
+
|
|
48
|
+
promises.push(this.emitSpriteChange(sprite));
|
|
49
|
+
promises.push(this.emitSpriteMove(sprite));
|
|
50
|
+
});
|
|
51
|
+
oldSprites.forEach((sprite) => !newSprites.find((s) => s.id === sprite.id) && promises.push(this.emitSpriteHide(sprite)));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
this.shared.viewForceAnimationSources.push(`${this.name}.set`);
|
|
55
|
+
await Promise.all(promises);
|
|
56
|
+
this.shared.viewForceAnimationSources = this.shared.viewForceAnimationSources.filter((i) => i !== `${this.name}.set`);
|
|
57
|
+
};
|
|
58
|
+
onStateClear = () => this.clearState();
|
|
59
|
+
onStatePreload = ({ [this.name]: state }) => this.preloadState(state);
|
|
60
|
+
|
|
61
|
+
onMemoryCleared = async () => {
|
|
62
|
+
await this.preloadState(this.state);
|
|
63
|
+
this.shared.viewForceAnimationSources.push(`${this.name}.memory`);
|
|
64
|
+
await Promise.all(this.state.sprites.map(this.emitSpriteChange));
|
|
65
|
+
this.shared.viewForceAnimationSources = this.shared.viewForceAnimationSources.filter((i) => i !== `${this.name}.memory`);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
clearState = async () => {
|
|
69
|
+
this.shared.viewForceAnimationSources.push(`${this.name}.clear`);
|
|
70
|
+
await Promise.all(this.state.sprites.map(this.emitSpriteHide));
|
|
71
|
+
this.shared.viewForceAnimationSources = this.shared.viewForceAnimationSources.filter((i) => i !== `${this.name}.clear`);
|
|
72
|
+
};
|
|
73
|
+
preloadState = (state) => Promise.all(state.sprites.map(this.emitSpriteSrcGet));
|
|
74
|
+
|
|
75
|
+
emitSpriteSrcGet = (sprite) => this.emit(this.EVENTS.LAYER_SPRITE.SRC_GET, sprite);
|
|
76
|
+
emitSpriteChange = (sprite) => this.emit(this.EVENTS.LAYER_SPRITE.CHANGE, sprite);
|
|
77
|
+
emitSpriteMove = (sprite) => this.emit(this.EVENTS.LAYER_SPRITE.MOVE, sprite);
|
|
78
|
+
emitSpriteHide = (sprite) => this.emit(this.EVENTS.LAYER_SPRITE.HIDE, sprite);
|
|
79
|
+
emitSpriteShow = (sprite) => this.emit(this.EVENTS.LAYER_SPRITE.SHOW, sprite);
|
|
80
|
+
|
|
81
|
+
getSpritesByLayerFromState = (acc, sprite) => {
|
|
82
|
+
if (!acc[sprite.layer]) acc[sprite.layer] = [];
|
|
83
|
+
acc[sprite.layer].push(sprite);
|
|
84
|
+
|
|
85
|
+
return acc;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
getDefaultState = () => ({ sprites: [] });
|
|
89
|
+
}
|
package/modules/utils.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const getPromiseAndResolve = () => {
|
|
2
|
+
const obj = {};
|
|
3
|
+
obj.promise = new Promise((resolve) => {
|
|
4
|
+
obj.resolve = resolve;
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
return obj;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const getScale = (scale) => `calc(${100 * scale} * min(calc(1vw / var(--vne-canvas-width, 3840px)), calc(1vh / var(--vne-canvas-height, 2160px))))`;
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vnejs/plugins.canvas.sprite",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
7
|
+
"publish:major:plugin": "npm run publish:major",
|
|
8
|
+
"publish:minor:plugin": "npm run publish:minor",
|
|
9
|
+
"publish:patch:plugin": "npm run publish:patch",
|
|
10
|
+
"publish:major": "npm version major && npm publish --access public",
|
|
11
|
+
"publish:minor": "npm version minor && npm publish --access public",
|
|
12
|
+
"publish:patch": "npm version patch && npm publish --access public"
|
|
13
|
+
},
|
|
14
|
+
"author": "",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"description": ""
|
|
17
|
+
}
|