@vnejs/plugins.canvas.image 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 ADDED
@@ -0,0 +1,11 @@
1
+ export const ACTIONS = { SHOW: "show", HIDE: "hide", CHANGE: "change" };
2
+
3
+ export const LINE_REG = /^({(?<name>.+?)}|(?<action>(hide|show|change)))( (?<transition>[a-zA-Z_0-9-]+)([:](?<duration>[0-9]+))?)?( async)?$/;
4
+
5
+ export const LINE_PRELOAD_REG = /{(?<name>.+?)}/;
6
+
7
+ export const LINE_SHOW_REG = /^show {(?<name>.+?)}( (?<transition>[a-zA-Z_0-9-]+)([:](?<duration>[0-9]+))?)?( async)?$/;
8
+ export const LINE_HIDE_REG = /^hide( (?<transition>[a-zA-Z_0-9-]+)([:](?<duration>[0-9]+))?)?( async)?$/;
9
+ export const LINE_CHANGE_REG = /^{(?<name>.+?)}( (?<duration>\d+))?( async)?$/;
10
+
11
+ export const LAYER_CHILD_TYPE = "image";
@@ -0,0 +1,14 @@
1
+ export const SUBSCRIBE_EVENTS = {
2
+ SHOW: "vne:layer_image:show",
3
+ HIDE: "vne:layer_image:hide",
4
+ CHANGE: "vne:layer_image:change",
5
+
6
+ PRELOAD: "vne:layer_image:preload",
7
+
8
+ SRC_GET: "vne:layer_image:src_get",
9
+
10
+ STATE_RM: "vne:layer_image:state_rm",
11
+ STATE_GET: "vne:layer_image:state_get",
12
+ STATE_ADD: "vne:layer_image:state_add",
13
+ STATE_UPDATE: "vne:layer_image:state_update",
14
+ };
@@ -0,0 +1,7 @@
1
+ export const TRANSITIONS_SHOW = {
2
+ opacity: (duration) => ({ initialProps: { opacity: 0, transition: duration }, finishProps: { opacity: 1 } }),
3
+ };
4
+
5
+ export const TRANSITIONS_HIDE = {
6
+ opacity: (duration) => ({ initialProps: { transition: duration }, finishProps: { opacity: 0 } }),
7
+ };
package/index.js ADDED
@@ -0,0 +1,21 @@
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 { LayerImageShow } from "./modules/show";
8
+ import { LayerImageHide } from "./modules/hide";
9
+ import { LayerImageStaff } from "./modules/staff";
10
+ import { LayerImageState } from "./modules/state";
11
+ import { LayerImageChange } from "./modules/change";
12
+ import { LayerImagePreload } from "./modules/preload";
13
+
14
+ regPlugin("LAYER_IMAGE", { constants, events: SUBSCRIBE_EVENTS, params }, [
15
+ LayerImageShow,
16
+ LayerImageHide,
17
+ LayerImageStaff,
18
+ LayerImageState,
19
+ LayerImageChange,
20
+ LayerImagePreload,
21
+ ]);
@@ -0,0 +1,33 @@
1
+ import { Module } from "@vnejs/module";
2
+
3
+ import { getPromiseAndResolve } from "./utils";
4
+
5
+ export class LayerImageChange extends Module {
6
+ name = "layer.image.change";
7
+
8
+ subscribe = () => {
9
+ this.on(this.EVENTS.LAYER_IMAGE.CHANGE, this.onImageChange);
10
+ };
11
+
12
+ onImageChange = async ({ id, name, layer, duration, args = {} } = {}) => {
13
+ if (!id || !name || !layer) return;
14
+
15
+ const src = await this.emitOne(this.EVENTS.LAYER_IMAGE.SRC_GET, { name, layer, args });
16
+
17
+ const changeArgs = { src, isAllSrcRendered: Boolean(args.parts), name, args };
18
+
19
+ await this.emit(this.EVENTS.LAYER_IMAGE.STATE_UPDATE, { id, name, args });
20
+
21
+ if (!duration || this.shared.viewForceAnimationSources.length) return this.emitChildChange(layer, id, 0, changeArgs);
22
+
23
+ const { resolve: skipResolve, promise: skipPromise } = getPromiseAndResolve();
24
+
25
+ return this.emit(this.EVENTS.INTERACT.PUSH_POP, {
26
+ key: `${this.name}_${layer}_${name}`,
27
+ skipHandler: () => this.emit(this.EVENTS.LAYER.FORCE_UPDATE, { layer }).then(skipResolve),
28
+ handler: () => Promise.race([this.emitChildChange(layer, id, Number(duration), changeArgs), skipPromise]),
29
+ });
30
+ };
31
+
32
+ emitChildChange = (layer, childId, duration, props) => this.emit(this.EVENTS.LAYER.CHILD_CHANGE, { layer, childId, duration, props });
33
+ }
@@ -0,0 +1,35 @@
1
+ import { Module } from "@vnejs/module";
2
+
3
+ import { getPromiseAndResolve } from "./utils";
4
+
5
+ export class LayerImageHide extends Module {
6
+ name = "layer.image.hide";
7
+
8
+ subscribe = () => {
9
+ this.on(this.EVENTS.LAYER_IMAGE.HIDE, this.onImageHide);
10
+ };
11
+
12
+ onImageHide = async ({ layer, transition, duration } = {}) => {
13
+ const oldChildsId = (await this.emitOne(this.EVENTS.LAYER_IMAGE.STATE_GET, { layer })).map((i) => i.id);
14
+
15
+ if (transition && duration && !this.shared.viewForceAnimationSources.length) {
16
+ const { initialProps = {}, finishProps = {} } = this.getTransitionProps(transition, duration);
17
+ const { resolve: skipResolve, promise: skipPromise } = getPromiseAndResolve();
18
+ const key = `${this.name}_${layer}`;
19
+
20
+ await Promise.all(oldChildsId.map((childId) => this.emit(this.EVENTS.LAYER.CHILD_CHANGE, { layer, childId, duration: 0, props: initialProps })));
21
+ await this.emit(this.EVENTS.INTERACT.PUSH, { key, handler: () => this.emit(this.EVENTS.LAYER.FORCE_UPDATE, { layer }).then(skipResolve) });
22
+ const promises = oldChildsId.map((childId) => this.emit(this.EVENTS.LAYER.CHILD_CHANGE, { layer, childId, duration, props: finishProps }));
23
+ await Promise.race([Promise.all(promises), skipPromise]);
24
+ await this.emit(this.EVENTS.INTERACT.POP, { key });
25
+ }
26
+
27
+ await this.emit(this.EVENTS.LAYER.CHILDS_RM, { layer, childsIds: oldChildsId });
28
+ };
29
+
30
+ getTransitionProps = (transition, duration) => {
31
+ const transitions = this.PARAMS.LAYER_IMAGE.TRANSITIONS_HIDE;
32
+
33
+ return transitions[transition] ? transitions[transition](duration) : transitions.opacity(duration);
34
+ };
35
+ }
@@ -0,0 +1,25 @@
1
+ import { Module } from "@vnejs/module";
2
+
3
+ export class LayerImagePreload extends Module {
4
+ name = "layer.image.preload";
5
+
6
+ subscribe = () => {
7
+ this.on(this.EVENTS.LAYER_IMAGE.PRELOAD, this.onPreload);
8
+ };
9
+
10
+ onPreload = async ({ name, mediaType, priority = this.CONST.MEDIA.PRIORITIES.BACKGROUND, parts } = {}) => {
11
+ if (!name) return;
12
+
13
+ const [type, quality] = [this.CONST.MEDIA.TYPES.IMAGE, this.shared.settings[this.SETTINGS.LAYER.QUALITY]];
14
+ const args = { type, mediaType, priority, quality };
15
+
16
+ if (!parts) return this.loadMedia(name, args);
17
+
18
+ const promises = [this.loadMedia(`${name}/index`, args)];
19
+ Object.entries(parts).forEach(([key, value]) => promises.push(this.loadMedia(`${name}/${key}/${value}`, args)));
20
+
21
+ return Promise.all(promises);
22
+ };
23
+
24
+ loadMedia = (name, args) => this.emit(this.EVENTS.MEDIA.LOAD, { name, ...args });
25
+ }
@@ -0,0 +1,47 @@
1
+ import { Module } from "@vnejs/module";
2
+
3
+ import { getPromiseAndResolve } from "./utils";
4
+
5
+ export class LayerImageShow extends Module {
6
+ name = "layer.image.show";
7
+
8
+ subscribe = () => {
9
+ this.on(this.EVENTS.LAYER_IMAGE.SHOW, this.onImageShow);
10
+ };
11
+
12
+ onImageShow = async ({ name, layer, transition, duration, args = {}, hideOldImagesOnShow = true } = {}) => {
13
+ const shouldHideOldImages = hideOldImagesOnShow || args.hideOldImagesOnShow;
14
+
15
+ const id = args.id || (await this.emitOne(this.EVENTS.VENDORS.UID));
16
+ const oldChildsId = shouldHideOldImages ? (await this.emitOne(this.EVENTS.LAYER_IMAGE.STATE_GET, { layer })).map((i) => i.id) : [];
17
+ const src = await this.emitOne(this.EVENTS.LAYER_IMAGE.SRC_GET, { name, layer, args });
18
+
19
+ const childCommon = { type: this.CONST.LAYER_IMAGE.LAYER_CHILD_TYPE, id, src, isAllSrcRendered: Boolean(args.parts), name, args };
20
+
21
+ await this.emit(this.EVENTS.LAYER_IMAGE.STATE_ADD, { id, name, layer, args });
22
+
23
+ if (!duration || !transition || this.shared.viewForceAnimationSources.length) {
24
+ await this.emit(this.EVENTS.LAYER.CHILD_ADD, { layer, child: childCommon });
25
+ } else {
26
+ const { initialProps = {}, finishProps = {} } = this.getTransitionProps(transition, duration);
27
+ const { resolve: skipResolve, promise: skipPromise } = getPromiseAndResolve();
28
+ const [key, changeArgs] = [`${this.name}_${layer}_${name}`, { layer, childId: id, duration, props: finishProps }];
29
+
30
+ await this.emit(this.EVENTS.LAYER.CHILD_ADD, { layer, child: { ...childCommon, ...initialProps } });
31
+ await this.emit(this.EVENTS.INTERACT.PUSH, { key, handler: () => this.emit(this.EVENTS.LAYER.FORCE_UPDATE, { layer }).then(skipResolve) });
32
+ await Promise.race([this.emit(this.EVENTS.LAYER.CHILD_CHANGE, changeArgs), skipPromise]);
33
+ await this.emit(this.EVENTS.INTERACT.POP, { key });
34
+ }
35
+
36
+ if (shouldHideOldImages)
37
+ return Promise.all([...oldChildsId.map(this.emitStateRm), this.emit(this.EVENTS.LAYER.CHILDS_RM, { layer, childsIds: oldChildsId })]);
38
+ };
39
+
40
+ getTransitionProps = (transition, duration) => {
41
+ const transitions = this.PARAMS.LAYER_IMAGE.TRANSITIONS_SHOW;
42
+
43
+ return transitions[transition] ? transitions[transition](duration) : transitions.opacity(duration);
44
+ };
45
+
46
+ emitStateRm = (id) => this.emit(this.EVENTS.LAYER_IMAGE.STATE_RM, { id });
47
+ }
@@ -0,0 +1,25 @@
1
+ import { Module } from "@vnejs/module";
2
+
3
+ const imagesToSrcs = (q) => ({ url: q.src });
4
+
5
+ export class LayerImageStaff extends Module {
6
+ name = "layer.image.staff";
7
+
8
+ subscribe = () => {
9
+ this.on(this.EVENTS.LAYER_IMAGE.SRC_GET, this.onImageGetSrc);
10
+ };
11
+
12
+ onImageGetSrc = ({ name, layer, args = {} } = {}) => (args.parts ? this.getImageSrcParts(name, layer, args.parts) : this.getImageSrcOne(name, layer));
13
+
14
+ getImageSrcParts = async (name, layer, parts) => {
15
+ const partsPromises = Object.entries(parts).map(([partName, partValue]) => this.getImageMedia(`${name}/${partName}/${partValue}`, layer));
16
+
17
+ return (await Promise.all([this.getImageMedia(`${name}/index`, layer), ...partsPromises])).map(imagesToSrcs);
18
+ };
19
+ getImageSrcOne = async (name, layer) => (await this.getImageMedia(name, layer)).src;
20
+ getImageMedia = (name, layer) => {
21
+ const [type, quality, mediaType] = [this.CONST.MEDIA.TYPES.IMAGE, this.shared.settings[this.SETTINGS.LAYER.QUALITY], layer];
22
+
23
+ return this.emitOne(this.EVENTS.MEDIA.GET, { name, mediaType, type, quality });
24
+ };
25
+ }
@@ -0,0 +1,84 @@
1
+ import { Module } from "@vnejs/module";
2
+
3
+ export class LayerImageState extends Module {
4
+ name = "layer.image.state";
5
+
6
+ subscribe = () => {
7
+ this.on(this.EVENTS.LAYER_IMAGE.STATE_UPDATE, this.onImageStateUpdate);
8
+ this.on(this.EVENTS.LAYER_IMAGE.STATE_GET, this.onImageStateGet);
9
+ this.on(this.EVENTS.LAYER_IMAGE.STATE_ADD, this.onImageStateAdd);
10
+ this.on(this.EVENTS.LAYER_IMAGE.STATE_RM, this.onImageStateRm);
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
+ onImageStateUpdate = ({ id, ...image } = {}) => {
20
+ this.state.images = this.state.images.map((e) => (e.id === id ? { ...e, ...image } : e));
21
+ };
22
+ onImageStateGet = ({ layer } = {}) => this.state.images.filter((e) => e.layer === layer);
23
+ onImageStateAdd = ({ id, name, layer, args } = {}) => {
24
+ this.state.images.push({ id, name, layer, args });
25
+ };
26
+ onImageStateRm = ({ id } = {}) => {
27
+ this.state.images = this.state.images.filter((e) => e.id !== id);
28
+ };
29
+
30
+ onStateSet = async ({ [this.name]: state }) => {
31
+ await this.preloadState(state);
32
+
33
+ const oldImagesByLayer = this.state.images.reduce(this.getImagesByLayerFromState, {});
34
+ const newImagesByLayer = state.images.reduce(this.getImagesByLayerFromState, {});
35
+
36
+ const [promises, uniqLayers, oldLayers, newLayers] = [[], new Set(), Object.keys(oldImagesByLayer), Object.keys(newImagesByLayer)];
37
+
38
+ oldLayers.length && uniqLayers.add(...oldLayers);
39
+ newLayers.length && uniqLayers.add(...newLayers);
40
+
41
+ Array.from(uniqLayers).forEach((layer) => {
42
+ const oldImages = oldImagesByLayer[layer] || [];
43
+ const newImages = newImagesByLayer[layer] || [];
44
+
45
+ promises.push(...oldImages.slice(0, newImages.length).map((img, i) => this.emitImageChange({ ...newImages[i], id: img.id })));
46
+ promises.push(...newImages.slice(oldImages.length).map(this.emitImageShow));
47
+ promises.push(...oldImages.slice(newImages.length).map(this.emitImageHide));
48
+ });
49
+
50
+ this.shared.viewForceAnimationSources.push(`${this.name}.set`);
51
+ await Promise.all(promises);
52
+ this.shared.viewForceAnimationSources = this.shared.viewForceAnimationSources.filter((i) => i !== `${this.name}.set`);
53
+ };
54
+ onStateClear = () => this.clearState();
55
+ onStatePreload = ({ [this.name]: state }) => this.preloadState(state);
56
+
57
+ onMemoryCleared = async () => {
58
+ await this.preloadState(this.state);
59
+ this.shared.viewForceAnimationSources.push(`${this.name}.memory`);
60
+ await Promise.all(this.state.images.map(this.emitImageChange));
61
+ this.shared.viewForceAnimationSources = this.shared.viewForceAnimationSources.filter((i) => i !== `${this.name}.memory`);
62
+ };
63
+
64
+ clearState = async () => {
65
+ this.shared.viewForceAnimationSources.push(`${this.name}.clear`);
66
+ await Promise.all(this.state.images.map(this.emitImageHide));
67
+ this.shared.viewForceAnimationSources = this.shared.viewForceAnimationSources.filter((i) => i !== `${this.name}.clear`);
68
+ };
69
+ preloadState = (state) => Promise.all(state.images.map(this.emitImageSrcGet));
70
+
71
+ emitImageSrcGet = (image) => this.emit(this.EVENTS.LAYER_IMAGE.SRC_GET, image);
72
+ emitImageChange = (image) => this.emit(this.EVENTS.LAYER_IMAGE.CHANGE, image);
73
+ emitImageHide = (image) => this.emit(this.EVENTS.LAYER_IMAGE.HIDE, image);
74
+ emitImageShow = (image) => this.emit(this.EVENTS.LAYER_IMAGE.SHOW, image);
75
+
76
+ getImagesByLayerFromState = (acc, img) => {
77
+ if (!acc[img.layer]) acc[img.layer] = [];
78
+ acc[img.layer].push(img);
79
+
80
+ return acc;
81
+ };
82
+
83
+ getDefaultState = () => ({ images: [] });
84
+ }
@@ -0,0 +1,8 @@
1
+ export const getPromiseAndResolve = () => {
2
+ const obj = {};
3
+ obj.promise = new Promise((resolve) => {
4
+ obj.resolve = resolve;
5
+ });
6
+
7
+ return obj;
8
+ };
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@vnejs/plugins.canvas.image",
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
+ }