@shijiu/jsview-vue 2.0.1073 → 2.0.1106
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/package.json +1 -1
- package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +4 -1
- package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +27 -14
- package/utils/JsViewEngineWidget/MetroWidget/PageUpdater.ts +1 -2
- package/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.ts +6 -2
- package/utils/JsViewEngineWidget/TemplateParser/MetroTemplate.ts +6 -6
- package/utils/JsViewPlugin/JsvAudio/version.js +3 -3
- package/utils/JsViewPlugin/JsvAudio/version.mjs +3 -3
- package/utils/JsViewVueTools/JsvDemoTester.js +4 -3
- package/utils/JsViewVueWidget/JsvActorMove/ActorControlBase.js +5 -5
- package/utils/JsViewVueWidget/JsvActorMove/JsvActorMove.vue +6 -2
- package/utils/JsViewVueWidget/JsvActorMove/JsvActorMoveControl.js +18 -4
- package/utils/JsViewVueWidget/JsvInput/JsvInput.vue +5 -0
- package/utils/JsViewVueWidget/JsvSpriteAnim/JsvSpriteAnim.vue +394 -412
- package/utils/JsViewVueWidget/JsvTextBox.vue +1 -1
package/package.json
CHANGED
|
@@ -386,6 +386,7 @@ const {
|
|
|
386
386
|
);
|
|
387
387
|
|
|
388
388
|
defineExpose(exportObject);
|
|
389
|
+
|
|
389
390
|
</script>
|
|
390
391
|
|
|
391
392
|
<template>
|
|
@@ -414,6 +415,7 @@ defineExpose(exportObject);
|
|
|
414
415
|
width: touchContainerW,
|
|
415
416
|
height: touchContainerH,
|
|
416
417
|
}"
|
|
418
|
+
|
|
417
419
|
>
|
|
418
420
|
<div>
|
|
419
421
|
<slot name="background"></slot>
|
|
@@ -439,7 +441,7 @@ defineExpose(exportObject);
|
|
|
439
441
|
}"
|
|
440
442
|
>
|
|
441
443
|
<div
|
|
442
|
-
v-for="item in renderData"
|
|
444
|
+
v-for="(item, index) in renderData"
|
|
443
445
|
:key="pageUpdateToken + '_' + item.index"
|
|
444
446
|
:ref="item.divRef"
|
|
445
447
|
:style="{
|
|
@@ -450,6 +452,7 @@ defineExpose(exportObject);
|
|
|
450
452
|
v-if="!enableItemRenderBreak || item.mounted || itemRender"
|
|
451
453
|
:key="renderBreakKey"
|
|
452
454
|
:ref="item.slotRef"
|
|
455
|
+
:id="`${name}_${index}`"
|
|
453
456
|
>
|
|
454
457
|
<slot
|
|
455
458
|
name="renderItem"
|
|
@@ -1233,7 +1233,7 @@ export const setup = (
|
|
|
1233
1233
|
);
|
|
1234
1234
|
if (next_focus_item !== null) {
|
|
1235
1235
|
preFocusId = focusId;
|
|
1236
|
-
const preFocusItem =
|
|
1236
|
+
const preFocusItem = getItemById(preFocusId);
|
|
1237
1237
|
focusId = next_focus_item.id;
|
|
1238
1238
|
|
|
1239
1239
|
templateItemAdder.tryAddItem(next_focus_item.templateInfo, 1);
|
|
@@ -1361,14 +1361,25 @@ export const setup = (
|
|
|
1361
1361
|
edge = EdgeDirection.top;
|
|
1362
1362
|
}
|
|
1363
1363
|
const curTemplateInfo = getItemById(focusId)?.templateInfo;
|
|
1364
|
-
let rect
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1364
|
+
let rect
|
|
1365
|
+
if (curTemplateInfo) {
|
|
1366
|
+
rect = {
|
|
1367
|
+
x: curTemplateInfo.left - x_off_set,
|
|
1368
|
+
y: curTemplateInfo.top - y_off_set,
|
|
1369
|
+
width: curTemplateInfo.width,
|
|
1370
|
+
height: curTemplateInfo.height,
|
|
1371
|
+
};
|
|
1372
|
+
} else {
|
|
1373
|
+
rect = {
|
|
1374
|
+
x: 0,
|
|
1375
|
+
y: 0,
|
|
1376
|
+
width: 0,
|
|
1377
|
+
height: 0,
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1370
1381
|
props.onEdge?.({ direction: edge, rect: rect });
|
|
1371
|
-
innerData[id2Index(focusId)]
|
|
1382
|
+
innerData[id2Index(focusId)]?.onWidgetEdge({
|
|
1372
1383
|
direction: edge,
|
|
1373
1384
|
});
|
|
1374
1385
|
}
|
|
@@ -1692,12 +1703,14 @@ export const setup = (
|
|
|
1692
1703
|
if (props.onScroll) {
|
|
1693
1704
|
const lastTemplateInfo = getItemByIndex(
|
|
1694
1705
|
metroTemplate.size - 1
|
|
1695
|
-
)
|
|
1696
|
-
let totalWidth;
|
|
1697
|
-
if (
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1706
|
+
)?.templateInfo;
|
|
1707
|
+
let totalWidth = 0;
|
|
1708
|
+
if (lastTemplateInfo) {
|
|
1709
|
+
if (vertical) {
|
|
1710
|
+
totalWidth = lastTemplateInfo.top + lastTemplateInfo.height - 1;
|
|
1711
|
+
} else {
|
|
1712
|
+
totalWidth = lastTemplateInfo.left + lastTemplateInfo.width - 1;
|
|
1713
|
+
}
|
|
1701
1714
|
}
|
|
1702
1715
|
props.onScroll(visibleInfo.start, visibleInfo.range, totalWidth);
|
|
1703
1716
|
}
|
|
@@ -32,8 +32,7 @@ export class PageUpdater {
|
|
|
32
32
|
mergeTmp: boolean,
|
|
33
33
|
permanentList: Array<PermanentItemInfo> | null,
|
|
34
34
|
extensionRange: number = 0
|
|
35
|
-
) {
|
|
36
|
-
if (!template || template.size === 0) return;
|
|
35
|
+
): {apply: Function, applyTmp: Function} {
|
|
37
36
|
this.count++;
|
|
38
37
|
const [visibleStart, visibleEnd] = template.getVisibleItemList(
|
|
39
38
|
start - extensionRange,
|
|
@@ -388,6 +388,10 @@ class CommonMetroTemplate extends MetroTemplate {
|
|
|
388
388
|
}
|
|
389
389
|
|
|
390
390
|
const itemIndex = this.id2Index(baseId);
|
|
391
|
+
if (itemIndex < 0) {
|
|
392
|
+
console.log("getNextItem: no focusable item.");
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
391
395
|
const offset = vOffset !== 0 ? vOffset : hOffset;
|
|
392
396
|
let nextTemplateItem = this.getNextItemInner(
|
|
393
397
|
itemIndex,
|
|
@@ -724,7 +728,7 @@ class CommonMetroTemplate extends MetroTemplate {
|
|
|
724
728
|
visibleStart: number,
|
|
725
729
|
visibleEnd: number,
|
|
726
730
|
baseId: number): [number, number] {
|
|
727
|
-
if (visibleStart > visibleEnd) {
|
|
731
|
+
if (visibleStart > visibleEnd || this.templateList.length == 0) {
|
|
728
732
|
// No visible item
|
|
729
733
|
return [-1, -1];
|
|
730
734
|
}
|
|
@@ -732,7 +736,7 @@ class CommonMetroTemplate extends MetroTemplate {
|
|
|
732
736
|
visibleStart = Math.round(visibleStart);
|
|
733
737
|
visibleEnd = Math.round(visibleEnd);
|
|
734
738
|
let searchBaseItemIdx = this.id2Index(baseId);
|
|
735
|
-
if (
|
|
739
|
+
if (searchBaseItemIdx < 0) searchBaseItemIdx = 0;
|
|
736
740
|
const commonData: VisibleSearchConfigCommon = {
|
|
737
741
|
resultStartIdx: -1,
|
|
738
742
|
resultEndIdx: -1,
|
|
@@ -270,12 +270,12 @@ abstract class MetroTemplate {
|
|
|
270
270
|
|
|
271
271
|
width: itemObj.width,
|
|
272
272
|
height: itemObj.height,
|
|
273
|
-
left: itemObj.left
|
|
274
|
-
top: itemObj.top
|
|
275
|
-
marginRight: itemObj.marginRight
|
|
276
|
-
marginBottom: itemObj.marginBottom
|
|
277
|
-
focusable: itemObj.focusable
|
|
278
|
-
findNextAnchor: itemObj.findNextAnchor
|
|
273
|
+
left: itemObj.left ?? 0,
|
|
274
|
+
top: itemObj.top ?? 0,
|
|
275
|
+
marginRight: itemObj.marginRight ?? 0,
|
|
276
|
+
marginBottom: itemObj.marginBottom ?? 0,
|
|
277
|
+
focusable: itemObj.focusable ?? true,
|
|
278
|
+
findNextAnchor: itemObj.findNextAnchor ?? null,
|
|
279
279
|
|
|
280
280
|
neighborIndexList: {
|
|
281
281
|
left: [],
|
|
@@ -7,9 +7,9 @@ let PluginInfo = {
|
|
|
7
7
|
// downloadUrl:"http://192.168.0.63:8080/plugin/JsvAudio-164.zip", //插件下载地址
|
|
8
8
|
packageName: "com.qcode.jsvaudio",
|
|
9
9
|
name: "音频插件",
|
|
10
|
-
version: "1.0.
|
|
11
|
-
versionCodeMin:
|
|
12
|
-
versionCodeMax:
|
|
10
|
+
version: "1.0.24", //插件需要的版本号
|
|
11
|
+
versionCodeMin: 24,
|
|
12
|
+
versionCodeMax: 24,
|
|
13
13
|
bridgeName: "jsvAudioBridge", //插件bridge注册到jsview的名称
|
|
14
14
|
className: "com.qcode.jsvaudio.JsvAudio", //插件初始化类名称
|
|
15
15
|
initMethod: "createInstance", //插件初始化方法
|
|
@@ -7,9 +7,9 @@ let PluginInfo = {
|
|
|
7
7
|
// downloadUrl:"http://192.168.0.63:8080/plugin/JsvAudio-164.zip", //插件下载地址
|
|
8
8
|
packageName: "com.qcode.jsvaudio",
|
|
9
9
|
name: "音频插件",
|
|
10
|
-
version: "1.0.
|
|
11
|
-
versionCodeMin:
|
|
12
|
-
versionCodeMax:
|
|
10
|
+
version: "1.0.24", //插件需要的版本号
|
|
11
|
+
versionCodeMin: 24,
|
|
12
|
+
versionCodeMax: 24,
|
|
13
13
|
bridgeName: "jsvAudioBridge", //插件bridge注册到jsview的名称
|
|
14
14
|
className: "com.qcode.jsvaudio.JsvAudio", //插件初始化类名称
|
|
15
15
|
initMethod: "createInstance", //插件初始化方法
|
|
@@ -37,12 +37,13 @@ const ensureInterface = ()=>{
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const enableNativeViewListener = (nativeViewId)=>{
|
|
40
|
+
const enableNativeViewListener = (nativeViewId,info)=>{
|
|
41
41
|
let listenerId = idGeneratoer;
|
|
42
42
|
idGeneratoer++;
|
|
43
43
|
idObjectMap[listenerId] = {
|
|
44
44
|
eventCallback: (ret)=>{
|
|
45
|
-
|
|
45
|
+
info.value=ret.info
|
|
46
|
+
console.log(`JsvDemoTester nativeView info=${info.value}`);
|
|
46
47
|
}
|
|
47
48
|
};
|
|
48
49
|
|
|
@@ -76,5 +77,5 @@ const disableNativeViewListener = (listenerId)=>{
|
|
|
76
77
|
|
|
77
78
|
export {
|
|
78
79
|
enableNativeViewListener,
|
|
79
|
-
disableNativeViewListener
|
|
80
|
+
disableNativeViewListener,
|
|
80
81
|
}
|
|
@@ -67,6 +67,10 @@ class ActorControlBase {
|
|
|
67
67
|
Forge.sRenderBridge.SetStepFpsSwitch(false);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
altStraightSpeedInner(newSpeedPerSecond, time) {
|
|
71
|
+
Forge.AnimFireCommand.AltSpeed(this._SpriteView, newSpeedPerSecond, time);
|
|
72
|
+
}
|
|
73
|
+
|
|
70
74
|
_WrapBuildAnimation(
|
|
71
75
|
repeat_start_array,
|
|
72
76
|
current_array,
|
|
@@ -126,7 +130,6 @@ class ActorControlBase {
|
|
|
126
130
|
|
|
127
131
|
const froms = [...this._Current];
|
|
128
132
|
const tos = this._Target;
|
|
129
|
-
const repeat_starts = this._Repeat ? [...this._RepeatStart] : null;
|
|
130
133
|
|
|
131
134
|
// const token = this._Token++;
|
|
132
135
|
|
|
@@ -142,7 +145,7 @@ class ActorControlBase {
|
|
|
142
145
|
const listener = new Forge.AnimationListener().OnFinalProgress(
|
|
143
146
|
(progress) => {
|
|
144
147
|
that._OnPaused(
|
|
145
|
-
|
|
148
|
+
froms,
|
|
146
149
|
memo_tos,
|
|
147
150
|
progress,
|
|
148
151
|
start_params
|
|
@@ -154,9 +157,6 @@ class ActorControlBase {
|
|
|
154
157
|
|
|
155
158
|
anim.AddAnimationListener(listener);
|
|
156
159
|
anim.Enable(Forge.AnimationEnable.KeepTransform);
|
|
157
|
-
if (this._Repeat) {
|
|
158
|
-
anim.EnableInfinite();
|
|
159
|
-
}
|
|
160
160
|
this._SpriteView.StartAnimation(anim);
|
|
161
161
|
|
|
162
162
|
return true; // success
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
* 功能:延X轴进行匀速运动
|
|
20
20
|
* moveToY(target_y, speed, end_callback)
|
|
21
21
|
* 功能:延Y轴进行匀速运动
|
|
22
|
-
*
|
|
22
|
+
* scrollMoveAlongX(target_x, speed, repeat_start, repeat_callback)
|
|
23
23
|
* 功能:延X轴进行重复匀速运动
|
|
24
|
-
*
|
|
24
|
+
* scrollMoveAlongY(target_y, speed, repeat_start, repeat_callback)
|
|
25
25
|
* 功能:延Y轴进行重复匀速运动
|
|
26
26
|
* throwAlongX(init_v, acc, end_condition, end_callback, pole_callback)
|
|
27
27
|
* 功能:延X轴进行回旋运动
|
|
@@ -31,6 +31,10 @@
|
|
|
31
31
|
* 功能:直接将JsvActorMove移动到目标位置,无中间运动动画
|
|
32
32
|
* pause(pause_callback)
|
|
33
33
|
* 功能:暂停动画,并将JsvActorMove保持在暂停的位置上
|
|
34
|
+
* pause(pause_callback)
|
|
35
|
+
* 功能:暂停动画,并将JsvActorMove保持在暂停的位置上
|
|
36
|
+
* altStraightSpeed(newSpeedPerSecond, time)
|
|
37
|
+
* 功能: 将由moveToX, moveToY, scrollMoveAlongX, scrollMoveAlongY 发起的直线运动进行均匀变速
|
|
34
38
|
|
|
35
39
|
-->
|
|
36
40
|
<script setup>
|
|
@@ -50,14 +50,25 @@ class JsvActorMoveControl extends ActorControlBase {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/*
|
|
53
|
-
*
|
|
53
|
+
* altStraightSpeed
|
|
54
|
+
* 将由moveToX, moveToY, scrollMoveAlongX, scrollMoveAlongY 发起的直线运动进行均匀变速
|
|
55
|
+
* 参数说明:
|
|
56
|
+
* spnewSpeedPerSecond (int) 带符号整数,符号表示方向,标识运动的运行速度,单位(pixel/s)
|
|
57
|
+
* end_callback (Function(x,y)) 运动到目标位置后的回调函数,回报当前JsvActorMove的相对x,y
|
|
58
|
+
*/
|
|
59
|
+
altStraightSpeed(newSpeedPerSecond, time) {
|
|
60
|
+
this.altStraightSpeedInner(newSpeedPerSecond, time);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* scrollMoveAlongX 用于背景无限滚轴动画效果的接口,参数说明:
|
|
54
65
|
* target_x (int) 带符号整数,标识运动的目标位置,相对于JsvActorMove当前位置
|
|
55
66
|
* speed (int) 带符号整数,符号表示方向,标识运动的运行速度,单位(pixel/s)
|
|
56
67
|
* repeat_start (int) 带符号整数,标识往复运动的起始点,使用时注意,JsvActorMove的当前位置必须在
|
|
57
68
|
* repeat_start和target_x之间
|
|
58
69
|
* repeat_callback (Function(times)) 完整一个运动周期后的回调,返回当前运动的周期数times
|
|
59
70
|
*/
|
|
60
|
-
|
|
71
|
+
scrollMoveAlongX(target_x, speed, repeat_start, repeat_callback) {
|
|
61
72
|
this._UniformMove(0,
|
|
62
73
|
target_x, NaN, speed,
|
|
63
74
|
{
|
|
@@ -68,14 +79,14 @@ class JsvActorMoveControl extends ActorControlBase {
|
|
|
68
79
|
}
|
|
69
80
|
|
|
70
81
|
/*
|
|
71
|
-
*
|
|
82
|
+
* scrollMoveAlongY 用于背景无限滚轴动画效果的接口,参数说明:
|
|
72
83
|
* target_y (int) 带符号整数,标识运动的目标位置,相对于JsvActorMove当前位置
|
|
73
84
|
* speed (int) 带符号整数,符号表示方向,标识运动的运行速度,单位(pixel/s)
|
|
74
85
|
* repeat_start (int) 带符号整数,标识往复运动的起始点,使用时注意,JsvActorMove的当前位置必须在
|
|
75
86
|
* repeat_start和target_y之间
|
|
76
87
|
* repeat_callback (Function(times)) 完整一个运动周期后的回调,返回当前运动的周期数times
|
|
77
88
|
*/
|
|
78
|
-
|
|
89
|
+
scrollMoveAlongY(target_y, speed, repeat_start, repeat_callback) {
|
|
79
90
|
this._UniformMove(1,
|
|
80
91
|
NaN, target_y, speed,
|
|
81
92
|
{
|
|
@@ -354,11 +365,14 @@ class JsvActorMoveControl extends ActorControlBase {
|
|
|
354
365
|
|
|
355
366
|
|
|
356
367
|
_ReCalculateUMoveCurrent(froms, tos, progress, start_params) {
|
|
368
|
+
let repeat_start = start_params?.repeatSet?.start;
|
|
357
369
|
if (start_params.xOrY === 0) {
|
|
370
|
+
froms[0] = repeat_start ? repeat_start : froms[0];
|
|
358
371
|
const value = (tos[0] - froms[0]) * progress + froms[0];
|
|
359
372
|
const direction = value >= 0 ? 1 : -1;
|
|
360
373
|
this._Current[0] = direction * Math.floor(Math.abs(value));
|
|
361
374
|
} else {
|
|
375
|
+
froms[1] = repeat_start ? repeat_start : froms[1];
|
|
362
376
|
const value = (tos[1] - froms[1]) * progress + froms[1];
|
|
363
377
|
const direction = value >= 0 ? 1 : -1;
|
|
364
378
|
this._Current[1] = direction * Math.floor(Math.abs(value));
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* 自动启动模式:start:精灵图自动启动,结束后显示第一帧内容、
|
|
22
22
|
* end:精灵图自动启动,结束后显示最后一帧内容,
|
|
23
23
|
* none:不自动启动
|
|
24
|
-
* loop {string} 动图的循环次数 infinite/数字,默认为infinite
|
|
24
|
+
* loop {string或number} 动图的循环次数 infinite/数字,默认为infinite
|
|
25
25
|
* spriteName {string} 动图的名称,默认为null
|
|
26
26
|
* controller {SpriteController} 控制动图start,stop的对象
|
|
27
27
|
*
|
|
@@ -32,414 +32,396 @@
|
|
|
32
32
|
* stop(end_frame)
|
|
33
33
|
* 功能: 停止精灵图动画,可选择静止在第一帧或最后一帧
|
|
34
34
|
-->
|
|
35
|
-
<script>
|
|
36
|
-
import { getKeyFramesGroup } from '../../JsViewVueTools/JsvDynamicKeyFrames.js'
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
</script>
|
|
432
|
-
|
|
433
|
-
<template>
|
|
434
|
-
<div id="canvas">
|
|
435
|
-
<div id="clip" :style="{...transform_style.clipStyle}">
|
|
436
|
-
<div id="trans" :style="{...transform_style.transStyle}" @animationend="onAnimEndDelegate">
|
|
437
|
-
<div id="image" :style="{...transform_style.imageStyle, animation: blinkAnim}" @animationend="onBlinkAnimEnd"></div>
|
|
438
|
-
</div>
|
|
439
|
-
</div>
|
|
440
|
-
</div>
|
|
441
|
-
</template>
|
|
442
|
-
|
|
443
|
-
<style scoped>
|
|
444
|
-
@keyframes sprite-tag{}
|
|
445
|
-
</style>
|
|
35
|
+
<script setup>
|
|
36
|
+
import { getKeyFramesGroup } from '../../JsViewVueTools/JsvDynamicKeyFrames.js'
|
|
37
|
+
import { reactive, shallowRef, onUnmounted, watch } from 'vue';
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
const _getTransformInfo = (source_obj, target_obj, canvas_width, canvas_height) => {
|
|
41
|
+
const result = { csw: 1, csh: 1, cx: 0, cy: 0, sw: 1, sh: 1, x: 0, y: 0 };
|
|
42
|
+
|
|
43
|
+
// Clip在Canvas div之内,以Canvas为基准进行缩放和平移
|
|
44
|
+
// 图形左上角远离原点后再缩放,所以需要进行缩放补偿
|
|
45
|
+
const clip_scale_w = target_obj.w / canvas_width;
|
|
46
|
+
const clip_scale_h = target_obj.h / canvas_height;
|
|
47
|
+
result.csw = clip_scale_w;
|
|
48
|
+
result.csh = clip_scale_h;
|
|
49
|
+
result.cx = target_obj.x / clip_scale_w;
|
|
50
|
+
result.cy = target_obj.y / clip_scale_h;
|
|
51
|
+
|
|
52
|
+
// Image在Clip div之内,所以以Clip为基准进行缩放和平移, 对clip的缩放进行反处理以还原尺寸
|
|
53
|
+
// 将子图左上角对齐原点后再缩放,所以x,y不需要进行举例缩放补偿
|
|
54
|
+
result.sw = source_obj.w / target_obj.w / clip_scale_w;
|
|
55
|
+
result.sh = source_obj.h / target_obj.h / clip_scale_h;
|
|
56
|
+
result.x = -source_obj.x;
|
|
57
|
+
result.y = -source_obj.y;
|
|
58
|
+
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const _createTransformStyle = (w_scale, h_scale, x, y) => {
|
|
63
|
+
let output = "";
|
|
64
|
+
output = `${output}scale3d(${parseFloat(w_scale).toPrecision(5)},${parseFloat(h_scale).toPrecision(5)},1) `
|
|
65
|
+
+ `translate3d(${parseFloat(x).toPrecision(5)}px,${parseFloat(y).toPrecision(5)}px,0)`;
|
|
66
|
+
return output;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const props = defineProps({
|
|
70
|
+
spriteInfo: Object,
|
|
71
|
+
viewSize: Object,
|
|
72
|
+
imageUrl: String,
|
|
73
|
+
duration: Number,
|
|
74
|
+
onAnimEnd: Function,
|
|
75
|
+
autostart: [Boolean, String],
|
|
76
|
+
loop: [String,Number],
|
|
77
|
+
spriteName: String,
|
|
78
|
+
controller: Object,
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
let stopFrame = shallowRef("start");
|
|
83
|
+
let TRANSFORM_ORIGIN_LEFT_TOP = shallowRef("left top")
|
|
84
|
+
let keyFrameNames = reactive({
|
|
85
|
+
clip: null,
|
|
86
|
+
image: null,
|
|
87
|
+
valid: false
|
|
88
|
+
});
|
|
89
|
+
let frozeFrameCache = reactive({
|
|
90
|
+
clipStyle: {},
|
|
91
|
+
transStyle: {},
|
|
92
|
+
imageStyle: {
|
|
93
|
+
backgroundImage: null,
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
let animateFrameCache = reactive({
|
|
97
|
+
clipStyle: {},
|
|
98
|
+
transStyle: {},
|
|
99
|
+
imageStyle: {
|
|
100
|
+
backgroundImage: null,
|
|
101
|
+
},
|
|
102
|
+
clipAnimName: null,
|
|
103
|
+
imageAnimName: null,
|
|
104
|
+
});
|
|
105
|
+
let keyFrameStyleSheet = getKeyFramesGroup(null);
|
|
106
|
+
let innerId = shallowRef(0);
|
|
107
|
+
let stopped = shallowRef(false);
|
|
108
|
+
let spriteDuration = shallowRef(props.duration);
|
|
109
|
+
let blinkAnim = shallowRef(null);
|
|
110
|
+
let blinkAnimCache = reactive({});
|
|
111
|
+
let sAnimationToken = shallowRef(0);
|
|
112
|
+
|
|
113
|
+
const _removeKeyFrame = (names_array) => {
|
|
114
|
+
if (keyFrameStyleSheet) {
|
|
115
|
+
keyFrameStyleSheet.removeMultiRules(names_array);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const _clearExpiredKeyFrames = () => {
|
|
120
|
+
if (keyFrameNames.valid) {
|
|
121
|
+
_removeKeyFrame([keyFrameNames.clip, keyFrameNames.image]);
|
|
122
|
+
keyFrameNames.valid = false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
onUnmounted(() => {
|
|
127
|
+
_clearExpiredKeyFrames()
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
const _getAnimNameBase = () => {
|
|
131
|
+
return props.spriteName ? props.spriteName : `sprite-anim-name-${sAnimationToken.value++}`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const _updateFrozeFrameCache = (image_url, frame_info_list,
|
|
135
|
+
canvas_width, canvas_height,
|
|
136
|
+
source_width, source_height) => {
|
|
137
|
+
const cache = frozeFrameCache;
|
|
138
|
+
|
|
139
|
+
const index = stopFrame.value === "start" ? 0 : frame_info_list.length - 1;
|
|
140
|
+
const tr = _getTransformInfo(
|
|
141
|
+
frame_info_list[index].source,
|
|
142
|
+
frame_info_list[index].target,
|
|
143
|
+
canvas_width,
|
|
144
|
+
canvas_height
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
cache.clipStyle = {
|
|
148
|
+
transform: _createTransformStyle(tr.csw, tr.csh, tr.cx, tr.cy),
|
|
149
|
+
transformOrigin: TRANSFORM_ORIGIN_LEFT_TOP.value,
|
|
150
|
+
overflow: "hidden",
|
|
151
|
+
left: 0,
|
|
152
|
+
top: 0,
|
|
153
|
+
width: canvas_width,
|
|
154
|
+
height: canvas_height,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
cache.transStyle = {
|
|
158
|
+
transformOrigin: TRANSFORM_ORIGIN_LEFT_TOP.value,
|
|
159
|
+
transform: _createTransformStyle(tr.sw, tr.sh, tr.x, tr.y),
|
|
160
|
+
width: source_width,
|
|
161
|
+
height: source_height,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
cache.imageStyle = {
|
|
165
|
+
backgroundImage: image_url,
|
|
166
|
+
width: source_width,
|
|
167
|
+
height: source_height,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const _updateAnimateFrameCache = (image_url, frame_info_list,
|
|
172
|
+
canvas_width, canvas_height,
|
|
173
|
+
source_width, source_height) => {
|
|
174
|
+
_clearExpiredKeyFrames();
|
|
175
|
+
|
|
176
|
+
if (!frame_info_list) { return; }
|
|
177
|
+
const anim_name_base = _getAnimNameBase();
|
|
178
|
+
const frame_percent = 1 / (frame_info_list.length);
|
|
179
|
+
const anim_name_clip = `${anim_name_base}-clip`;
|
|
180
|
+
const anim_name_image = `${anim_name_base}-image`;
|
|
181
|
+
let image_keyframs = `@keyframes ${anim_name_image} {`;
|
|
182
|
+
let clip_keyframs = `@keyframes ${anim_name_clip} {`;
|
|
183
|
+
|
|
184
|
+
for (let i = 0; i < frame_info_list.length + 1; i++) {
|
|
185
|
+
let item;
|
|
186
|
+
if (i !== frame_info_list.length) {
|
|
187
|
+
item = frame_info_list[i];
|
|
188
|
+
} else {
|
|
189
|
+
// 追加一个最后一帧以保证最后一帧可见
|
|
190
|
+
item = frame_info_list[frame_info_list.length - 1];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Header
|
|
194
|
+
let header;
|
|
195
|
+
if (i !== frame_info_list.length) {
|
|
196
|
+
header = `${parseFloat(frame_percent * i * 100).toFixed(2)}% {`;
|
|
197
|
+
} else {
|
|
198
|
+
header = '100% {';
|
|
199
|
+
}
|
|
200
|
+
image_keyframs += header;
|
|
201
|
+
clip_keyframs += header;
|
|
202
|
+
|
|
203
|
+
if (item.source) {
|
|
204
|
+
const tr = _getTransformInfo(item.source, item.target, canvas_width, canvas_height);
|
|
205
|
+
const clip_trans = _createTransformStyle(tr.csw, tr.csh, tr.cx, tr.cy);
|
|
206
|
+
const image_trans = _createTransformStyle(tr.sw, tr.sh, tr.x, tr.y);
|
|
207
|
+
|
|
208
|
+
let tr_str = "";
|
|
209
|
+
tr_str = `${tr_str}transform:${clip_trans};transform-origin:left top;`;
|
|
210
|
+
clip_keyframs += tr_str;
|
|
211
|
+
|
|
212
|
+
tr_str = "";
|
|
213
|
+
tr_str = `${tr_str}transform:${image_trans};transform-origin:left top;`;
|
|
214
|
+
image_keyframs += tr_str;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
image_keyframs += '}';
|
|
218
|
+
clip_keyframs += '}';
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
image_keyframs += '}';
|
|
222
|
+
clip_keyframs += '}';
|
|
223
|
+
|
|
224
|
+
if (keyFrameStyleSheet) {
|
|
225
|
+
keyFrameStyleSheet.insertRule(image_keyframs);
|
|
226
|
+
keyFrameStyleSheet.insertRule(clip_keyframs);
|
|
227
|
+
|
|
228
|
+
// 记录Keyframe设置,以便于界面关闭时进行清理
|
|
229
|
+
keyFrameNames.clip = anim_name_clip;
|
|
230
|
+
keyFrameNames.image = anim_name_image;
|
|
231
|
+
keyFrameNames.valid = true;
|
|
232
|
+
}
|
|
233
|
+
const cache = animateFrameCache;
|
|
234
|
+
|
|
235
|
+
cache.clipAnimName = `${anim_name_base}-clip`;
|
|
236
|
+
cache.imageAnimName = `${anim_name_base}-image`;
|
|
237
|
+
|
|
238
|
+
cache.clipStyle = {
|
|
239
|
+
overflow: "hidden",
|
|
240
|
+
width: canvas_width,
|
|
241
|
+
height: canvas_height,
|
|
242
|
+
transform: null, // 重置 transform,以免影响keyframe动画
|
|
243
|
+
transformOrigin: TRANSFORM_ORIGIN_LEFT_TOP.value,
|
|
244
|
+
animation: null, // 外部设置,需要时间和loop信息
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
cache.transStyle = {
|
|
248
|
+
transform: null, // 重置 transform,以免影响keyframe动画
|
|
249
|
+
transformOrigin: TRANSFORM_ORIGIN_LEFT_TOP.value,
|
|
250
|
+
animation: null, // 外部设置,需要时间和loop信息
|
|
251
|
+
width: source_width,
|
|
252
|
+
height: source_height,
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
cache.imageStyle = {
|
|
256
|
+
backgroundImage: image_url,
|
|
257
|
+
width: source_width,
|
|
258
|
+
height: source_height,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const _IsAutoStart = () => {
|
|
263
|
+
let autoStart = false;
|
|
264
|
+
if (typeof props.autostart === "boolean") {
|
|
265
|
+
autoStart = props.autostart;
|
|
266
|
+
} if (typeof props.autostart === "string" && props.autostart !== "none") {
|
|
267
|
+
autoStart = true;
|
|
268
|
+
}
|
|
269
|
+
return autoStart;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
const _AnalyzeProp = () => {
|
|
274
|
+
const used = props.controller && props.controller.Used;
|
|
275
|
+
if (props.spriteInfo.frames.length === 1 || (!used && !_IsAutoStart()) || stopped.value) {
|
|
276
|
+
// 单图模式
|
|
277
|
+
// 解析图片信息
|
|
278
|
+
_updateFrozeFrameCache(
|
|
279
|
+
props.imageUrl,
|
|
280
|
+
props.spriteInfo.frames,
|
|
281
|
+
props.viewSize.w,
|
|
282
|
+
props.viewSize.h,
|
|
283
|
+
props.spriteInfo.meta.size.w,
|
|
284
|
+
props.spriteInfo.meta.size.h
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
return {
|
|
288
|
+
clipStyle: frozeFrameCache.clipStyle,
|
|
289
|
+
transStyle: frozeFrameCache.transStyle,
|
|
290
|
+
imageStyle: frozeFrameCache.imageStyle,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
// 动画模式
|
|
296
|
+
if (animateFrameCache.imageStyle.backgroundImage !== props.imageUrl) {
|
|
297
|
+
// 解析图片信息
|
|
298
|
+
_updateAnimateFrameCache(
|
|
299
|
+
props.imageUrl,
|
|
300
|
+
props.spriteInfo.frames,
|
|
301
|
+
props.viewSize.w,
|
|
302
|
+
props.viewSize.h,
|
|
303
|
+
props.spriteInfo.meta.size.w,
|
|
304
|
+
props.spriteInfo.meta.size.h
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// 使用duration和loop信息更新动画设定
|
|
309
|
+
animateFrameCache.clipStyle.animation =
|
|
310
|
+
`${animateFrameCache.clipAnimName} ${spriteDuration.value}s steps(1,end) ${props.loop}`;
|
|
311
|
+
animateFrameCache.transStyle.animation =
|
|
312
|
+
`${animateFrameCache.imageAnimName} ${spriteDuration.value}s steps(1,end) ${props.loop}`;
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
clipStyle: animateFrameCache.clipStyle,
|
|
316
|
+
transStyle: animateFrameCache.transStyle,
|
|
317
|
+
imageStyle: animateFrameCache.imageStyle,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
let transform_style = reactive(_AnalyzeProp());
|
|
321
|
+
|
|
322
|
+
watch(props, (n, o) => {
|
|
323
|
+
transform_style = _AnalyzeProp();
|
|
324
|
+
})
|
|
325
|
+
const onAnimEndDelegate = () => {
|
|
326
|
+
// 在onAnimEnd之前进行Stop,以防onAnimEnd内部继续发生别的操作
|
|
327
|
+
stopped.value = true;
|
|
328
|
+
if (props.onAnimEnd) {
|
|
329
|
+
props.onAnimEnd();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const onBlinkAnimEnd = () => {
|
|
334
|
+
// 在onAnimEnd之前进行Stop,以防onAnimEnd内部继续发生别的操作
|
|
335
|
+
blinkAnim.value = null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const op = {
|
|
339
|
+
start: (end_frame, duration) => {
|
|
340
|
+
if (props.spriteInfo.frames && props.spriteInfo.frames.length === 1) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
innerId.value += 1;
|
|
344
|
+
stopped.value = false;
|
|
345
|
+
spriteDuration.value = duration || props.duration;
|
|
346
|
+
stopFrame.value = end_frame || stopFrame.value;
|
|
347
|
+
},
|
|
348
|
+
stop: (end_frame) => {
|
|
349
|
+
if (props.spriteInfo.frames && props.spriteInfo.frames.length === 1) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
stopped.value = true;
|
|
353
|
+
stopFrame.value = end_frame || stopFrame.value;
|
|
354
|
+
},
|
|
355
|
+
blink: (alphas, duration, ease, delay, repeat) => {
|
|
356
|
+
// 注意:比较数组是否相同仅在此场景下使用toString,其他场景
|
|
357
|
+
if (!blinkAnimCache
|
|
358
|
+
|| (blinkAnimCache.alphas.toString() !== alphas.toString()
|
|
359
|
+
|| blinkAnimCache.duration !== duration
|
|
360
|
+
|| blinkAnimCache.ease !== ease
|
|
361
|
+
|| blinkAnimCache.delay !== delay
|
|
362
|
+
|| blinkAnimCache.repeat !== repeat)) {
|
|
363
|
+
const anim_name_base = _getAnimNameBase();
|
|
364
|
+
const anim_name_blink = `${anim_name_base}-blink`;
|
|
365
|
+
let image_keyframs = `@keyframes ${anim_name_blink} {`;
|
|
366
|
+
const frame_percent = 1 / (alphas.length);
|
|
367
|
+
for (let i = 0; i < alphas.length; i++) {
|
|
368
|
+
const alpha = alphas[i];
|
|
369
|
+
let header;
|
|
370
|
+
if (i !== alphas.length - 1) {
|
|
371
|
+
header = `${parseFloat(frame_percent * i * 100).toFixed(2)}% {`;
|
|
372
|
+
} else {
|
|
373
|
+
header = '100% {';
|
|
374
|
+
}
|
|
375
|
+
image_keyframs += header;
|
|
376
|
+
|
|
377
|
+
if (alpha) {
|
|
378
|
+
const tr_str = ` opacity:${alpha};`;
|
|
379
|
+
image_keyframs += tr_str;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
image_keyframs += '}';
|
|
383
|
+
image_keyframs += "\n";
|
|
384
|
+
}
|
|
385
|
+
image_keyframs += '}';
|
|
386
|
+
if (keyFrameStyleSheet) {
|
|
387
|
+
keyFrameStyleSheet.insertRule(image_keyframs);
|
|
388
|
+
}
|
|
389
|
+
blinkAnimCache = {
|
|
390
|
+
alphas,
|
|
391
|
+
duration,
|
|
392
|
+
ease,
|
|
393
|
+
delay,
|
|
394
|
+
repeat,
|
|
395
|
+
blinkAnimName: anim_name_blink
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// 参数格式化
|
|
400
|
+
ease = ease || "";
|
|
401
|
+
delay = delay || 0;
|
|
402
|
+
repeat = (repeat === -1) ? "infinite" : (repeat || 1);
|
|
403
|
+
|
|
404
|
+
const animName = `${blinkAnimCache.blinkAnimName} ${duration}s ${ease} ${delay}s ${repeat}`;
|
|
405
|
+
blinkAnim.value = animName;
|
|
406
|
+
stopped.value = true;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
};
|
|
410
|
+
//TODO:
|
|
411
|
+
props.controller?._setSpriteImg(op);
|
|
412
|
+
</script>
|
|
413
|
+
|
|
414
|
+
<template>
|
|
415
|
+
<div id="canvas">
|
|
416
|
+
<div id="clip" :style="{ ...transform_style.clipStyle }">
|
|
417
|
+
<div id="trans" :style="{ ...transform_style.transStyle }" @animationend="onAnimEndDelegate">
|
|
418
|
+
<div id="image" :style="{ ...transform_style.imageStyle, animation: blinkAnim }"
|
|
419
|
+
@animationend="onBlinkAnimEnd"></div>
|
|
420
|
+
</div>
|
|
421
|
+
</div>
|
|
422
|
+
</div>
|
|
423
|
+
</template>
|
|
424
|
+
|
|
425
|
+
<style scoped>
|
|
426
|
+
@keyframes sprite-tag {}
|
|
427
|
+
</style>
|