@shijiu/jsview-vue 2.3.0 → 2.3.151-test.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/bin/browser/BrowserAudio.vue.mjs +4 -1
- package/bin/jsview-vue.mjs +2200 -466
- package/bin/types/utils/JsViewEngineWidget/JsvFocus/JsvFocusHub.d.ts +21 -1
- package/bin/types/utils/JsViewEngineWidget/MetroWidget/RenderItem.d.ts +5 -1
- package/bin/types/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.d.ts +2 -1
- package/bin/types/utils/JsViewEngineWidget/WidgetCommon.d.ts +10 -7
- package/bin/types/utils/JsViewVueTools/ForgeHandles.d.ts +1 -0
- package/bin/types/utils/JsViewVueTools/JsvRuntimeBridge.d.ts +37 -1
- package/bin/types/utils/JsViewVueTools/JsvTextureStore/CapturedTexture/CapturedTexture.d.ts +3 -3
- package/bin/types/utils/JsViewVueTools/JsvTextureStore/DominantColor/GetDominantColor.d.ts +7 -0
- package/bin/types/utils/JsViewVueTools/JsvTextureStore/JsvTextureStore.d.ts +14 -1
- package/bin/types/utils/JsViewVueTools/JsvTextureStore/Store.d.ts +2 -0
- package/bin/types/utils/JsViewVueTools/JsvTextureStore/Texture.d.ts +4 -0
- package/bin/types/utils/JsViewVueWidget/JsvDashPath.vue.d.ts +11 -0
- package/bin/types/utils/JsViewVueWidget/JsvFragShaderView/JsvFragShaderView.vue.d.ts +2 -1
- package/bin/types/utils/JsViewVueWidget/JsvSmoothSlideContainer.vue.d.ts +72 -0
- package/bin/types/utils/JsViewVueWidget/JsvSoundPool.d.ts +26 -0
- package/bin/types/utils/JsViewVueWidget/JsvSwiper/JsvSmoothSwiper.vue.d.ts +112 -0
- package/bin/types/utils/JsViewVueWidget/JsvSwiper/JsvSwiper2.vue.d.ts +142 -0
- package/bin/types/utils/JsViewVueWidget/JsvSwiper/index.d.ts +3 -1
- package/bin/types/utils/JsViewVueWidget/JsvTextureAnim/JsvTextureAnim.vue.d.ts +2 -2
- package/bin/types/utils/JsViewVueWidget/index.d.ts +2 -1
- package/package.json +1 -1
- package/utils/JsViewEngineWidget/JsvFocus/JsvFocusHub.ts +27 -1
- package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +35 -3
- package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +736 -386
- package/utils/JsViewEngineWidget/MetroWidget/RenderItem.ts +13 -2
- package/utils/JsViewEngineWidget/MetroWidget/TaskManager.ts +38 -26
- package/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.ts +144 -73
- package/utils/JsViewEngineWidget/WidgetCommon.ts +12 -0
- package/utils/JsViewPlugin/JsvAudio/BrowserAudio/BrowserAudio.vue +4 -0
- package/utils/JsViewPlugin/JsvAudio/BrowserAudio/JsvSystemAudio.vue +13 -13
- package/utils/JsViewPlugin/JsvPlayer/BrowserJsvPlayer.vue +1 -1
- package/utils/JsViewVueTools/FeatureActive.ts +2 -1
- package/utils/JsViewVueTools/ForgeHandles.ts +5 -2
- package/utils/JsViewVueTools/JsvRuntimeBridge.js +97 -1
- package/utils/JsViewVueTools/JsvTextTools.ts +3 -1
- package/utils/JsViewVueTools/JsvTextureStore/CapturedTexture/CapturedTexture.ts +15 -12
- package/utils/JsViewVueTools/JsvTextureStore/DominantColor/GetDominantColor.ts +36 -0
- package/utils/JsViewVueTools/JsvTextureStore/JsvTextureStore.ts +23 -2
- package/utils/JsViewVueTools/JsvTextureStore/Store.ts +33 -21
- package/utils/JsViewVueTools/JsvTextureStore/Texture.ts +56 -41
- package/utils/JsViewVueWidget/JsvDashPath.vue +150 -0
- package/utils/JsViewVueWidget/JsvFlexCell/JsvFullScrAdjust.vue +3 -1
- package/utils/JsViewVueWidget/JsvFragShaderView/JsvFragShaderView.vue +26 -22
- package/utils/JsViewVueWidget/JsvFreeMoveActor/SetAction.ts +1 -1
- package/utils/JsViewVueWidget/JsvInput/JsvInput.vue +1 -0
- package/utils/JsViewVueWidget/JsvPreload/JsvPreload.vue +2 -2
- package/utils/JsViewVueWidget/JsvSmoothSlideContainer.vue +108 -0
- package/utils/JsViewVueWidget/JsvSoundPool.js +75 -12
- package/utils/JsViewVueWidget/JsvSwiper/JsvSmoothSwiper.vue +543 -0
- package/utils/JsViewVueWidget/JsvSwiper/JsvSwiper.vue +3 -3
- package/utils/JsViewVueWidget/JsvSwiper/JsvSwiper2.vue +644 -0
- package/utils/JsViewVueWidget/JsvSwiper/index.js +3 -1
- package/utils/JsViewVueWidget/JsvTextureAnim/JsvTextureAnim.vue +14 -8
- package/utils/JsViewVueWidget/index.js +2 -1
|
@@ -0,0 +1,644 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* @file
|
|
3
|
+
*
|
|
4
|
+
* 【模块 export 内容】
|
|
5
|
+
* JsvSwiper:Vue高阶组件,图片轮播组件
|
|
6
|
+
* props说明:
|
|
7
|
+
* showIndicator {boolean} 是否显示指示点,默认显示
|
|
8
|
+
* dotSize {int} 指示点大小,默认为10px
|
|
9
|
+
* dotGap {int} 指示点之间间隔,默认为10px
|
|
10
|
+
* indicatorPos {int} 指示点位置, 横向时为距顶端的位置,默认为高的80%;
|
|
11
|
+
纵向时为距左端的位置,默认为宽的80%
|
|
12
|
+
* indicatorAlign {String} 指示面板的 align, 值为 start / middle / end,默认为middle
|
|
13
|
+
* totalFrame {int} (必需)item 的个数
|
|
14
|
+
* firstFrame {int} 初始 item 的 index,默认为0
|
|
15
|
+
* layoutInfo {Object} (必需)组件的大小及位置 {top: 0, left: 0, width: 0, height: 0}
|
|
16
|
+
* onClick {Function} 点击事件 function () {}
|
|
17
|
+
* onChange {Function} 滚动事件 function (index) {}
|
|
18
|
+
* onEdge {Function} 到达边缘事件 ({direction: EdgeDirection}) => Void
|
|
19
|
+
* autoplayInterval {int} 自动滚动的时间(毫秒),等于0时不自动滚动, 默认为5000
|
|
20
|
+
* animation {Object} 滚动动画设置 {duration: 0, easing: "linear"}
|
|
21
|
+
* vertical {boolean} 组件是否为纵向的,默认为 false
|
|
22
|
+
* name {String} 组件获得焦点的 name
|
|
23
|
+
* onFocus {Function} 获得焦点的回调
|
|
24
|
+
* onBlur {Function} 失去焦点的回调
|
|
25
|
+
* swipeType {String} 切换方式,目前只支持 translate,之后可能会添加 opacity 等方式
|
|
26
|
+
* smoothTranslate {boolean} 平滑模式动画开关
|
|
27
|
+
* reverseSwipe {boolean} 反转滚动方向,默认值为false. 默认滚动方向是正向, 既向index增大的方向, 反转后为反向, 既向index减小的方向
|
|
28
|
+
* disableLoopWhenFocus {boolean} 获焦时按键是否循环滚动
|
|
29
|
+
* public methods:
|
|
30
|
+
* slideTo
|
|
31
|
+
* @description 滚动到指定id
|
|
32
|
+
@params {int} id 目标id
|
|
33
|
+
@params {int} 方向, 1为正向, -1为负向
|
|
34
|
+
-->
|
|
35
|
+
|
|
36
|
+
<script setup>
|
|
37
|
+
import { Forge } from "@shijiu/jsview/dom/jsv-forge-define";
|
|
38
|
+
import { EdgeDirection } from "../../JsViewEngineWidget";
|
|
39
|
+
import { ref, computed, watch, onMounted, onBeforeUnmount } from "vue";
|
|
40
|
+
import JsvActorMove, { JsvActorMoveControl } from "../JsvActorMove";
|
|
41
|
+
import JsvVisibleSensor from "../JsvVisibleSensor";
|
|
42
|
+
|
|
43
|
+
function modToRange(value, mod, start = 0) {
|
|
44
|
+
let m = value % mod;
|
|
45
|
+
if (m < start) {
|
|
46
|
+
m += mod;
|
|
47
|
+
} else if (m >= start + mod) {
|
|
48
|
+
m -= mod;
|
|
49
|
+
}
|
|
50
|
+
return m;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const keyCode2EdgeDirection = (keyCode) => {
|
|
54
|
+
switch (keyCode) {
|
|
55
|
+
case 37:
|
|
56
|
+
return EdgeDirection.left;
|
|
57
|
+
case 38:
|
|
58
|
+
return EdgeDirection.top;
|
|
59
|
+
case 39:
|
|
60
|
+
return EdgeDirection.right;
|
|
61
|
+
case 40:
|
|
62
|
+
return EdgeDirection.bottom;
|
|
63
|
+
default:
|
|
64
|
+
console.error("not direction key", keyCode);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// 定义props
|
|
70
|
+
const props = defineProps({
|
|
71
|
+
showIndicator: {
|
|
72
|
+
type: Boolean,
|
|
73
|
+
default: true,
|
|
74
|
+
},
|
|
75
|
+
dotSize: {
|
|
76
|
+
type: Number,
|
|
77
|
+
default: 10,
|
|
78
|
+
},
|
|
79
|
+
dotGap: {
|
|
80
|
+
type: Number,
|
|
81
|
+
default: 10,
|
|
82
|
+
},
|
|
83
|
+
indicatorPos: {
|
|
84
|
+
type: Number,
|
|
85
|
+
default: -1,
|
|
86
|
+
},
|
|
87
|
+
indicatorAlign: {
|
|
88
|
+
type: String,
|
|
89
|
+
validator(value) {
|
|
90
|
+
// The value must match one of these strings
|
|
91
|
+
return ["start", "middle", "end"].includes(value);
|
|
92
|
+
},
|
|
93
|
+
default: "middle",
|
|
94
|
+
},
|
|
95
|
+
totalFrame: {
|
|
96
|
+
type: Number,
|
|
97
|
+
required: true,
|
|
98
|
+
},
|
|
99
|
+
firstFrame: {
|
|
100
|
+
type: Number,
|
|
101
|
+
default: 0,
|
|
102
|
+
},
|
|
103
|
+
layoutInfo: {
|
|
104
|
+
type: Object,
|
|
105
|
+
required: true,
|
|
106
|
+
},
|
|
107
|
+
onClick: {
|
|
108
|
+
type: Function,
|
|
109
|
+
},
|
|
110
|
+
onChange: {
|
|
111
|
+
type: Function,
|
|
112
|
+
},
|
|
113
|
+
onEdge: {
|
|
114
|
+
type: Function,
|
|
115
|
+
},
|
|
116
|
+
autoplayInterval: {
|
|
117
|
+
type: Number,
|
|
118
|
+
default: 5000,
|
|
119
|
+
},
|
|
120
|
+
animation: {
|
|
121
|
+
type: Object,
|
|
122
|
+
default() {
|
|
123
|
+
return {
|
|
124
|
+
duration: 200,
|
|
125
|
+
easing: "linear",
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
vertical: {
|
|
130
|
+
type: Boolean,
|
|
131
|
+
default: false,
|
|
132
|
+
},
|
|
133
|
+
name: {
|
|
134
|
+
type: String,
|
|
135
|
+
},
|
|
136
|
+
onFocus: {
|
|
137
|
+
type: Function,
|
|
138
|
+
},
|
|
139
|
+
onBlur: {
|
|
140
|
+
type: Function,
|
|
141
|
+
},
|
|
142
|
+
swipeType: {
|
|
143
|
+
type: String,
|
|
144
|
+
default: "translate",
|
|
145
|
+
},
|
|
146
|
+
smoothTranslate: {
|
|
147
|
+
type: Boolean,
|
|
148
|
+
default: false,
|
|
149
|
+
},
|
|
150
|
+
reverseSwipe: {
|
|
151
|
+
type: Boolean,
|
|
152
|
+
default: false,
|
|
153
|
+
},
|
|
154
|
+
disableLoopWhenFocus: {
|
|
155
|
+
type: Boolean,
|
|
156
|
+
default: false,
|
|
157
|
+
},
|
|
158
|
+
itemSize: {
|
|
159
|
+
type: Object,
|
|
160
|
+
},
|
|
161
|
+
itemGap: {
|
|
162
|
+
type: Number,
|
|
163
|
+
default: 0,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const innerItemSize = computed(() => {
|
|
168
|
+
return (
|
|
169
|
+
props.itemSize || {
|
|
170
|
+
width: props.layoutInfo.width,
|
|
171
|
+
height: props.layoutInfo.height,
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const visibleCount = computed(() => {
|
|
177
|
+
if (props.vertical) {
|
|
178
|
+
return (
|
|
179
|
+
Math.ceil(
|
|
180
|
+
(props.layoutInfo.height - innerItemSize.value.height) /
|
|
181
|
+
2 /
|
|
182
|
+
(innerItemSize.value.height + props.itemGap)
|
|
183
|
+
) *
|
|
184
|
+
2 +
|
|
185
|
+
1
|
|
186
|
+
);
|
|
187
|
+
} else {
|
|
188
|
+
return (
|
|
189
|
+
Math.ceil(
|
|
190
|
+
(props.layoutInfo.width - innerItemSize.value.width) /
|
|
191
|
+
2 /
|
|
192
|
+
(innerItemSize.value.width + props.itemGap)
|
|
193
|
+
) *
|
|
194
|
+
2 +
|
|
195
|
+
1
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
const viewNum = computed(() => {
|
|
201
|
+
return visibleCount.value + 2;
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// 状态变量
|
|
205
|
+
let controllerList = new Array(viewNum.value);
|
|
206
|
+
if (props.smoothTranslate) {
|
|
207
|
+
for (let i = 0; i < controllerList.length; i++) {
|
|
208
|
+
controllerList[i] = new JsvActorMoveControl();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const focusBlock = ref();
|
|
212
|
+
let preOffset = ref(-1);
|
|
213
|
+
const offset = ref(0);
|
|
214
|
+
const focused = ref(false);
|
|
215
|
+
let timeoutHandler = -1;
|
|
216
|
+
let autoplay = ref(false);
|
|
217
|
+
const element = ref([]);
|
|
218
|
+
|
|
219
|
+
// 计算属性
|
|
220
|
+
const indexList = computed(() => {
|
|
221
|
+
return new Array(props.totalFrame).fill(0).map((_, index) => {
|
|
222
|
+
return index;
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const indicatorLayout = computed(() => {
|
|
227
|
+
let indicatorSize =
|
|
228
|
+
props.totalFrame * (props.dotSize + props.dotGap) - props.dotGap;
|
|
229
|
+
if (props.vertical) {
|
|
230
|
+
let top;
|
|
231
|
+
if (props.indicatorAlign === "start") {
|
|
232
|
+
top = props.dotGap;
|
|
233
|
+
} else if (props.indicatorAlign === "end") {
|
|
234
|
+
top = props.layoutInfo.height - indicatorSize - props.dotGap;
|
|
235
|
+
} else {
|
|
236
|
+
top = (props.layoutInfo.height - indicatorSize) / 2;
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
left:
|
|
240
|
+
props.indicatorPos < 0
|
|
241
|
+
? props.layoutInfo.width * 0.8
|
|
242
|
+
: props.indicatorPos,
|
|
243
|
+
top,
|
|
244
|
+
zIndex: 1,
|
|
245
|
+
};
|
|
246
|
+
} else {
|
|
247
|
+
let left;
|
|
248
|
+
if (props.indicatorAlign === "start") {
|
|
249
|
+
left = props.dotGap;
|
|
250
|
+
} else if (props.indicatorAlign === "end") {
|
|
251
|
+
left = props.layoutInfo.width - indicatorSize - props.dotGap;
|
|
252
|
+
} else {
|
|
253
|
+
left = (props.layoutInfo.width - indicatorSize) / 2;
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
left,
|
|
257
|
+
top:
|
|
258
|
+
props.indicatorPos < 0
|
|
259
|
+
? props.layoutInfo.height * 0.8
|
|
260
|
+
: props.indicatorPos,
|
|
261
|
+
zIndex: 1,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const indicatorDotSize = computed(() => {
|
|
267
|
+
return props.dotSize + props.dotGap;
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const currentDataIndex = computed(() => {
|
|
271
|
+
return modToRange(props.firstFrame + offset.value, props.totalFrame);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const currentViewIndex = computed(() => {
|
|
275
|
+
return modToRange(
|
|
276
|
+
offset.value + Math.floor(viewNum.value / 2),
|
|
277
|
+
viewNum.value
|
|
278
|
+
);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const viewInfoList = computed(() => {
|
|
282
|
+
let viewList = [];
|
|
283
|
+
//计算最左侧view的位置
|
|
284
|
+
let widgetSize = props.vertical
|
|
285
|
+
? props.layoutInfo.height
|
|
286
|
+
: props.layoutInfo.width;
|
|
287
|
+
let itemSize = props.vertical
|
|
288
|
+
? innerItemSize.value.height
|
|
289
|
+
: innerItemSize.value.width;
|
|
290
|
+
let totalSize =
|
|
291
|
+
itemSize * viewNum.value + props.itemGap * (viewNum.value - 1);
|
|
292
|
+
let min = (widgetSize - totalSize) / 2;
|
|
293
|
+
|
|
294
|
+
let centerIndex = Math.floor(viewNum.value / 2);
|
|
295
|
+
for (let i = 0; i < viewNum.value; i++) {
|
|
296
|
+
let pos = modToRange(i - offset.value, viewNum.value);
|
|
297
|
+
const style = {
|
|
298
|
+
top: props.vertical ? min + pos * itemSize + pos * props.itemGap : 0,
|
|
299
|
+
left: props.vertical ? 0 : min + pos * itemSize + pos * props.itemGap,
|
|
300
|
+
width: props.layoutInfo.width,
|
|
301
|
+
height: props.layoutInfo.height,
|
|
302
|
+
};
|
|
303
|
+
//currentDataIndex是中间的那个
|
|
304
|
+
viewList.push({
|
|
305
|
+
dataIndex: modToRange(
|
|
306
|
+
currentDataIndex.value + (pos - centerIndex),
|
|
307
|
+
props.totalFrame
|
|
308
|
+
),
|
|
309
|
+
style: style,
|
|
310
|
+
distanceToCenter: pos - centerIndex,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
return viewList;
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// 监听器
|
|
317
|
+
watch(offset, (newValue) => {
|
|
318
|
+
props.onChange?.(modToRange(props.firstFrame + newValue, props.totalFrame));
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// 监听currentDataIndex的变化
|
|
322
|
+
watch(() => currentDataIndex.value, (newVal, oldVal) => {
|
|
323
|
+
console.log('currentDataIndex变化:', oldVal, '->', newVal);
|
|
324
|
+
// 这里可以添加您需要的逻辑
|
|
325
|
+
// 例如:通知子组件当前索引已更改
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// 方法
|
|
329
|
+
const getFocusBlockRef = () => {
|
|
330
|
+
return focusBlock;
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const stopAutoplay = () => {
|
|
334
|
+
autoplay.value = false;
|
|
335
|
+
clearInterval(timeoutHandler);
|
|
336
|
+
timeoutHandler = -1;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const startAutoplay = () => {
|
|
340
|
+
if (props.autoplayInterval > 0 && props.totalFrame > 1) {
|
|
341
|
+
autoplay.value = true;
|
|
342
|
+
if (timeoutHandler > 0) {
|
|
343
|
+
clearInterval(timeoutHandler);
|
|
344
|
+
}
|
|
345
|
+
timeoutHandler = setInterval(() => {
|
|
346
|
+
_trigger(props.reverseSwipe ? -1 : 1);
|
|
347
|
+
}, props.autoplayInterval);
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
const slideTo = (id, direction = 0) => {
|
|
352
|
+
const curId = modToRange(props.firstFrame + offset.value, props.totalFrame);
|
|
353
|
+
if (curId != id) {
|
|
354
|
+
let d;
|
|
355
|
+
if (direction != 0) {
|
|
356
|
+
d = direction;
|
|
357
|
+
} else {
|
|
358
|
+
d = id - curId;
|
|
359
|
+
}
|
|
360
|
+
_trigger(
|
|
361
|
+
modToRange(
|
|
362
|
+
id - curId,
|
|
363
|
+
props.totalFrame,
|
|
364
|
+
d > 0 ? 0 : -props.totalFrame + 1
|
|
365
|
+
)
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const _onKeyDown = (ev) => {
|
|
371
|
+
let direction = 0;
|
|
372
|
+
switch (ev.keyCode) {
|
|
373
|
+
case 37:
|
|
374
|
+
if (!props.vertical) {
|
|
375
|
+
direction = -1;
|
|
376
|
+
}
|
|
377
|
+
break;
|
|
378
|
+
case 38:
|
|
379
|
+
if (props.vertical) {
|
|
380
|
+
direction = -1;
|
|
381
|
+
}
|
|
382
|
+
break;
|
|
383
|
+
case 39:
|
|
384
|
+
if (!props.vertical) {
|
|
385
|
+
direction = 1;
|
|
386
|
+
}
|
|
387
|
+
break;
|
|
388
|
+
case 40:
|
|
389
|
+
if (props.vertical) {
|
|
390
|
+
direction = 1;
|
|
391
|
+
}
|
|
392
|
+
break;
|
|
393
|
+
case 13:
|
|
394
|
+
props.onClick?.(currentDataIndex.value);
|
|
395
|
+
return true;
|
|
396
|
+
default:
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
//处理方向键
|
|
401
|
+
if (direction !== 0) {
|
|
402
|
+
if (!props.disableLoopWhenFocus) {
|
|
403
|
+
_trigger(direction);
|
|
404
|
+
return true;
|
|
405
|
+
} else {
|
|
406
|
+
if (
|
|
407
|
+
currentDataIndex.value + direction >= 0 &&
|
|
408
|
+
currentDataIndex.value + direction < props.totalFrame
|
|
409
|
+
) {
|
|
410
|
+
_trigger(direction);
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
//未处理方向键
|
|
417
|
+
props.onEdge?.({
|
|
418
|
+
direction: keyCode2EdgeDirection(ev.keyCode),
|
|
419
|
+
rect: {
|
|
420
|
+
x: props.layoutInfo.left,
|
|
421
|
+
y: props.layoutInfo.top,
|
|
422
|
+
width: props.layoutInfo.width,
|
|
423
|
+
height: props.layoutInfo.height,
|
|
424
|
+
},
|
|
425
|
+
});
|
|
426
|
+
return true;
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
const _onAnimationEnd = () => {};
|
|
430
|
+
|
|
431
|
+
const _onFocus = () => {
|
|
432
|
+
focused.value = true;
|
|
433
|
+
stopAutoplay();
|
|
434
|
+
props.onFocus?.();
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
const _onBlur = () => {
|
|
438
|
+
focused.value = false;
|
|
439
|
+
startAutoplay();
|
|
440
|
+
props.onBlur?.();
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
const _getAnimation = (direction, smooth, addListener) => {
|
|
444
|
+
let easing = props.animation.easing ? props.animation.easing : "linear";
|
|
445
|
+
let anim;
|
|
446
|
+
if (smooth) {
|
|
447
|
+
const speed =
|
|
448
|
+
((props.vertical ? props.layoutInfo.height : props.layoutInfo.width) /
|
|
449
|
+
props.animation.duration) *
|
|
450
|
+
1000;
|
|
451
|
+
anim = new Forge.TranslateFrameAnimation(
|
|
452
|
+
props.vertical
|
|
453
|
+
? direction * (props.itemSize.height + props.itemGap)
|
|
454
|
+
: direction * (props.itemSize.width + props.itemGap),
|
|
455
|
+
0,
|
|
456
|
+
speed,
|
|
457
|
+
!props.vertical,
|
|
458
|
+
props.vertical ? 0 : direction * (props.itemSize.width + props.itemGap),
|
|
459
|
+
props.vertical ? direction * (props.itemSize.height + props.itemGap) : 0
|
|
460
|
+
);
|
|
461
|
+
} else {
|
|
462
|
+
anim = new Forge.TranslateAnimation(
|
|
463
|
+
props.vertical ? 0 : direction * (props.itemSize.width + props.itemGap),
|
|
464
|
+
0,
|
|
465
|
+
props.vertical ? direction * (props.itemSize.height + props.itemGap) : 0,
|
|
466
|
+
0,
|
|
467
|
+
props.animation.duration,
|
|
468
|
+
Forge.Easing.str2Easing(easing)
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
if (addListener) {
|
|
472
|
+
anim.SetAnimationListener(
|
|
473
|
+
new Forge.AnimationListener(null, _onAnimationEnd, null)
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
return anim;
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
const _startAnimation = (direction, smooth = false) => {
|
|
480
|
+
switch (props.swipeType) {
|
|
481
|
+
case "translate":
|
|
482
|
+
let startIndex =
|
|
483
|
+
currentViewIndex.value -
|
|
484
|
+
(visibleCount.value - 1) / 2 +
|
|
485
|
+
(direction > 0 ? -1 : 0);
|
|
486
|
+
let endIndex =
|
|
487
|
+
currentViewIndex.value +
|
|
488
|
+
(visibleCount.value - 1) / 2 +
|
|
489
|
+
(direction > 0 ? 0 : 1);
|
|
490
|
+
for (let i = startIndex; i <= endIndex; ++i) {
|
|
491
|
+
element.value?.[
|
|
492
|
+
i == currentViewIndex.value
|
|
493
|
+
? currentViewIndex.value
|
|
494
|
+
: modToRange(i, viewNum.value)
|
|
495
|
+
]
|
|
496
|
+
?.jsvGetProxyView(true)
|
|
497
|
+
.StartAnimation(
|
|
498
|
+
_getAnimation(direction, smooth, i == currentViewIndex.value)
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
break;
|
|
502
|
+
case "opacity":
|
|
503
|
+
break;
|
|
504
|
+
default:
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
const _trigger = (direction) => {
|
|
510
|
+
if (props.totalFrame <= 1) return;
|
|
511
|
+
preOffset.value = offset.value;
|
|
512
|
+
offset.value += direction;
|
|
513
|
+
_startAnimation(direction > 0 ? 1 : -1, props.smoothTranslate);
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
const onBeVisible = (old_h, new_h, old_v, new_v) => {
|
|
517
|
+
if ((old_h && !new_h) || (old_v && !new_h)) {
|
|
518
|
+
stopAutoplay();
|
|
519
|
+
} else if ((!old_h && new_h) || (!old_v && new_h)) {
|
|
520
|
+
if (!focused.value) {
|
|
521
|
+
startAutoplay();
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
// 生命周期钩子
|
|
527
|
+
onMounted(() => {
|
|
528
|
+
if (!focused.value) {
|
|
529
|
+
startAutoplay();
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
onBeforeUnmount(() => {
|
|
534
|
+
stopAutoplay();
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
// 暴露方法给父组件
|
|
538
|
+
defineExpose({
|
|
539
|
+
getFocusBlockRef,
|
|
540
|
+
slideTo,
|
|
541
|
+
});
|
|
542
|
+
</script>
|
|
543
|
+
|
|
544
|
+
<template>
|
|
545
|
+
<jsv-visible-sensor
|
|
546
|
+
:horizonShown="0.2"
|
|
547
|
+
:verticalShown="0.2"
|
|
548
|
+
:width="layoutInfo.width"
|
|
549
|
+
:height="layoutInfo.height"
|
|
550
|
+
:enable="true"
|
|
551
|
+
:callback="onBeVisible"
|
|
552
|
+
></jsv-visible-sensor>
|
|
553
|
+
<jsv-focus-block
|
|
554
|
+
ref="focusBlock"
|
|
555
|
+
:name="name"
|
|
556
|
+
:style="{
|
|
557
|
+
left: layoutInfo.left,
|
|
558
|
+
top: layoutInfo.top,
|
|
559
|
+
width: layoutInfo.width,
|
|
560
|
+
height: layoutInfo.height,
|
|
561
|
+
}"
|
|
562
|
+
:onAction="{
|
|
563
|
+
onFocus: _onFocus,
|
|
564
|
+
onBlur: _onBlur,
|
|
565
|
+
onKeyDown: _onKeyDown,
|
|
566
|
+
}"
|
|
567
|
+
>
|
|
568
|
+
<div
|
|
569
|
+
:style="{
|
|
570
|
+
width: layoutInfo.width,
|
|
571
|
+
height: layoutInfo.height,
|
|
572
|
+
overflow: 'hidden',
|
|
573
|
+
}"
|
|
574
|
+
>
|
|
575
|
+
<div
|
|
576
|
+
:style="{
|
|
577
|
+
zIndex: 0,
|
|
578
|
+
}"
|
|
579
|
+
>
|
|
580
|
+
<div>
|
|
581
|
+
<div
|
|
582
|
+
v-for="(item, index) in viewInfoList"
|
|
583
|
+
:key="index"
|
|
584
|
+
:style="item.style"
|
|
585
|
+
ref="element"
|
|
586
|
+
>
|
|
587
|
+
<!-- 为了保证slot中的页面刷新。不加这个div slot中的img标签不会更新,vue或者是dom的bug? -->
|
|
588
|
+
<div :key="item.dataIndex">
|
|
589
|
+
<slot
|
|
590
|
+
name="itemView"
|
|
591
|
+
:currentIndex="currentDataIndex"
|
|
592
|
+
:dataIndex="item.dataIndex"
|
|
593
|
+
:focused="focused"
|
|
594
|
+
:distanceToCenter="item.distanceToCenter"
|
|
595
|
+
></slot>
|
|
596
|
+
</div>
|
|
597
|
+
<!-- <div
|
|
598
|
+
:style="{
|
|
599
|
+
top: 100,
|
|
600
|
+
width: 50,
|
|
601
|
+
height: 50,
|
|
602
|
+
color: '#0000ff',
|
|
603
|
+
fontSize: 40,
|
|
604
|
+
}"
|
|
605
|
+
>
|
|
606
|
+
{{ index }}
|
|
607
|
+
</div> -->
|
|
608
|
+
</div>
|
|
609
|
+
</div>
|
|
610
|
+
</div>
|
|
611
|
+
|
|
612
|
+
<div v-if="showIndicator" :style="indicatorLayout">
|
|
613
|
+
<div
|
|
614
|
+
v-for="index in indexList"
|
|
615
|
+
:key="index"
|
|
616
|
+
:style="
|
|
617
|
+
vertical
|
|
618
|
+
? { top: indicatorDotSize * index }
|
|
619
|
+
: { left: indicatorDotSize * index }
|
|
620
|
+
"
|
|
621
|
+
>
|
|
622
|
+
<slot
|
|
623
|
+
name="indicatorDot"
|
|
624
|
+
:dataIndex="index"
|
|
625
|
+
:currentIndex="currentDataIndex"
|
|
626
|
+
:focused="focused"
|
|
627
|
+
>
|
|
628
|
+
<div
|
|
629
|
+
:style="{
|
|
630
|
+
width: dotSize,
|
|
631
|
+
height: dotSize,
|
|
632
|
+
backgroundColor:
|
|
633
|
+
index == currentDataIndex
|
|
634
|
+
? 'rgba(50, 50, 50, 1.0)'
|
|
635
|
+
: 'rgba(100, 100, 100, 0.7)',
|
|
636
|
+
borderRadius: Math.round(dotSize / 2) + 'px',
|
|
637
|
+
}"
|
|
638
|
+
></div>
|
|
639
|
+
</slot>
|
|
640
|
+
</div>
|
|
641
|
+
</div>
|
|
642
|
+
</div>
|
|
643
|
+
</jsv-focus-block>
|
|
644
|
+
</template>
|
|
@@ -130,6 +130,11 @@ export default {
|
|
|
130
130
|
},
|
|
131
131
|
deep: true,
|
|
132
132
|
},
|
|
133
|
+
transform: {
|
|
134
|
+
handler(newValue, oldValue) {
|
|
135
|
+
this.innerView.ResetTextureCssTransform(newValue, this.transformOrigin);
|
|
136
|
+
},
|
|
137
|
+
},
|
|
133
138
|
},
|
|
134
139
|
setup() {
|
|
135
140
|
return {
|
|
@@ -253,7 +258,7 @@ export default {
|
|
|
253
258
|
if (normal_end) {
|
|
254
259
|
this.runningState = STATE_END;
|
|
255
260
|
}
|
|
256
|
-
this.onAnimationEnd?.();
|
|
261
|
+
this.onAnimationEnd?.(normal_end);
|
|
257
262
|
},
|
|
258
263
|
|
|
259
264
|
_updateTexCoord() {
|
|
@@ -281,12 +286,12 @@ export default {
|
|
|
281
286
|
}
|
|
282
287
|
},
|
|
283
288
|
|
|
284
|
-
_buildAnimation() {
|
|
285
|
-
if (
|
|
289
|
+
_buildAnimation(a) {
|
|
290
|
+
if (a) {
|
|
286
291
|
let anim = new Forge.CssKeyframeAnimation(
|
|
287
|
-
"@keyframes texAnimDef" +
|
|
292
|
+
"@keyframes texAnimDef" + a,
|
|
288
293
|
this.duration,
|
|
289
|
-
|
|
294
|
+
Forge.Easing.str2Easing(this.easing),
|
|
290
295
|
1,
|
|
291
296
|
1
|
|
292
297
|
);
|
|
@@ -302,9 +307,10 @@ export default {
|
|
|
302
307
|
}
|
|
303
308
|
},
|
|
304
309
|
|
|
305
|
-
start() {
|
|
310
|
+
start(customAnim) {
|
|
306
311
|
if (this.innerView) {
|
|
307
|
-
|
|
312
|
+
const a = customAnim ?? this.animation;
|
|
313
|
+
let anim = this._buildAnimation(a);
|
|
308
314
|
if (anim) {
|
|
309
315
|
this.runningState = STATE_RUNNING;
|
|
310
316
|
this.innerView.StartTextureAnimation(anim);
|
|
@@ -376,7 +382,7 @@ export default {
|
|
|
376
382
|
activated() {
|
|
377
383
|
if (this.innerView && this.runningState == STATE_PAUSED) {
|
|
378
384
|
// 动画未正常结束,重新开始动画
|
|
379
|
-
let anim = this._buildAnimation();
|
|
385
|
+
let anim = this._buildAnimation(this.animation);
|
|
380
386
|
this.innerView.StartTextureAnimation(anim); // pause状态,一定有值
|
|
381
387
|
}
|
|
382
388
|
},
|