@shijiu/jsview-vue 2.2.35 → 2.2.201

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.
Files changed (131) hide show
  1. package/bin/browser/BrowserApic.vue.mjs +4 -3
  2. package/bin/browser/BrowserApic2.vue.mjs +4 -3
  3. package/bin/browser/BrowserApicLib.mjs +10 -3
  4. package/bin/browser/BrowserJsvFragShaderView.vue.mjs +63 -0
  5. package/bin/browser/BrowserQrcode.vue.mjs +3 -1
  6. package/bin/browser/BrowserTextureAnim.vue.mjs +7 -6
  7. package/bin/jsview-vue.mjs +2990 -1146
  8. package/bin/types/JsViewEngineWidget/JsvFocus/JsvFocusManager.d.ts +8 -6
  9. package/bin/types/JsViewEngineWidget/MetroWidget/Dispatcher.d.ts +10 -12
  10. package/bin/types/JsViewEngineWidget/MetroWidget/ListWidget.vue.d.ts +3 -3
  11. package/bin/types/JsViewEngineWidget/MetroWidget/MetroWidget.vue.d.ts +3 -3
  12. package/bin/types/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.d.ts +2 -2
  13. package/bin/types/JsViewEngineWidget/MetroWidget/RenderItem.d.ts +3 -0
  14. package/bin/types/JsViewEngineWidget/MetroWidget/Slide.d.ts +21 -0
  15. package/bin/types/JsViewEngineWidget/TemplateParser/ListMetroTemplate.d.ts +1 -0
  16. package/bin/types/JsViewEngineWidget/TemplateParser/MetroTemplate.d.ts +2 -8
  17. package/bin/types/JsViewEngineWidget/TemplateParser/TemplateItemAdder.d.ts +1 -1
  18. package/bin/types/JsViewEngineWidget/WidgetCommon.d.ts +9 -3
  19. package/bin/types/JsViewEngineWidget/index.d.ts +10 -1
  20. package/bin/types/JsViewVueTools/ConstSymbol.d.ts +2 -0
  21. package/bin/types/JsViewVueTools/ForgeConstDefine.d.ts +11 -0
  22. package/bin/types/JsViewVueTools/JsvFederationTools.d.ts +16 -0
  23. package/bin/types/JsViewVueTools/JsvPerformance.d.ts +5 -0
  24. package/bin/types/JsViewVueTools/JsvPreDownloader.d.ts +33 -0
  25. package/bin/types/JsViewVueTools/JsvRuntimeBridge.d.ts +113 -57
  26. package/bin/types/JsViewVueTools/JsvTextureStore/CapturedTexture/CapturedTexture.d.ts +11 -0
  27. package/bin/types/JsViewVueTools/JsvTextureStore/JsvTextureStore.d.ts +45 -1
  28. package/bin/types/JsViewVueTools/JsvTextureStore/Texture.d.ts +8 -0
  29. package/bin/types/JsViewVueTools/index.d.ts +19 -11
  30. package/bin/types/JsViewVueWidget/JsvApic/JsvApic/BrowserApic.vue.d.ts +1 -1
  31. package/bin/types/JsViewVueWidget/JsvApic/JsvApic/JsvApic.vue.d.ts +1 -1
  32. package/bin/types/JsViewVueWidget/JsvApic/JsvApic2/BrowserApic2.vue.d.ts +1 -1
  33. package/bin/types/JsViewVueWidget/JsvApic/JsvApic2/JsvApic2.vue.d.ts +1 -1
  34. package/bin/types/JsViewVueWidget/JsvApic/JsvBrowserApicLib/Viewer.d.ts +2 -1
  35. package/bin/types/JsViewVueWidget/JsvClipDiv/JsvClipDiv.vue.d.ts +70 -0
  36. package/bin/types/JsViewVueWidget/JsvClipDiv/index.d.ts +1 -0
  37. package/bin/types/JsViewVueWidget/JsvConnectLine/JsvConnectLine.vue.d.ts +1 -1
  38. package/bin/types/JsViewVueWidget/JsvDriftScope/JsvDriftScope.vue.d.ts +104 -0
  39. package/bin/types/JsViewVueWidget/JsvDriftScope/index.d.ts +1 -0
  40. package/bin/types/JsViewVueWidget/JsvFragShaderView/BrowserJsvFragShaderView.vue.d.ts +13 -0
  41. package/bin/types/JsViewVueWidget/JsvFragShaderView/JsvFragShaderView.vue.d.ts +13 -0
  42. package/bin/types/JsViewVueWidget/JsvFragShaderView/index.d.ts +2 -0
  43. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/ActionRefObject.d.ts +4 -0
  44. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/ActorControl.d.ts +91 -0
  45. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/ActorState.d.ts +6 -0
  46. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/CallbackManager.d.ts +11 -0
  47. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/ForgeTypeDefine.d.ts +15 -0
  48. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/FreeMoveActor.vue.d.ts +6 -0
  49. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/SetAction.d.ts +71 -0
  50. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/SetCondition.d.ts +97 -0
  51. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/SetState.d.ts +62 -0
  52. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/SyncLinkManager.d.ts +18 -0
  53. package/bin/types/JsViewVueWidget/JsvFreeMoveActor/index.d.ts +4 -1
  54. package/bin/types/JsViewVueWidget/JsvLine/JsvLine.vue.d.ts +1 -1
  55. package/bin/types/JsViewVueWidget/JsvNativeSharedDiv.vue.d.ts +66 -28
  56. package/bin/types/JsViewVueWidget/JsvNinePatch.vue.d.ts +2 -0
  57. package/bin/types/JsViewVueWidget/JsvScrollBox/JsvScrollBox.vue.d.ts +236 -0
  58. package/bin/types/JsViewVueWidget/JsvScrollBox/JsvScrollFollow.vue.d.ts +153 -0
  59. package/bin/types/JsViewVueWidget/JsvScrollBox/ScrollInnerSymbol.d.ts +4 -0
  60. package/bin/types/JsViewVueWidget/JsvScrollBox/ScrollSymbol.d.ts +12 -0
  61. package/bin/types/JsViewVueWidget/JsvScrollBox/index.d.ts +3 -0
  62. package/bin/types/JsViewVueWidget/JsvTextBox.vue.d.ts +3 -3
  63. package/bin/types/JsViewVueWidget/index.d.ts +4 -0
  64. package/package.json +1 -1
  65. package/tools/config/rollup.config.mjs +1 -0
  66. package/utils/JsViewEngineWidget/JsvFocus/{JsvFocusManager.js → JsvFocusManager.ts} +12 -12
  67. package/utils/JsViewEngineWidget/MetroWidget/Dispatcher.ts +20 -0
  68. package/utils/JsViewEngineWidget/MetroWidget/ListWidget.vue +27 -10
  69. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +52 -11
  70. package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +686 -480
  71. package/utils/JsViewEngineWidget/MetroWidget/RenderItem.ts +13 -1
  72. package/utils/JsViewEngineWidget/MetroWidget/Slide.ts +56 -0
  73. package/utils/JsViewEngineWidget/MetroWidget/TaskManager.ts +59 -10
  74. package/utils/JsViewEngineWidget/MetroWidget/TokenGenerator.ts +10 -0
  75. package/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.ts +20 -10
  76. package/utils/JsViewEngineWidget/TemplateParser/ListMetroTemplate.ts +27 -3
  77. package/utils/JsViewEngineWidget/TemplateParser/MetroTemplate.ts +25 -35
  78. package/utils/JsViewEngineWidget/TemplateParser/TemplateItemAdder.ts +7 -0
  79. package/utils/JsViewEngineWidget/WidgetCommon.ts +20 -7
  80. package/utils/JsViewEngineWidget/{index.js → index.ts} +1 -1
  81. package/utils/JsViewPlugin/JsvAudio/AudioProxy.js +21 -2
  82. package/utils/JsViewPlugin/JsvPlayer/BrowserJsvPlayer.vue +13 -1
  83. package/utils/JsViewPlugin/JsvPlayer/JsvPlayer.vue +470 -338
  84. package/utils/JsViewVueTools/ConstSymbol.ts +3 -0
  85. package/utils/JsViewVueTools/ForgeConstDefine.ts +11 -0
  86. package/utils/JsViewVueTools/JsvPreDownloader.ts +3 -3
  87. package/utils/JsViewVueTools/JsvRuntimeBridge.js +172 -50
  88. package/utils/JsViewVueTools/JsvTextureStore/CapturedTexture/CapturedTexture.ts +62 -0
  89. package/utils/JsViewVueTools/JsvTextureStore/JsvTextureStore.ts +42 -8
  90. package/utils/JsViewVueTools/JsvTextureStore/Texture.ts +15 -1
  91. package/utils/JsViewVueTools/index.js +19 -17
  92. package/utils/JsViewVueWidget/JsvApic/JsvApic/BrowserApic.vue +8 -8
  93. package/utils/JsViewVueWidget/JsvApic/JsvApic/JsvApic.vue +3 -3
  94. package/utils/JsViewVueWidget/JsvApic/JsvApic2/BrowserApic2.vue +7 -8
  95. package/utils/JsViewVueWidget/JsvApic/JsvApic2/JsvApic2.vue +3 -3
  96. package/utils/JsViewVueWidget/JsvApic/JsvBrowserApicLib/ApicDataBase.js +5 -1
  97. package/utils/JsViewVueWidget/JsvApic/JsvBrowserApicLib/Viewer.js +8 -3
  98. package/utils/JsViewVueWidget/JsvClipDiv/JsvClipDiv.vue +42 -0
  99. package/utils/JsViewVueWidget/JsvClipDiv/index.ts +1 -0
  100. package/utils/JsViewVueWidget/JsvConnectLine/JsvConnectLine.vue +5 -1
  101. package/utils/JsViewVueWidget/JsvDriftScope/JsvDriftScope.vue +82 -0
  102. package/utils/JsViewVueWidget/JsvDriftScope/index.ts +1 -0
  103. package/utils/JsViewVueWidget/JsvFragShaderView/BrowserJsvFragShaderView.vue +48 -0
  104. package/utils/JsViewVueWidget/JsvFragShaderView/JsvFragShaderView.vue +145 -0
  105. package/utils/JsViewVueWidget/JsvFragShaderView/index.js +18 -0
  106. package/utils/JsViewVueWidget/JsvFreeMoveActor/ActionRefObject.ts +1 -1
  107. package/utils/JsViewVueWidget/JsvFreeMoveActor/ActorControl.ts +156 -55
  108. package/utils/JsViewVueWidget/JsvFreeMoveActor/ActorState.ts +4 -4
  109. package/utils/JsViewVueWidget/JsvFreeMoveActor/CallbackManager.ts +6 -6
  110. package/utils/JsViewVueWidget/JsvFreeMoveActor/ForgeTypeDefine.ts +1 -1
  111. package/utils/JsViewVueWidget/JsvFreeMoveActor/FreeMoveActor.vue +43 -9
  112. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetAction.ts +33 -0
  113. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetCondition.ts +69 -8
  114. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetState.ts +60 -0
  115. package/utils/JsViewVueWidget/JsvFreeMoveActor/SyncLinkManager.ts +120 -0
  116. package/utils/JsViewVueWidget/JsvFreeMoveActor/index.js +7 -0
  117. package/utils/JsViewVueWidget/JsvMaskClipDiv.vue +6 -1
  118. package/utils/JsViewVueWidget/JsvNativeSharedDiv.vue +121 -68
  119. package/utils/JsViewVueWidget/JsvNinePatch.vue +17 -2
  120. package/utils/JsViewVueWidget/JsvPosterImage.vue +22 -9
  121. package/utils/JsViewVueWidget/JsvQrcode/BrowserQrcode.vue +6 -2
  122. package/utils/JsViewVueWidget/JsvScrollBox/JsvScrollBox.vue +518 -0
  123. package/utils/JsViewVueWidget/JsvScrollBox/JsvScrollFollow.vue +468 -0
  124. package/utils/JsViewVueWidget/JsvScrollBox/ScrollInnerSymbol.ts +9 -0
  125. package/utils/JsViewVueWidget/JsvScrollBox/ScrollSymbol.ts +24 -0
  126. package/utils/JsViewVueWidget/JsvScrollBox/index.ts +3 -0
  127. package/utils/JsViewVueWidget/JsvTextBox.vue +12 -4
  128. package/utils/JsViewVueWidget/JsvTextureAnim/BrowserTextureAnim.vue +9 -6
  129. package/utils/JsViewVueWidget/JsvTextureAnim/JsvTextureAnim.vue +2 -0
  130. package/utils/JsViewVueWidget/index.js +4 -0
  131. package/utils/JsViewEngineWidget/MetroWidget/Dispatcher.js +0 -19
@@ -27,10 +27,14 @@ import { RenderItem } from "./RenderItem";
27
27
  import { VisibleInfo } from "./VisibleInfo";
28
28
  import { WidgetRectInfo } from "./WidgetRectInfo";
29
29
  import ActorControl from "../../JsViewVueWidget/JsvFreeMoveActor/ActorControl.ts";
30
- import { TaskType, SlideAnimWrapper, TaskManager, AnimationManager } from "./TaskManager.ts";
30
+ import { TaskType, SlideAnimWrapper, TaskManager, AnimationManager, SlideTaskType } from "./TaskManager.ts";
31
+ import { getDirectionByRect, RectCache } from "./Slide.ts";
32
+ import { ForgeConst } from "../../JsViewVueTools/ForgeConstDefine.ts";
31
33
 
32
34
  const TAG = "MetroWidget";
33
35
 
36
+ let metroWidgetTokenGen = 1;
37
+
34
38
  const _getMetroTemplate = function (
35
39
  widgetRectInfo,
36
40
  direction,
@@ -109,7 +113,7 @@ export const setup = (
109
113
  };
110
114
 
111
115
  let innerKeepTraceRange = 0;
112
- if (typeof props.keepTraceRange > 0) {
116
+ if (typeof props.keepTraceRange == "number" && props.keepTraceRange > 0) {
113
117
  innerKeepTraceRange = props.keepTraceRange;
114
118
  } else {
115
119
  if (props.touchFlag > 0) {
@@ -125,25 +129,38 @@ export const setup = (
125
129
  const mode = {
126
130
  _mode: FOCUS_MODE,
127
131
  _touchState: TouchState.IDLE,
132
+ _touchCount: 0, // 触控流流程ID,解决fling等事件晚于新的touchDown时引起的混乱问题
128
133
 
129
134
  _duringTouch: false,
130
135
  _duringFling: false,
131
- touchStart() {
136
+ touchStart(touchCount) {
132
137
  this._mode = TOUCH_MODE;
133
138
  modeForExport.value = TOUCH_MODE;
134
139
  this._touchState = TouchState.TAP;
140
+ this._touchCount = touchCount;
135
141
  },
136
- touchEnd() {
137
- this._touchState = TouchState.IDLE;
142
+ touchEnd(touchCount) {
143
+ if (touchCount == this._touchCount) {
144
+ this._touchState = TouchState.IDLE;
145
+ }
138
146
  },
139
- flingStart() {
140
- this._touchState = TouchState.FLING;
147
+ flingStart(touchCount) {
148
+ if (touchCount == this._touchCount) {
149
+ this._touchState = TouchState.FLING;
150
+ }
141
151
  },
142
- flingEnd() { },
143
- dragStart() {
144
- this._touchState = TouchState.DRAG;
152
+ flingEnd(touchCount) {
153
+ if (touchCount == this._touchCount) {
154
+ this._touchState = TouchState.IDLE;
155
+ }
156
+ },
157
+ dragStart(touchCount) {
158
+ if (touchCount == this._touchCount) {
159
+ this._touchState = TouchState.DRAG;
160
+ }
161
+ },
162
+ dragEnd(touchCount) {
145
163
  },
146
- dragEnd() { },
147
164
  keyDown() {
148
165
  this._mode = FOCUS_MODE;
149
166
  modeForExport.value = FOCUS_MODE;
@@ -173,7 +190,6 @@ export const setup = (
173
190
  let preEdgeRect = null;
174
191
  let isFocus = false;
175
192
  let vertical = props.direction == VERTICAL;
176
- let preAnchorItemIndex = -1;
177
193
  let templateItemAdder = null;
178
194
  let permanentItemList = [];
179
195
  let mounted = false;
@@ -182,11 +198,14 @@ export const setup = (
182
198
  let childSlideEventLock = false;
183
199
  let onKeyDownLock = false;
184
200
  let visibleInfo = new VisibleInfo();
185
- let preSlideDirection = 0;
186
201
  let alreadyCallItemFocus = false;
187
202
  let innerSlideSetting = props.slideSetting
188
203
  const currentFocusIndex = ref(0);
189
204
 
205
+ // 当sliderDiv变化时,渲染端在响应此变化前的gap记录,用于准确计算getVisibleStart
206
+ let freeMoveSlideGapTop = 0;
207
+ let freeMoveSlideGapLeft = 0;
208
+
190
209
  const DEFAULT_ANIMATION_DURATION = 200;
191
210
 
192
211
  const isItemVisible = (item) => {
@@ -196,125 +215,185 @@ export const setup = (
196
215
  && item.templateInfo[pos_key] + item.templateInfo[size_key] - 1 < visibleInfo.end;
197
216
  }
198
217
 
199
- let templateCacheFrameCount = -1;
200
- const onMacroTaskEnd = (taskList) => {
201
- let resizeList = [];
218
+ //tools
219
+ const lastOfArray = (array) => {
220
+ if (array instanceof Array && array.length > 0) {
221
+ return array[array.length - 1]
222
+ }
223
+ return null;
224
+ }
225
+
226
+ const onAddTask = (allTask) => {
227
+ if (!innerData || innerData.length <= 0) { return; }
202
228
  let resizeTaskMap = {};
203
- let slideTask = null;
204
229
  //统一处理itemResize和slide动画
205
230
  let minIndex = Infinity;
206
- let slideInfo = null;
207
231
  let mergeTmp = false;
208
232
  let anchorInfo = null;
209
- let duration = 200;
210
- let easing = null;
211
233
 
212
234
  let pos_key = vertical ? "top" : "left";
213
235
  let size_key = vertical ? "height" : "width";
214
- let doAnim = false;
215
236
 
216
- let existOnFocusChange = false;
217
237
  let targetVisibleStart = visibleInfo.start;
238
+ let slideDoAnim = false;
218
239
 
219
- //先遍历寻找slide task, 确认目标位置. 有多个slide task时取最后一个
220
- taskList.forEach(i => {
221
- if (i.type == TaskType.SLIDE) {
222
- slideTask = i;
223
- mergeTmp = mergeTmp || i.params?.updateParam?.mergeTmp;
224
- if (!isNaN(i.params?.target)) {
225
- targetVisibleStart = -i.params.target;
226
- }
227
- }
228
- });
240
+ mRectCache.cacheManually();
229
241
 
230
- for (let task of taskList) {
231
- if (task.type == TaskType.RESIZE_ITEM) {
232
- mergeTmp = mergeTmp || task.params?.updateParam?.mergeTmp;
242
+ /**
243
+ * 处理resize
244
+ */
245
+ let resizeAnimInfo = {
246
+ doAnim: false,
247
+ duration: 200,
248
+ easing: "",
249
+ }
250
+ let resizeList = allTask.resize.concat();
251
+ if (resizeList.length > 0) {
252
+ //resize
253
+ resizeList.forEach(task => {
233
254
  resizeTaskMap[task.params.index] = task;
234
- resizeList.push(task);
235
255
  const { index, animInfo } = task.params;
236
- doAnim = doAnim || !!animInfo;
256
+ if (animInfo) {
257
+ resizeAnimInfo.doAnim = true;
258
+ resizeAnimInfo.duration = animInfo.duration ?? resizeAnimInfo.duration;
259
+ resizeAnimInfo.easing = animInfo.duration ?? "";
260
+ }
237
261
  minIndex = Math.min(minIndex, index);
238
262
 
239
- duration = task.params.animInfo?.duration ?? duration;
240
- easing = task.params.animInfo?.easing ?? easing;
263
+ metroTemplate.updateItemSize(task.params.index, {
264
+ width: task.params.width,
265
+ height: task.params.height,
266
+ })
267
+ });
241
268
 
242
- if (index == id2Index(focusId) && typeof animInfo?.anchor != "undefined") {
243
- //记录锚点信息
244
- const item = getItemByIndex(index);
245
- anchorInfo = {
246
- anchorPosition: item.templateInfo[pos_key] + item.templateInfo[size_key] * animInfo.anchor - 1 - targetVisibleStart,
247
- anchor: animInfo.anchor,
269
+ //使用上一帧的状态计算anchorPosition
270
+ if (resizeTaskMap[id2Index(focusId)]) {
271
+ const task = resizeTaskMap[id2Index(focusId)];
272
+ const animInfo = task.params.animInfo;
273
+ if (typeof animInfo?.anchor == "number") {
274
+ const preRect = getItemById(focusId)?.templateInfo?.layoutCache.getPreRect();
275
+ if (preRect) {
276
+ anchorInfo = {
277
+ anchorPosition: preRect[pos_key] + preRect[size_key] * animInfo.anchor - 1 - visibleInfo.start,
278
+ anchor: animInfo.anchor,
279
+ }
248
280
  }
249
281
  }
250
- } else if (task.type == TaskType.ON_FOCUS_CHANGE) {
251
- existOnFocusChange = true;
252
282
  }
253
283
  }
254
284
 
255
- if (slideTask) {
256
- slideInfo = {
257
- target: slideTask.params.target,
258
- animObj: slideTask.params.animObj,
285
+ /**
286
+ * 获取slide的targetRect
287
+ * 多个slide task取最后一个
288
+ */
289
+
290
+ /* 两种改变方式: 直接指定Position; 通过targetRect计算 */
291
+ let targetRect = null;
292
+ let direction = undefined;
293
+
294
+ let validSlideTask = false;
295
+ if (allTask.slide.length > 0) {
296
+ validSlideTask = true;
297
+ //有滚动时, 取消延时加载
298
+ tryCancelDelayLoad();
299
+ let slideTask = lastOfArray(allTask.slide);
300
+ slideDoAnim = slideTask.params.doAnim;
301
+ switch (slideTask.subType) {
302
+ case SlideTaskType.SLIDE_BY_DIV: {
303
+ const div = slideTask.params.div;
304
+ const item_layout = div.jsvGetRelativePosition(toRaw(locateDiv.value));
305
+ let fakeItem = {
306
+ templateInfo: {
307
+ left: item_layout.left,
308
+ top: item_layout.top,
309
+ width: item_layout.width,
310
+ height: item_layout.height,
311
+ centerYPos: Math.floor(item_layout.top + item_layout.height / 2),
312
+ centerXPos: Math.floor(item_layout.left + item_layout.width / 2),
313
+ index: id2Index(focusId),
314
+ },
315
+ };
316
+ templateItemAdder.tryAddItemByPosition(vertical ? fakeItem.templateInfo.top : fakeItem.templateInfo.left);
317
+ targetRect = fakeItem.templateInfo;
318
+ } break;
319
+ case SlideTaskType.SLIDE_BY_POS: {
320
+ const position = slideTask.params.position;
321
+ templateItemAdder.tryAddItemByPosition(position);
322
+ targetVisibleStart = position;
323
+ } break;
324
+ case SlideTaskType.SLIDE_BY_ITEM: {
325
+ const index = slideTask.params.index;
326
+ templateItemAdder.tryAddItemByIndex(index);
327
+ const targetItem = getItemByIndex(index);
328
+ if (targetItem) {
329
+ if (typeof slideTask.params.direction != "undefined") {
330
+ direction = slideTask.params.direction;
331
+ }
332
+ targetRect = targetItem.templateInfo;
333
+ } else {
334
+ //无效的滚动
335
+ validSlideTask = false;
336
+ }
337
+ } break;
338
+ case SlideTaskType.SLIDE_BY_RECT: {
339
+ if (typeof slideTask.params.direction != "undefined") {
340
+ direction = slideTask.params.direction;
341
+ }
342
+ targetRect = slideTask.params.rect;
343
+ } break;
344
+ default:
345
+ break;
259
346
  }
260
- }
261
347
 
262
- let existItemResize = false;
263
- if (resizeList.length > 0) {
264
- existItemResize = true;
265
- //TODO 应该是尺寸变化后的可视item需要记录位置, 但暂时先记录20个
266
- if (templateCacheFrameCount != Forge.sFrameCount.count) {
267
- metroTemplate.cacheLayout(minIndex, minIndex + 20);
268
- templateCacheFrameCount = Forge.sFrameCount.count;
269
- }
270
- //resize
271
- resizeList.forEach(task => {
272
- metroTemplate.updateItemSize(task.params.index, {
273
- width: task.params.width,
274
- height: task.params.height,
275
- })
276
- });
277
- //保持anchor
348
+ mergeTmp = mergeTmp || slideTask.params?.updateParam?.mergeTmp;
349
+ }
350
+ if (!validSlideTask && resizeList.length > 0) {
351
+ //没有slide任务时, 采用resize的slide位置计算
278
352
  if (anchorInfo) {
353
+ //保持anchor
279
354
  const focusItem = getItemById(focusId);
280
- const start = focusItem.templateInfo[pos_key] + focusItem.templateInfo[size_key] * anchorInfo.anchor - 1 - anchorInfo.anchorPosition;
281
- targetVisibleStart = normalizeVisibleStart(start, focusItem.templateInfo);
355
+ let start = focusItem.templateInfo[pos_key] + focusItem.templateInfo[size_key] * anchorInfo.anchor - 1 - anchorInfo.anchorPosition;
356
+ let totalSize = metroTemplate.getBoundingBoxSize();
357
+ start = Math.min(Math.max(0, start), totalSize[size_key] - visibleInfo.range)
358
+ targetVisibleStart = normalizeVisibleStart(start, focusItem.templateInfo, focusItem.templateInfo.index, visibleInfo);
282
359
  } else {
283
- targetVisibleStart = _calculateVisibleStart(getItemById(focusId).templateInfo, preSlideDirection);
360
+ targetRect = getItemById(focusId).templateInfo;
284
361
  }
285
-
286
- if (visibleInfo.start != targetVisibleStart) {
287
- //只有resize引起的slide动画时, 动画时长使用resize设置, 否者使用slideSetting设置
288
- slideInfo = {
289
- target: -targetVisibleStart,
290
- };
291
- if (doAnim) {
292
- slideInfo.animObj = {
293
- easing: "",
294
- onStart: null,
295
- speed: null,
296
- duration,
297
- }
298
- } else {
299
- //resize无动画时正常slide
300
- if (slideTask) {
301
- slideInfo.animObj = slideTask.params?.animObj
302
- } else {
303
- //默认滚动
304
- slideInfo.animObj = {
305
- //resize无动画时正常slide
306
- easing: "",
307
- onStart: null,
308
- onEnd: null,
309
- speed: innerSlideSetting.Speed,
310
- duration: innerSlideSetting.Duration,
311
- }
312
- }
362
+ slideDoAnim = resizeAnimInfo.doAnim;
363
+ }
364
+
365
+ if (targetRect) {
366
+ const v = visibleInfo.copy();
367
+ let preInfo = null;
368
+ if (resizeList.length > 0) {
369
+ //存在resize时, 需要调整targetRect
370
+ preInfo = mRectCache.getPreRect();
371
+ if (preInfo) {
372
+ let totalSize = metroTemplate.getBoundingBoxSize();
373
+ v.start = Math.min(Math.max(0, targetRect[pos_key] - preInfo[pos_key] + v.start), totalSize[size_key] - v.range);
374
+ preInfo[pos_key] += (v.start - visibleInfo.start);
375
+ }
376
+ }
377
+ targetVisibleStart = _calculateVisibleStart(targetRect, direction, targetRect, v, preInfo);
378
+ } else {
379
+ //resize通过anchor直接设置了visibleStart
380
+ if (resizeList.length > 0) {
381
+ let tRect = getItemById(focusId)?.templateInfo;
382
+ if (tRect) {
383
+ mRectCache.cache({
384
+ left: tRect.left,
385
+ top: tRect.top,
386
+ width: tRect.width,
387
+ height: tRect.height,
388
+ frameCount: Forge.sFrameCount.count,
389
+ })
313
390
  }
314
391
  }
315
392
  }
316
393
 
394
+ let needSlide = false;
317
395
  if (targetVisibleStart != visibleInfo.start) {
396
+ needSlide = true;
318
397
  taskManager.run(() => {
319
398
  const preVisibleStart = visibleInfo.start;
320
399
  visibleInfo.start = targetVisibleStart;
@@ -323,6 +402,7 @@ export const setup = (
323
402
  }
324
403
  });
325
404
  }
405
+
326
406
  //updatePage
327
407
  let updateHandler
328
408
  taskManager.run(() => {
@@ -342,39 +422,41 @@ export const setup = (
342
422
  // resize item 动画
343
423
  if (resizeList.length > 0) {
344
424
  updateHandler.applyTmp();
345
- if (doAnim) {
425
+ if (resizeAnimInfo.doAnim) {
346
426
  const visibleIndexList = Array.from(pageUpdater.getTmpRange());
347
427
  //创建item slide anim
348
428
  for (let index of visibleIndexList) {
349
429
  const renderItem = getItemByIndex(index);
350
430
  const { left, top } = renderItem.templateInfo;
351
431
  if (index >= minIndex) {
352
- const layoutCache = renderItem.templateInfo.layoutCache;
353
- const doItemSlide = (div) => {
354
- taskManager.run(() => {
355
- const cancel = animationManager.startSlideAnim(
356
- div,
357
- [layoutCache.left - left, layoutCache.top - top],
358
- [0, 0],
359
- resizeTaskMap[index] ?
360
- resizeTaskMap[index].params.animInfo
361
- : { duration: duration }
362
- )
363
- return () => {
364
- cancel()
365
- }
366
- });
367
- }
432
+ const layoutCache = renderItem.templateInfo.layoutCache.getPreRect();
433
+ if (layoutCache) {
434
+ const doItemSlide = (div) => {
435
+ taskManager.run(() => {
436
+ const cancel = animationManager.startSlideAnim(
437
+ div,
438
+ [layoutCache.left - left, layoutCache.top - top],
439
+ [0, 0],
440
+ resizeTaskMap[index] ?
441
+ resizeTaskMap[index].params.animInfo
442
+ : { duration: resizeAnimInfo.duration }
443
+ )
444
+ return () => {
445
+ cancel()
446
+ }
447
+ });
448
+ }
368
449
 
369
- if (renderItem.mounted.value) {
370
- doItemSlide(renderItem.rootDiv);
371
- } else {
372
- taskManager.run(() => {
373
- const unregister = renderItem.addDivMountedListener((div) => {
374
- doItemSlide(div);
450
+ if (renderItem.mounted.value) {
451
+ doItemSlide(renderItem.rootDiv);
452
+ } else {
453
+ taskManager.run(() => {
454
+ const unregister = renderItem.addDivMountedListener((div) => {
455
+ doItemSlide(div);
456
+ });
457
+ return unregister;
375
458
  });
376
- return unregister;
377
- });
459
+ }
378
460
  }
379
461
  }
380
462
  }
@@ -382,13 +464,22 @@ export const setup = (
382
464
  }
383
465
 
384
466
  //处理滚动动画
385
- let viewSlid = false;
386
- if (slideInfo) {
387
- viewSlid = executeSlide(slideInfo, updateHandler);
467
+ if (needSlide) {
468
+ let animInfo = undefined;
469
+ if (slideDoAnim) {
470
+ animInfo = {
471
+ easing: null,//resizeAnimInfo.doAnim ? resizeAnimInfo.easing : '' /* innerSlideSetting.Easing */,
472
+ duration: resizeAnimInfo.doAnim ? resizeAnimInfo.duration : innerSlideSetting.Duration,
473
+ speed: innerSlideSetting.Speed,
474
+ onStart: null,
475
+ onEnd: null,
476
+ }
477
+ }
478
+ executeSlide(visibleInfo.start, animInfo, updateHandler)
388
479
  }
389
480
 
390
481
  //回调
391
- if (existItemResize && props.onAllItemResizeDone) {
482
+ if (resizeList.length > 0 && props.onAllItemResizeDone) {
392
483
  taskManager.run(() => {
393
484
  const handler = setTimeout(() => {
394
485
  props.onAllItemResizeDone();
@@ -398,7 +489,7 @@ export const setup = (
398
489
  }
399
490
  })
400
491
  }
401
- if ((viewSlid || existOnFocusChange) && props.onFocusRectChange) {
492
+ if ((needSlide || allTask.focus.length > 0) && props.onFocusRectChange) {
402
493
  taskManager.run(() => {
403
494
  const handler = setTimeout(() => {
404
495
  props.onFocusRectChange();
@@ -409,22 +500,21 @@ export const setup = (
409
500
  })
410
501
  }
411
502
  }
412
- const taskManager = new TaskManager(onMacroTaskEnd);
503
+ const taskManager = new TaskManager(onAddTask);
413
504
  const animationManager = new AnimationManager();
414
505
 
415
- const executeSlide = (slideInfo, updateHandler) => {
506
+ const executeSlide = (target, animObj, updateHandler) => {
416
507
  let preLeft = slideDivLeft.value;
417
508
  let preTop = slideDivTop.value;
418
509
  taskManager.run(() => {
419
- slideDivLeft.value = vertical ? 0 : -visibleInfo.start;
420
- slideDivTop.value = vertical ? -visibleInfo.start : 0;
510
+ slideDivLeft.value = vertical ? 0 : -target;
511
+ slideDivTop.value = vertical ? -target : 0;
421
512
  return () => {
422
513
  slideDivLeft.value = preLeft;
423
514
  slideDivTop.value = preTop;
424
515
  }
425
516
  });
426
- let viewSlid = preLeft != slideDivLeft.value || preTop != slideDivTop.value;
427
- if (slideInfo.animObj) {
517
+ if (animObj) {
428
518
  updateHandler.applyTmp();
429
519
  taskManager.run(() => {
430
520
  const from = vertical ? [0, preTop - slideDivTop.value] : [preLeft - slideDivLeft.value, 0];
@@ -433,7 +523,7 @@ export const setup = (
433
523
  from,
434
524
  [0, 0],
435
525
  {
436
- ...slideInfo.animObj,
526
+ ...animObj,
437
527
  onEnd: () => {
438
528
  updateHandler.apply()
439
529
  }
@@ -454,26 +544,27 @@ export const setup = (
454
544
  clearTimeout(handler);
455
545
  }
456
546
  })
457
- return viewSlid
458
547
  }
459
548
 
460
549
  const updateItemSize = (index, newSize, animInfo) => {
461
- taskManager.addTask(TaskType.RESIZE_ITEM,
462
- {
463
- index,
464
- width: newSize.width,
465
- height: newSize.height,
466
- animInfo,
467
- });
550
+ const item = getItemByIndex(index);
551
+ if (item && (item.templateInfo.width !== newSize.width || item.templateInfo.height !== newSize.height)) {
552
+ taskManager.addTask(TaskType.RESIZE_ITEM,
553
+ {
554
+ index,
555
+ width: newSize.width,
556
+ height: newSize.height,
557
+ animInfo,
558
+ preRect: {
559
+ left: item.templateInfo.left,
560
+ top: item.templateInfo.top,
561
+ width: item.templateInfo.width,
562
+ height: item.templateInfo.height,
563
+ },
564
+ });
565
+ }
468
566
  }
469
567
 
470
- const _slideTo = (target, animObj, updateParam = { mergeTmp: false }) => {
471
- if (slideLock || target == visibleInfo.start) {
472
- return
473
- };
474
- taskManager.addTask(TaskType.SLIDE, { target: -target, animObj, updateParam });
475
- };
476
-
477
568
  let callFocusAfterUpdate = false;
478
569
 
479
570
  //methods
@@ -584,7 +675,7 @@ export const setup = (
584
675
  };
585
676
 
586
677
  const setFocusByUid = (uid, needSlide = true, doAnim = false, extraSetting) => {
587
- if (!uid) { return; }
678
+ if (!uid || innerData.length <= 0) { return; }
588
679
  //添加item
589
680
  templateItemAdder.tryAddItemByUid(uid);
590
681
  const item = metroTemplate.getItemByUid(uid);
@@ -597,7 +688,7 @@ export const setup = (
597
688
  }
598
689
 
599
690
  const setFocusId = (id, needSlide = true, doAnim = false, extraSetting) => {
600
- if (id == focusId) {
691
+ if (id == focusId || innerData.length <= 0) {
601
692
  return;
602
693
  }
603
694
  //有外部触发的滚动时, 取消load
@@ -689,27 +780,6 @@ export const setup = (
689
780
  enterFocusRect = rect;
690
781
  };
691
782
 
692
- const slideTo = (position, doAnim) => {
693
- //有外部触发的滚动时, 取消load
694
- tryCancelDelayLoad();
695
- templateItemAdder.tryAddItemByPosition(position);
696
- if (
697
- typeof position !== "undefined" &&
698
- position != null
699
- ) {
700
- let animObj = null;
701
- if (doAnim) {
702
- animObj = {
703
- easing: innerSlideSetting.Easing,
704
- onStart: null,
705
- speed: innerSlideSetting.Speed,
706
- duration: innerSlideSetting.Duration,
707
- };
708
- }
709
- _slideTo(position, animObj);
710
- }
711
- };
712
-
713
783
  const setZIndex = (index, normalZIndex, focusZIndex) => {
714
784
  const targetItem = getItemByIndex(index);
715
785
  if (targetItem) {
@@ -722,131 +792,200 @@ export const setup = (
722
792
  }
723
793
  }
724
794
 
725
- const slideToItem = (index, doAnim) => {
726
- templateItemAdder.tryAddItemByIndex(index);
727
- const targetItem = getItemByIndex(index);
728
- if (targetItem) {
729
- const direction = index - preAnchorItemIndex >= 0 ? 1 : -1;
730
- const visible_start = _calculateVisibleStart(targetItem.templateInfo, direction);
731
- slideTo(visible_start, doAnim);
795
+ const slideToInner = (position, doAnim, updateParam = { mergeTmp: false }) => {
796
+ if (slideLock || position == (vertical ? slideDivTop.value : slideDivLeft.value)) {
797
+ return
798
+ };
799
+ taskManager.addTask(TaskType.SLIDE, { position, doAnim, updateParam }, SlideTaskType.SLIDE_BY_POS);
800
+ };
801
+
802
+ const slideTo = (position, doAnim) => {
803
+ if (typeof position == "number") {
804
+ slideToInner(position, doAnim);
732
805
  }
733
806
  };
734
807
 
808
+ const slideToItemInner = (index, doAnim, direction = undefined, preItem = undefined) => {
809
+ taskManager.addTask(
810
+ TaskType.SLIDE,
811
+ {
812
+ index,
813
+ doAnim,
814
+ direction,
815
+ preItem,
816
+ },
817
+ SlideTaskType.SLIDE_BY_ITEM);
818
+ };
819
+ const slideToItem = (index, doAnim) => {
820
+ slideToItemInner(index, doAnim)
821
+ }
822
+
735
823
  const slideToDiv = (div, doAnim) => {
736
- //有外部触发的滚动时, 取消load
737
- tryCancelDelayLoad();
824
+ slideToDivInner(div, doAnim);
825
+ }
826
+ const slideToDivInner = (div, doAnim, direction = undefined) => {
738
827
  if (div) {
739
- const item_layout = div.jsvGetRelativePosition(toRaw(locateDiv.value));
740
- const direction = 1;
741
-
742
- let fakeItem = {
743
- templateInfo: {
744
- left: item_layout.left,
745
- top: item_layout.top,
746
- width: item_layout.width,
747
- height: item_layout.height,
748
- centerYPos: Math.floor(item_layout.top + item_layout.height / 2),
749
- centerXPos: Math.floor(item_layout.left + item_layout.width / 2),
750
- index: id2Index(focusId),
828
+ taskManager.addTask(
829
+ TaskType.SLIDE,
830
+ {
831
+ div,
832
+ doAnim,
833
+ direction,
751
834
  },
752
- };
753
-
754
- let cur_slide = _calculateVisibleStart(fakeItem.templateInfo, direction);
755
- if (cur_slide != visibleInfo.start) {
756
- _slideTo(cur_slide, doAnim ? {
757
- easing: "",
758
- onStart: null,
759
- speed: innerSlideSetting.Speed,
760
- duration: innerSlideSetting.Duration,
761
- onEnd: null,
762
- } : null);
763
- }
835
+ SlideTaskType.SLIDE_BY_DIV);
836
+ }
837
+ }
838
+ const slideToRect = (rect, doAnim, direction = undefined) => {
839
+ if (rect
840
+ && typeof rect.left == 'number'
841
+ && typeof rect.top == 'number'
842
+ && typeof rect.width == 'number'
843
+ && typeof rect.height == 'number') {
844
+ taskManager.addTask(
845
+ TaskType.SLIDE,
846
+ {
847
+ rect,
848
+ doAnim,
849
+ direction,
850
+ },
851
+ SlideTaskType.SLIDE_BY_RECT);
764
852
  }
765
853
  }
766
854
 
767
- const refreshData = (force_update) => {
855
+ const DATA_ID_KEY = "jsvKey";
856
+ const refreshData = (forceUpdate) => {
768
857
  //由于data不支持reactive, 因此数据的更新只通过provideData
769
858
  if (!props.provideData) {
770
859
  console.error("refreshData: provideData is null.");
771
860
  return;
772
861
  }
773
- let _force_update = force_update;
774
- if (metroTemplate.size === 0) {
775
- _force_update = true;
776
- }
777
- let new_list = toRaw(props.provideData());
778
- if (focusId >= new_list.length) {
779
- _changeFocusId(new_list.length - 1, false)
780
- }
781
- let new_index = 0;
782
- if (!_force_update) {
783
- for (new_index = 0; new_index < new_list.length; ++new_index) {
784
- let already_add = false;
785
- for (let j = 0; j < innerData.length; ++j) {
786
- if (new_list[new_index] === innerData[j].customerData) {
787
- already_add = true;
788
- break;
862
+ try {
863
+ let newData = toRaw(props.provideData());
864
+ if (newData instanceof Array) {
865
+ let maxSameIndex = -1;
866
+ let layoutChange = false;
867
+ let onlyDataChangeList = [];
868
+ if (focusId >= newData.length) {
869
+ _changeFocusId(newData.length - 1, false)
870
+ }
871
+
872
+ if (!forceUpdate) {
873
+ for (let i = 0; i < dataList.length; ++i) {
874
+ let oldItem = dataList[i];
875
+ let newItem = newData[i];
876
+ if (newItem) {
877
+ if (newItem === oldItem
878
+ || (typeof newItem[DATA_ID_KEY] !== "undefined" && typeof oldItem[DATA_ID_KEY] !== "undefined" && newItem[DATA_ID_KEY] === oldItem[DATA_ID_KEY])) {
879
+ //相同的item
880
+ maxSameIndex = Math.max(maxSameIndex, i);
881
+ } else {
882
+ const newMeasureItem = props.measures(newItem);
883
+ const oldMeasureItem = props.measures(oldItem);
884
+ if (props.layoutType == "relative") {
885
+ layoutChange = newMeasureItem.width !== oldMeasureItem.width || newMeasureItem.height !== oldMeasureItem.height;
886
+ } else {
887
+ layoutChange = newMeasureItem.width !== oldMeasureItem.width || newMeasureItem.height !== oldMeasureItem.height || newMeasureItem.left !== oldMeasureItem.left || newMeasureItem.top !== oldMeasureItem.top;
888
+ }
889
+ if (layoutChange) {
890
+ break;
891
+ } else {
892
+ if (i < innerData.length) {
893
+ onlyDataChangeList.push({
894
+ templateInfo: innerData[i].templateInfo,
895
+ measureObj: newMeasureItem,
896
+ data: newItem,
897
+ index: i,
898
+ });
899
+ }
900
+ }
901
+ }
902
+ } else {
903
+ if (i >= newData.length) {
904
+ //item减少需要布局改变
905
+ layoutChange = true;
906
+ break;
907
+ } else {
908
+ //数据中存在undefined item
909
+ throw new Error("undefined item in data list.", i, newData);
910
+ }
911
+ }
789
912
  }
790
913
  }
791
- if (!already_add) {
792
- break;
914
+
915
+ dataList = newData.concat();
916
+ if (forceUpdate || layoutChange) {
917
+ //需要更新布局
918
+ pageUpdateToken.value++;
919
+ //数据更改
920
+ permanentItemList = [];
921
+ metroTemplate = _getMetroTemplate(
922
+ widgetRectInfo,
923
+ props.direction,
924
+ props.supportHistoryPath,
925
+ props.layoutType,
926
+ templateMode
927
+ );
928
+ innerData = [];
929
+ templateItemAdder = new TemplateItemAdder(
930
+ metroTemplate,
931
+ dataList,
932
+ props.measures,
933
+ pageRange,
934
+ _onTemplateItemAdd,
935
+ props.name,
936
+ _onTemplateAddDone
937
+ );
938
+ if (props.onScroll) {
939
+ templateItemAdder.tryAddItemByIndex(dataList.length - 1);
940
+ } else {
941
+ templateItemAdder.tryAddItemById(focusId);
942
+ }
943
+ } else {
944
+ if (maxSameIndex < newData.length) {
945
+ //追加数据
946
+ templateItemAdder.updateData(newData);
947
+ if (props.onScroll) {
948
+ templateItemAdder.tryAddItemByIndex(dataList.length - 1);
949
+ } else {
950
+ templateItemAdder.tryAddItemById(focusId);
951
+ }
952
+ }
953
+
954
+ //仅用户数据变更
955
+ if (onlyDataChangeList.length > 0) {
956
+ for (let i of onlyDataChangeList) {
957
+ if (i.index < innerData.length) {
958
+ innerData[i.index].updateCustomData(i.data, _getItemConfigFromMeasursObj(i.measureObj));
959
+ } else {
960
+ //之后的数据未布局, 尚未添加到innerData中
961
+ break;
962
+ }
963
+ }
964
+ }
793
965
  }
966
+
967
+ const updater = pageUpdater.update(
968
+ metroTemplate,
969
+ visibleInfo.startWithPadding - innerKeepTraceRange * pageRange,
970
+ visibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
971
+ focusId,
972
+ false,
973
+ permanentItemList
974
+ );
975
+ updater.apply();
976
+ onItemFocus(getItemById(focusId), null);
977
+ let targetRect = mRectCache.getCurRect() ?? mRectCache.getPreRect();
978
+ if (targetRect) {
979
+ slideToRect(targetRect, false);
980
+ } else {
981
+ slideToItem(id2Index(focusId), false);
982
+ }
983
+ //template和slideDivStyle均确定后再次重设box condition
984
+ updateTouchBoxCondition();
794
985
  }
986
+ } catch (e) {
987
+ console.log(TAG, "refresh error", e)
795
988
  }
796
- let need_update_content = false;
797
- if (!_force_update && new_index === metroTemplate.size) {
798
- //原始数据都在
799
- if (new_index !== new_list.length) {
800
- //增加数据
801
- need_update_content = true;
802
- templateItemAdder.updateData(new_list);
803
- } else {
804
- //数据没变
805
- }
806
- } else {
807
- pageUpdateToken.value++;
808
- //数据更改
809
- permanentItemList = [];
810
- need_update_content = true;
811
- metroTemplate = _getMetroTemplate(
812
- widgetRectInfo,
813
- props.direction,
814
- props.supportHistoryPath,
815
- props.layoutType,
816
- templateMode
817
- );
818
- innerData = [];
819
- dataList = new_list;
820
- templateItemAdder = new TemplateItemAdder(
821
- metroTemplate,
822
- dataList,
823
- props.measures,
824
- pageRange,
825
- _onTemplateItemAdd,
826
- props.name,
827
- _onTemplateAddDone
828
- );
829
- }
830
- if (need_update_content) {
831
- if (props.onScroll) {
832
- templateItemAdder.tryAddItemByIndex(dataList.length - 1);
833
- } else {
834
- templateItemAdder.tryAddItemById(focusId);
835
- }
836
- }
837
- const updater = pageUpdater.update(
838
- metroTemplate,
839
- visibleInfo.startWithPadding - innerKeepTraceRange * pageRange,
840
- visibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
841
- focusId,
842
- false,
843
- permanentItemList
844
- );
845
- updater.apply();
846
- onItemFocus(getItemById(focusId), null);
847
- slideToItem(id2Index(focusId), false);
848
- //template和slideDivStyle均确定后再次重设box condition
849
- updateTouchBoxCondition();
850
989
  };
851
990
 
852
991
  const getVisibleItems = () => {
@@ -863,6 +1002,7 @@ export const setup = (
863
1002
  };
864
1003
 
865
1004
  const moveFocus = (direction) => {
1005
+ if (innerData.length <= 0) { return; }
866
1006
  //有外部触发的滚动时, 取消load
867
1007
  tryCancelDelayLoad();
868
1008
  if (direction == "left" || direction == 37 || direction == EdgeDirection.left) {
@@ -1200,7 +1340,7 @@ export const setup = (
1200
1340
  }
1201
1341
  }
1202
1342
 
1203
- const _onTemplateItemAdd = (customerData, templateItem, measuresObj) => {
1343
+ const _getItemConfigFromMeasursObj = (measuresObj) => {
1204
1344
  let focusZIndex = -1,
1205
1345
  normalZIndex = -1;
1206
1346
  if (
@@ -1219,12 +1359,17 @@ export const setup = (
1219
1359
  normalZIndex = measuresObj["zIndex"];
1220
1360
  }
1221
1361
  }
1222
- let itemConfig = {
1362
+ return {
1223
1363
  focusZIndex,
1224
1364
  normalZIndex,
1225
1365
  permanent: measuresObj.permanent ?? false,
1226
1366
  itemSlide: measuresObj.itemSlide ?? METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS,
1367
+ showSkeleton: measuresObj.showSkeleton ?? true,
1227
1368
  };
1369
+ }
1370
+
1371
+ const _onTemplateItemAdd = (customerData, templateItem, measuresObj) => {
1372
+ let itemConfig = _getItemConfigFromMeasursObj(measuresObj);
1228
1373
 
1229
1374
  const renderStyle = reactive({
1230
1375
  left: templateItem.left,
@@ -1323,16 +1468,11 @@ export const setup = (
1323
1468
  },
1324
1469
  };
1325
1470
 
1326
- let cur_slide = _calculateVisibleStart(fakeItem.templateInfo, direction);
1471
+ let cur_slide = _calculateVisibleStart(fakeItem.templateInfo, direction, fakeItem.templateInfo, visibleInfo);
1327
1472
  if (cur_slide != visibleInfo.start) {
1328
- _slideTo(
1473
+ slideToInner(
1329
1474
  cur_slide,
1330
- {
1331
- easing: "",
1332
- onStart: null,
1333
- speed: innerSlideSetting.Speed,
1334
- duration: innerSlideSetting.Duration,
1335
- },
1475
+ true,
1336
1476
  {
1337
1477
  mergeTmp: true
1338
1478
  });
@@ -1344,7 +1484,7 @@ export const setup = (
1344
1484
 
1345
1485
  const _changeFocusId = (id, cache_pre = true) => {
1346
1486
  preFocusId = cache_pre ? focusId : -1;
1347
- focusId = id;
1487
+ focusId = id >= 0 && id < metroTemplate.size ? id : 0;
1348
1488
  currentFocusIndex.value = id2Index(id);
1349
1489
  taskManager.addTask(TaskType.ON_FOCUS_CHANGE);
1350
1490
  }
@@ -1431,22 +1571,12 @@ export const setup = (
1431
1571
  onItemBlur(preFocusItem);
1432
1572
  onItemFocus(next_focus_item, preEdgeRect);
1433
1573
 
1434
-
1435
1574
  if (next_focus_item.itemConfig.itemSlide == METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS) {
1436
- let cur_visible_start = _calculateVisibleStart(
1437
- next_focus_item.templateInfo,
1575
+ slideToItemInner(
1576
+ next_focus_item.index,
1577
+ true,
1438
1578
  vertical ? vertical_direction : horizontal_direction,
1439
- preFocusItem.templateInfo,
1440
- );
1441
- if (visibleInfo.start !== cur_visible_start) {
1442
- let animObj = {
1443
- easing: "",
1444
- onStart: null,
1445
- speed: innerSlideSetting.Speed,
1446
- duration: innerSlideSetting.Duration,
1447
- };
1448
- _slideTo(cur_visible_start, animObj, { mergeTmp: false });
1449
- }
1579
+ preFocusItem);
1450
1580
  } else {
1451
1581
  const updater = pageUpdater.update(
1452
1582
  metroTemplate,
@@ -1505,68 +1635,83 @@ export const setup = (
1505
1635
  }
1506
1636
  };
1507
1637
 
1508
- const normalizeVisibleStart = (origin, targetItem = null) => {
1638
+ const normalizeVisibleStart = (origin, targetRect, index, _visibleInfo) => {
1509
1639
  let pos_key = vertical ? "top" : "left";
1510
1640
  let size_key = vertical ? "height" : "width";
1511
1641
  let visibleStart = origin;
1642
+ let vInfo = _visibleInfo;
1643
+
1512
1644
  if ((innerSlideSetting.BoundaryProtect & SlideSetting.START_PROTECT) > 0) {
1513
- if (visibleInfo.start >= 0) {
1645
+ if (vInfo.start >= 0) {
1514
1646
  let boundary = 0;
1515
1647
  //首个元素是占位符时, 在保证获焦区域完全展示的前提下要保证首个不可获焦元素的完全展示
1516
1648
  const headTemplateInfo = getItemByIndex(0).templateInfo;
1517
1649
  if (
1518
- targetItem
1519
- && (!headTemplateInfo.focusable || targetItem.index == headTemplateInfo.index)
1520
- && targetItem[pos_key] + targetItem[size_key] <=
1521
- visibleInfo.range
1650
+ targetRect
1651
+ && (!headTemplateInfo.focusable || index == headTemplateInfo.index)
1652
+ && targetRect[pos_key] + targetRect[size_key] <=
1653
+ vInfo.range
1522
1654
  ) {
1523
1655
  boundary = headTemplateInfo[size_key];
1524
1656
  }
1525
1657
  visibleStart = visibleStart < boundary ? 0 : visibleStart;
1526
1658
  } else {
1527
1659
  // 以最后一个item的位置作为动态的保护边界
1528
- visibleStart = visibleStart < visibleInfo.start ? visibleInfo.start : visibleStart;
1660
+ visibleStart = visibleStart < vInfo.start ? vInfo.start : visibleStart;
1529
1661
  }
1530
1662
  }
1531
1663
  if ((innerSlideSetting.BoundaryProtect & SlideSetting.END_PROTECT) > 0) {
1532
1664
  let lastTemplateInfo = getItemByIndex(metroTemplate.getTailItemIndex()).templateInfo;
1533
1665
  const lastEnd = lastTemplateInfo[pos_key] + lastTemplateInfo[size_key];
1534
- const lastVisibleStart = Math.max(lastEnd - visibleInfo.range, 0);
1666
+ const lastVisibleStart = Math.max(lastEnd - vInfo.range, 0);
1535
1667
  //边界必须大于等于0, 同时若最后一个缩进时, 边界采用最后一个item的位置
1536
- if (visibleInfo.end <= lastEnd) {
1668
+ if (vInfo.end <= lastEnd) {
1537
1669
  let boundary = lastVisibleStart;
1538
1670
  if (
1539
- targetItem
1540
- && (!lastTemplateInfo.focusable || targetItem.index == lastTemplateInfo.index)
1541
- && targetItem[pos_key] - lastVisibleStart >= 0
1671
+ targetRect
1672
+ && (!lastTemplateInfo.focusable || index == lastTemplateInfo.index)
1673
+ && targetRect[pos_key] - lastVisibleStart >= 0
1542
1674
  ) {
1543
- boundary = lastTemplateInfo[pos_key] - visibleInfo.range;
1675
+ boundary = lastTemplateInfo[pos_key] - vInfo.range;
1544
1676
  }
1545
1677
  visibleStart = visibleStart > boundary ? lastVisibleStart : visibleStart;
1546
1678
  } else {
1547
1679
  // 以最后一个item的位置作为动态的保护边界
1548
- visibleStart = visibleStart > visibleInfo.start ? visibleInfo.start : visibleStart;
1680
+ visibleStart = visibleStart > vInfo.start ? vInfo.start : visibleStart;
1549
1681
  }
1550
1682
  }
1551
1683
  return visibleStart;
1552
1684
  }
1553
1685
 
1554
- let preTemplateInfo = null;
1555
- const _calculateVisibleStart = (targetTemplateInfo, direction, preInfo = null) => {
1556
- if (!targetTemplateInfo) {
1686
+ const mRectCache = new RectCache();
1687
+ const _calculateVisibleStart = (targetRect, _direction, templateInfo, vInfo, preInfo = null) => {
1688
+ if (!targetRect) {
1557
1689
  console.error("MetroWidget: _calculateVisibleStart target item is null");
1558
1690
  return 0;
1559
1691
  }
1692
+ const curRect = {
1693
+ left: targetRect.left,
1694
+ top: targetRect.top,
1695
+ width: targetRect.width,
1696
+ height: targetRect.height,
1697
+ frameCount: Forge.sFrameCount.count,
1698
+ }
1699
+ mRectCache.cache(curRect);
1700
+ let preRect = mRectCache.getPreRect();
1560
1701
  if (preInfo) {
1561
- preTemplateInfo = preInfo;
1702
+ preRect = preInfo;
1703
+ }
1704
+ let direction = _direction;
1705
+ if (typeof direction != "number") {
1706
+ //通过preRect确定direction
1707
+ let d = getDirectionByRect(curRect, preRect);
1708
+ direction = vertical ? d.vertical : d.horizontal;
1562
1709
  }
1563
1710
 
1564
- preSlideDirection = direction;
1565
- preAnchorItemIndex = targetTemplateInfo.index;
1566
1711
  let pos_key = vertical ? "top" : "left";
1567
1712
  let size_key = vertical ? "height" : "width";
1568
1713
  let center_key = vertical ? "centerYPos" : "centerXPos";
1569
- let new_visible_start = visibleInfo.start;
1714
+ let new_visible_start = vInfo.start;
1570
1715
 
1571
1716
  let needCalculate = true;
1572
1717
 
@@ -1577,7 +1722,7 @@ export const setup = (
1577
1722
 
1578
1723
  //首页不滚动
1579
1724
  if (innerSlideSetting.FixFirstPage) {
1580
- if (targetTemplateInfo[pos_key] + targetTemplateInfo[size_key] - 1 < visibleInfo.range) {
1725
+ if (targetRect[pos_key] + targetRect[size_key] - 1 < vInfo.range) {
1581
1726
  new_visible_start = 0;
1582
1727
  needCalculate = false;
1583
1728
  }
@@ -1585,19 +1730,19 @@ export const setup = (
1585
1730
 
1586
1731
  if (needCalculate) {
1587
1732
  new_visible_start = Math.ceil(
1588
- targetTemplateInfo[center_key] -
1589
- visibleInfo.range * innerSlideSetting.FixPercent
1733
+ targetRect[pos_key] + targetRect[size_key] / 2 -
1734
+ vInfo.range * innerSlideSetting.FixPercent
1590
1735
  );
1591
1736
  }
1592
1737
  break;
1593
1738
  case SlideSetting.Type.WHOLE_PAGE:
1594
- if (typeof targetTemplateInfo.pageHeadIndex == "undefined") {
1739
+ if (!templateInfo || typeof templateInfo.pageHeadIndex == "undefined") {
1595
1740
  //TODO 子控制滚动时whole page滚动
1596
1741
  console.error(
1597
1742
  "child controlled whole page slide type is not supported."
1598
1743
  );
1599
1744
  } else {
1600
- new_visible_start = getItemByIndex(targetTemplateInfo.pageHeadIndex)
1745
+ new_visible_start = getItemByIndex(templateInfo.pageHeadIndex)
1601
1746
  .templateInfo[pos_key];
1602
1747
  }
1603
1748
 
@@ -1605,7 +1750,7 @@ export const setup = (
1605
1750
  case SlideSetting.Type.SEAMLESS:
1606
1751
  //首页不滚动
1607
1752
  if (innerSlideSetting.FixFirstPage) {
1608
- if (targetTemplateInfo[pos_key] + targetTemplateInfo[size_key] - 1 < visibleInfo.range) {
1753
+ if (targetRect[pos_key] + targetRect[size_key] - 1 < vInfo.range) {
1609
1754
  new_visible_start = 0;
1610
1755
  needCalculate = false;
1611
1756
  }
@@ -1618,68 +1763,72 @@ export const setup = (
1618
1763
  * end-1.0: 焦点往左时不处理, 往右的时候更新position以保持焦点的end位置一致
1619
1764
  * 重合区域: 保持焦点的中心位置一致
1620
1765
  */
1621
- const rect0Start = visibleInfo.start;
1622
- const rect0End = visibleInfo.start + visibleInfo.range * innerSlideSetting.StartPercent;
1623
- const rect1Start = visibleInfo.start + visibleInfo.range * innerSlideSetting.EndPercent;
1624
- const rect1End = visibleInfo.end;
1625
-
1626
- const itemStart = targetTemplateInfo[pos_key];
1627
- const itemEnd = targetTemplateInfo[pos_key] + targetTemplateInfo[size_key] - 1;
1628
-
1629
- let targetStart;
1630
- let targetEnd;
1631
- if (preTemplateInfo != null) {
1632
- targetStart = preTemplateInfo[pos_key];
1633
- targetEnd = preTemplateInfo[pos_key] + preTemplateInfo[size_key] - 1;
1634
- } else {
1635
- targetStart = rect0End;
1636
- targetEnd = rect1Start;
1637
- }
1638
-
1639
- let rect0Result = undefined;
1640
- let rect1Result = undefined;
1641
- if (itemStart < rect0End) {
1642
- if (targetStart < rect0Start) {
1643
- rect0Result = itemStart;
1644
- } else {
1645
- //inRect0, 只处理往左/往上
1646
- if (direction <= 0) {
1647
- let pre;
1648
- if (targetStart < rect0End) {
1649
- pre = targetStart;
1650
- } else {
1651
- pre = rect0End;
1766
+ const itemStart = targetRect[pos_key];
1767
+ const itemEnd = targetRect[pos_key] + targetRect[size_key] - 1;
1768
+ const itemMainSize = targetRect[size_key];
1769
+
1770
+ if (preRect) {
1771
+ const rect0Start = vInfo.start;
1772
+ const rect0End = vInfo.start + vInfo.range * innerSlideSetting.StartPercent;
1773
+ const rect0Range = rect0End - rect0Start + 1
1774
+ const rect1Start = vInfo.start + vInfo.range * innerSlideSetting.EndPercent;
1775
+ const rect1End = vInfo.start + vInfo.range - 1;
1776
+ const rect1Range = rect1End - rect1Start + 1;
1777
+
1778
+ let target0 = Math.min(preRect[pos_key], rect0End);
1779
+ let target1 = Math.max(preRect[pos_key] + preRect[size_key] - 1, rect1Start);
1780
+
1781
+ let rect0Result = undefined;
1782
+ let rect1Result = undefined;
1783
+
1784
+ //item的head对齐rect0的end
1785
+ if (itemStart < rect0End) {
1786
+ if (target0 < rect0Start) {
1787
+ //preRect位置错误或者item的尺寸大于区域范围(保证item完整显示)
1788
+ // rect0Result = itemStart;
1789
+ } else {
1790
+ if (direction <= 0) {
1791
+ //inRect0, 只处理往左/往上
1792
+ rect0Result = vInfo.start + (itemStart - target0)
1652
1793
  }
1653
- rect0Result = visibleInfo.start + (itemStart - pre);
1654
1794
  }
1655
1795
  }
1656
- }
1657
- if (itemEnd > rect1Start) {
1658
- if (targetEnd > rect1End) {
1659
- rect1Result = itemEnd - visibleInfo.range;
1660
- } else {
1661
- //inRect1, 只处理往右/往下
1662
- let pre;
1663
- if (targetEnd > rect1Start) {
1664
- pre = targetEnd;
1796
+
1797
+ //item的头部对齐rect1的start
1798
+ if (itemEnd > rect1Start) {
1799
+ if (target1 > rect1End) {
1800
+ //preRect位置错误或者item的尺寸大于区域范围(保证item完整显示)
1801
+ // rect1Result = itemEnd - visibleInfo.range;
1665
1802
  } else {
1666
- pre = rect1Start;
1667
- }
1668
- if (direction >= 0) {
1669
- rect1Result = visibleInfo.start + (itemEnd - pre);
1803
+ if (direction >= 0) {
1804
+ //inRect1, 只处理往右/往下
1805
+ rect1Result = vInfo.start + (itemEnd - target1);
1806
+ }
1670
1807
  }
1671
1808
  }
1672
- } else {
1673
- //不移动
1809
+
1810
+ if (typeof rect0Result !== "undefined" && typeof rect1Result !== "undefined") {
1811
+ //重叠区域
1812
+ new_visible_start = rect0Result;
1813
+ } else if (typeof rect0Result !== "undefined") {
1814
+ new_visible_start = rect0Result;
1815
+ } else if (typeof rect1Result !== "undefined") {
1816
+ new_visible_start = rect1Result;
1817
+ }
1674
1818
  }
1675
1819
 
1676
- if (typeof rect0Result !== "undefined" && typeof rect1Result !== "undefined") {
1677
- //重叠区域
1678
- new_visible_start = rect0Result;
1679
- } else if (typeof rect0Result !== "undefined") {
1680
- new_visible_start = rect0Result;
1681
- } else if (typeof rect1Result !== "undefined") {
1682
- new_visible_start = rect1Result;
1820
+ //保证item处于safe area范围
1821
+ const headSafeArea = innerSlideSetting.HeadSafeArea * vInfo.range;
1822
+ const tailSafeArea = innerSlideSetting.TailSafeArea * vInfo.range;
1823
+ if (itemMainSize > vInfo.range - headSafeArea - tailSafeArea) {
1824
+ // 大item
1825
+ new_visible_start = Math.round(itemStart - (vInfo.range - itemMainSize) / 2)
1826
+ } else {
1827
+ if (itemStart < new_visible_start + headSafeArea) {
1828
+ new_visible_start = itemStart - headSafeArea;
1829
+ } else if (itemEnd > new_visible_start + vInfo.range - 1 - tailSafeArea) {
1830
+ new_visible_start = itemEnd - vInfo.range + tailSafeArea;
1831
+ }
1683
1832
  }
1684
1833
  }
1685
1834
  break;
@@ -1690,8 +1839,7 @@ export const setup = (
1690
1839
  );
1691
1840
  }
1692
1841
 
1693
- preTemplateInfo = targetTemplateInfo;
1694
- new_visible_start = normalizeVisibleStart(new_visible_start, targetTemplateInfo);
1842
+ new_visible_start = normalizeVisibleStart(new_visible_start, targetRect, templateInfo?.index, vInfo);
1695
1843
  return Math.round(new_visible_start);
1696
1844
  };
1697
1845
 
@@ -1727,6 +1875,7 @@ export const setup = (
1727
1875
  console.log(`MetroWidget: ${props.name} get focus while data is empty.`);
1728
1876
  return;
1729
1877
  }
1878
+
1730
1879
  let focus_id =
1731
1880
  typeof enterFocusId !== "undefined" &&
1732
1881
  enterFocusId >= 0 &&
@@ -1752,18 +1901,30 @@ export const setup = (
1752
1901
  onItemBlur(getItemById(preFocusId));
1753
1902
  props.onBlur?.();
1754
1903
  isFocus = false;
1904
+ mRectCache.clean()
1755
1905
  };
1756
1906
 
1757
1907
  const _updatePage = (rangeSet) => {
1908
+ let cur = id2Index(focusId);
1909
+ if (cur >= 0) {
1910
+ rangeSet.add(cur)
1911
+ }
1758
1912
  const tmpArray = Array.from(rangeSet);
1759
- renderData.value = tmpArray.map((item) => {
1913
+ let newArray = tmpArray.map((item) => {
1760
1914
  return getItemByIndex(item);
1761
1915
  });
1916
+ const newItemList = newArray.filter((i) => { return !renderData.value?.includes(i) });
1917
+ renderData.value = newArray;
1762
1918
  if (props.enableItemRenderBreak) {
1763
1919
  itemRender.value = false;
1764
- nextTick(() => {
1920
+ const f = () => {
1921
+ // 关闭强制TriggerManualBlock,改为vue内部通过dom的任务数来确定是否执行打断
1922
+ // if (newItemList.length > 12 && props.enableItemRenderBreak) {
1923
+ // window.JsView?.triggerManualBlocker?.();
1924
+ // }
1765
1925
  itemRender.value = true;
1766
- });
1926
+ };
1927
+ nextTick(f);
1767
1928
  }
1768
1929
  };
1769
1930
 
@@ -1808,9 +1969,7 @@ export const setup = (
1808
1969
  let divPos = -1;
1809
1970
  let frameCount = -1;
1810
1971
  const getVisibleStart = (moveInfo) => {
1811
- if (frameCount != Forge.sFrameCount.count) {
1812
- divPos = vertical ? slideDivTop.value : slideDivLeft.value;
1813
- }
1972
+ divPos = vertical ? slideDivTop.value + freeMoveSlideGapTop : slideDivLeft.value + freeMoveSlideGapLeft;
1814
1973
  if (vertical) {
1815
1974
  return -(divPos + Math.round(moveInfo.yPos));
1816
1975
  } else {
@@ -1831,35 +1990,32 @@ export const setup = (
1831
1990
  }
1832
1991
 
1833
1992
  const mergeTouchSlideToSlideDiv = (touchCount) => {
1834
- // console.log("testtest", props.name, `touchToDiv div: ${slideDivTop.value}, visibleStart:${visibleInfo.start} swapCount: ${Forge.sFrameCount.count}`)
1993
+ let originSlideDivTop = slideDivTop.value;
1994
+ let originSlideDivLeft = slideDivLeft.value;
1835
1995
  if (vertical) {
1836
1996
  slideDivTop.value = -visibleInfo.start;
1837
1997
  } else {
1838
1998
  slideDivLeft.value = -visibleInfo.start;
1839
1999
  }
2000
+ let newSlideGapTop = originSlideDivTop - slideDivTop.value;
2001
+ let newSlideGapLeft = originSlideDivLeft - slideDivLeft.value;
2002
+ freeMoveSlideGapTop += newSlideGapTop; // 累计slider变化的gap,等待同步完毕时消除gap
2003
+ freeMoveSlideGapLeft += newSlideGapLeft;
1840
2004
 
1841
2005
  const walls = getTouchWall();
1842
- actorController.run([
1843
- actorController.state().removeConditionByGroup(wallConditionGroup),
1844
- actorController
1845
- .condition(wallConditionGroup, true)
2006
+ actorController.run((cmds) => [
2007
+ cmds.state().removeConditionByGroup(wallConditionGroup),
2008
+ cmds.condition(wallConditionGroup, true)
1846
2009
  .boxPosition(walls.left, walls.top, walls.right, walls.bottom)
1847
- .then([actorController.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
1848
- actorController
1849
- .condition(touchCountGroup, false)
1850
- .touchCount(touchCount)
1851
- .then([
1852
- actorController
1853
- .action()
1854
- .teleportTo(0, 0)
1855
- ])
1856
- ]);
1857
- //下一帧删除touchCount
1858
- actorController.run([
1859
- actorController.condition().onNextTick().then([
1860
- actorController.state().removeConditionByGroup(touchCountGroup),
2010
+ .then([cmds.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
2011
+ cmds.state().setStartOffsetPos(newSlideGapLeft, newSlideGapTop), // 将div的位置调整回馈给FreeMove计量系统
2012
+ cmds.condition().onNextTick(0).then([
2013
+ SliderEditFuncReOrderWrap(() => {
2014
+ freeMoveSlideGapTop -= newSlideGapTop;
2015
+ freeMoveSlideGapLeft -= newSlideGapLeft;
2016
+ }, true) // Slide调整回调要放在其他事件之前,调整slide的gap值
1861
2017
  ])
1862
- ])
2018
+ ]);
1863
2019
  }
1864
2020
 
1865
2021
  const onTouchDown = (data, customData, nexusCustomData) => {
@@ -1870,27 +2026,32 @@ export const setup = (
1870
2026
  //模式切换, 更新boxPosition
1871
2027
  updateTouchBoxCondition();
1872
2028
  }
1873
- mode.touchStart();
1874
- mode.flingEnd();
2029
+ mode.touchStart(touchCount);
1875
2030
  // console.log("touchtest", `${props.name} animId:${debugAnimId} viewId:${debugViewId}`,
1876
2031
  // "onTouchDown", data, customData, nexusCustomData)
1877
- const t = 100;
2032
+
2033
+ // 运动方向锁定机制
2034
+ // 当MetroWidget在某一方向拖动后,讲另一方向的移动进行锁定
2035
+ const lockThreshhold = 10;
2036
+ const unlockThreshold = 100;
1878
2037
  const offsetThreshold = {
1879
- left: vertical ? undefined : t,
1880
- right: vertical ? undefined : t,
1881
- top: vertical ? t : undefined,
1882
- bottom: vertical ? t : undefined,
2038
+ left: vertical ? undefined : lockThreshhold,
2039
+ right: vertical ? undefined : lockThreshhold,
2040
+ top: vertical ? lockThreshhold : undefined,
2041
+ bottom: vertical ? lockThreshhold : undefined,
1883
2042
  }
1884
2043
 
1885
- actorController.run([
1886
- actorController
2044
+ let passDownTouchInfo = nexusCustomData;
2045
+ actorController.run((cmds) => [
2046
+ cmds
1887
2047
  .condition(undefined, false)
1888
2048
  .offsetPosition(offsetThreshold.left, offsetThreshold.top, offsetThreshold.right, offsetThreshold.bottom)
1889
- .then([actorController.state().touchLockSwitch(true, vertical ? 1 : 2, t)]),
1890
- actorController
2049
+ .then([
2050
+ cmds.state().touchLockSwitch(true, vertical ? 1 : 2, unlockThreshold)]),
2051
+ cmds
1891
2052
  .condition(undefined, false)
1892
2053
  .startMove(true, true)
1893
- .then([onDragStart]),
2054
+ .then([SliderEditFuncReOrderWrap((d) => { onDragStart(d, null, passDownTouchInfo) })]),
1894
2055
  ])
1895
2056
 
1896
2057
  //blur item
@@ -1918,28 +2079,30 @@ export const setup = (
1918
2079
  anchorPosList.push(-visibleInfo.start - visibleInfo.range - anchorPos + 1);
1919
2080
  anchorPos += anchorSpacing;
1920
2081
  }
1921
- const reachConditionList = anchorPosList.map(pos => {
1922
- actorController
1923
- .condition(reachAnchorGroup)
1924
- .reachPosition(pos, undefined)
1925
- .then([(data) => { updateRenderItems(true, true) }])
1926
- })
1927
- reachConditionList.unshift(
1928
- actorController.state().removeConditionByGroup(reachAnchorGroup),
1929
- )
1930
- actorController.run(reachConditionList);
2082
+ actorController.run((cmds) => {
2083
+ const reachConditionList = anchorPosList.map(pos => {
2084
+ return cmds
2085
+ .condition(reachAnchorGroup)
2086
+ .reachPosition(pos, undefined)
2087
+ .then([SliderEditFuncReOrderWrap((data) => { updateRenderItems(true, true) })])
2088
+ })
2089
+ reachConditionList.unshift(
2090
+ cmds.state().removeConditionByGroup(reachAnchorGroup),
2091
+ )
2092
+ return reachConditionList
2093
+ });
1931
2094
  }
1932
2095
 
1933
- const onTouchRelease = () => {
2096
+ const onTouchRelease = (touchCount) => {
1934
2097
  if (mode.getTouchState() == TouchState.TAP) {
1935
2098
  //只点击, 没有移动或者fling
1936
2099
  updateRenderItems(false, false);
1937
- mode.touchEnd();
2100
+ mode.touchEnd(touchCount);
1938
2101
  } else {
1939
2102
  if (touchRecorder.moved && !mode.duringFling()) {
1940
2103
  mergeTouchSlideToSlideDiv(touchRecorder.touchCount);
1941
2104
  updateRenderItems(false, false);
1942
- mode.touchEnd()
2105
+ mode.touchEnd(touchCount)
1943
2106
  }
1944
2107
  }
1945
2108
  }
@@ -1947,43 +2110,50 @@ export const setup = (
1947
2110
  const exportOnTouchRelease = props.touchFlag > 0 ? onTouchRelease : undefined;
1948
2111
 
1949
2112
  const onDragStart = (data, customData, nexusCustomData) => {
2113
+ let touchCount = getTouchCount(nexusCustomData); // 注意,由startMove触发的onDragStart是没有touchCount的
1950
2114
  touchRecorder.move();
1951
- mode.dragStart()
2115
+ mode.dragStart(touchCount)
1952
2116
  visibleInfo.start = getVisibleStart(data);
1953
2117
  }
1954
2118
 
1955
2119
  const onDragEnd = (data, customData, nexusCustomData) => {
2120
+ let touchCount = getTouchCount(nexusCustomData);
2121
+ mode.dragEnd(touchCount);
1956
2122
  visibleInfo.start = getVisibleStart(data);
1957
- actorController.run([
1958
- actorController.state().removeConditionByGroup(reachAnchorGroup),
2123
+ actorController.run((cmds) => [
2124
+ cmds.state().removeConditionByGroup(reachAnchorGroup),
1959
2125
  ]);
1960
2126
  }
1961
2127
 
1962
2128
  const onFlingStart = (data, customData, nexusCustomData) => {
2129
+ let touchCount = getTouchCount(nexusCustomData);
1963
2130
  touchRecorder.move();
1964
- mode.flingStart();
2131
+ mode.flingStart(touchCount);
1965
2132
  visibleInfo.start = getVisibleStart(data);
1966
2133
  updateRenderItems(true, true);
1967
2134
  }
1968
2135
 
1969
2136
  const onFlingProgress = (data, customData, nexusCustomData) => {
2137
+ let touchCount = getTouchCount(nexusCustomData);
1970
2138
  visibleInfo.start = getVisibleStart(data);
1971
2139
  updateRenderItems(true, true);
1972
2140
  }
1973
2141
 
1974
2142
  const onFlingEnd = (data, customData, nexusCustomData) => {
2143
+ let touchCount = getTouchCount(nexusCustomData);
1975
2144
  visibleInfo.start = getVisibleStart(data);
1976
2145
  //记录拖拽的距离
1977
2146
  if (mode.duringFling()) {
1978
2147
  let touchCount = getTouchCount(nexusCustomData);
1979
2148
  mergeTouchSlideToSlideDiv(touchCount);
1980
2149
  updateRenderItems(false, false);
1981
- mode.flingEnd();
1982
- mode.touchEnd();
2150
+ mode.flingEnd(touchCount);
2151
+ mode.touchEnd(touchCount);
1983
2152
  }
1984
2153
  }
1985
2154
 
1986
2155
  const onFlingDrop = (data, customData, nexusCustomData) => {
2156
+ let touchCount = getTouchCount(nexusCustomData);
1987
2157
  visibleInfo.start = getVisibleStart(data);
1988
2158
  }
1989
2159
 
@@ -2008,6 +2178,7 @@ export const setup = (
2008
2178
  wall.left = wall.right;
2009
2179
  }
2010
2180
  }
2181
+
2011
2182
  return wall;
2012
2183
  }
2013
2184
 
@@ -2029,12 +2200,12 @@ export const setup = (
2029
2200
  const walls = getTouchWall();
2030
2201
 
2031
2202
  //更新wall设置
2032
- actorController.run([
2033
- actorController.state().removeConditionByGroup(wallConditionGroup),
2034
- actorController
2203
+ actorController.run((cmds) => [
2204
+ cmds.state().removeConditionByGroup(wallConditionGroup),
2205
+ cmds
2035
2206
  .condition(wallConditionGroup, true)
2036
2207
  .boxPosition(walls.left, walls.top, walls.right, walls.bottom)
2037
- .then([actorController.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
2208
+ .then([cmds.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
2038
2209
  ]);
2039
2210
  }
2040
2211
  }
@@ -2054,6 +2225,21 @@ export const setup = (
2054
2225
  }
2055
2226
  };
2056
2227
 
2228
+ const metroWidgetToken = metroWidgetTokenGen++;
2229
+
2230
+ let orderTouchSlideCallbacks;
2231
+ const SliderEditFuncReOrderWrap = (callback, addHeader = false) => {
2232
+ return (...args) => {
2233
+ let pkg = { cb: callback, a: args }
2234
+ if (addHeader) {
2235
+ orderTouchSlideCallbacks.splice(0, 0, pkg);
2236
+ } else {
2237
+ orderTouchSlideCallbacks.push(pkg);
2238
+ }
2239
+ }
2240
+ }
2241
+
2242
+
2057
2243
  //TODO debug
2058
2244
  // let debugAnimId = -1;
2059
2245
  // let debugViewId = -1
@@ -2061,50 +2247,68 @@ export const setup = (
2061
2247
  actorController = new ActorControl();
2062
2248
  const divView = touchDiv.value.jsvGetProxyView();
2063
2249
  actorController.bindForgeView(divView, true);
2064
- divView.DragEnables?.(4 | 0x08 | 0x10); // 只激活drag
2250
+
2251
+ // 对触控回调进行顺序管理
2252
+ orderTouchSlideCallbacks = new Array();
2253
+ actorController.addCondCycleListener(
2254
+ // starter
2255
+ () => {
2256
+ // TODO: condtion回调的开始处理时机,预留函数为了加打印追踪
2257
+ },
2258
+ // finish
2259
+ () => {
2260
+ // 按照排好的顺序,进行cb调用
2261
+ for (let pkg of orderTouchSlideCallbacks) {
2262
+ pkg.cb(...pkg.a);
2263
+ }
2264
+ // 执行结束后进行清理
2265
+ orderTouchSlideCallbacks.length = 0;
2266
+ }
2267
+ )
2268
+
2269
+
2065
2270
  // debugAnimId = actorController.debugGetAnimId();
2066
2271
  // debugViewId = divView.ViewId;
2067
2272
  // console.log("testtest", props.name, `animId:${debugAnimId} viewId:${debugViewId}`);
2068
2273
  const walls = getTouchWall();
2069
2274
  //注册回调
2070
- actorController.run([
2071
- actorController
2275
+ actorController.run((cmds) => [
2276
+ cmds
2072
2277
  .condition(undefined, true)
2073
2278
  .onTouchDown()
2074
- .then([onTouchDown]),
2075
- actorController
2279
+ .then([SliderEditFuncReOrderWrap(onTouchDown)]),
2280
+ cmds
2076
2281
  .condition(undefined, true)
2077
2282
  .onDragStart()
2078
- .then([onDragStart]),
2079
- actorController
2283
+ .then([SliderEditFuncReOrderWrap(onDragStart)]),
2284
+ cmds
2080
2285
  .condition(undefined, true)
2081
2286
  .onDragEnd()
2082
- .then([onDragEnd]),
2083
- actorController
2287
+ .then([SliderEditFuncReOrderWrap(onDragEnd)]),
2288
+ cmds
2084
2289
  .condition(undefined, true)
2085
2290
  .onFlingStart()
2086
- .then([onFlingStart]),
2087
- actorController
2291
+ .then([SliderEditFuncReOrderWrap(onFlingStart)]),
2292
+ cmds
2088
2293
  .condition(undefined, true)
2089
2294
  .onFlingProgress()
2090
- .then([onFlingProgress]),
2091
- actorController
2295
+ .then([SliderEditFuncReOrderWrap(onFlingProgress)]),
2296
+ cmds
2092
2297
  .condition(undefined, true)
2093
2298
  .onFlingEnd()
2094
- .then([onFlingEnd]),
2095
- actorController
2299
+ .then([SliderEditFuncReOrderWrap(onFlingEnd)]),
2300
+ cmds
2096
2301
  .condition(undefined, true)
2097
2302
  .onFlingDrop()
2098
- .then([onFlingDrop]),
2099
- actorController
2303
+ .then([SliderEditFuncReOrderWrap(onFlingDrop)]),
2304
+ cmds
2100
2305
  .condition(undefined, true)
2101
2306
  .onTouchRelease()
2102
- .then([actorController.state().touchLockSwitch(false, vertical ? 1 : 2)]),
2103
-
2104
- actorController
2307
+ .then([cmds.state().touchLockSwitch(false, vertical ? 1 : 2)]),
2308
+ cmds
2105
2309
  .condition(wallConditionGroup, true)
2106
2310
  .boxPosition(walls.left, walls.top, walls.right, walls.bottom)
2107
- .then([actorController.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
2311
+ .then([cmds.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
2108
2312
  ]);
2109
2313
  }
2110
2314
 
@@ -2139,7 +2343,7 @@ export const setup = (
2139
2343
  }
2140
2344
 
2141
2345
  let init_focus_id = 0;
2142
- let cur_visible_start = 0;
2346
+ let initVisibleStart = 0;
2143
2347
 
2144
2348
  if (typeof props.initFocusId == "number") {
2145
2349
  templateItemAdder.tryAddItemById(props.initFocusId);
@@ -2147,18 +2351,19 @@ export const setup = (
2147
2351
  if (item) {
2148
2352
  init_focus_id = props.initFocusId;
2149
2353
  if (item.itemConfig.itemSlide == METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS) {
2150
- cur_visible_start = _calculateVisibleStart(item.templateInfo, 0);
2354
+ initVisibleStart = _calculateVisibleStart(item.templateInfo, 0, item.templateInfo, visibleInfo);
2151
2355
  }
2152
2356
  }
2153
2357
  }
2154
2358
  focusId = init_focus_id;
2155
- visibleInfo.start = cur_visible_start;
2156
2359
 
2157
- //保证创建速度, 你描画一屏
2360
+ let initVisibleInfo = visibleInfo.copy();
2361
+ initVisibleInfo.start = initVisibleStart;
2362
+ //保证创建速度, 先描画一屏
2158
2363
  const initUpdater = pageUpdater.update(
2159
2364
  metroTemplate,
2160
- visibleInfo.startWithPadding,
2161
- visibleInfo.endWithPadding,
2365
+ initVisibleInfo.startWithPadding,
2366
+ initVisibleInfo.endWithPadding,
2162
2367
  0,
2163
2368
  false,
2164
2369
  permanentItemList
@@ -2168,8 +2373,8 @@ export const setup = (
2168
2373
  const delayLoadHandler = setTimeout(() => {
2169
2374
  const updateHandler = pageUpdater.update(
2170
2375
  metroTemplate,
2171
- visibleInfo.startWithPadding - innerKeepTraceRange * pageRange,
2172
- visibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
2376
+ initVisibleInfo.startWithPadding - innerKeepTraceRange * pageRange,
2377
+ initVisibleInfo.endWithPadding + innerKeepTraceRange * pageRange,
2173
2378
  focusId,
2174
2379
  false,
2175
2380
  permanentItemList
@@ -2183,8 +2388,8 @@ export const setup = (
2183
2388
  onMounted(() => {
2184
2389
  _changeFocusId(focusId, false);
2185
2390
  mounted = true;
2186
- if (visibleInfo.start) {
2187
- _slideTo(visibleInfo.start, null);
2391
+ if (initVisibleStart) {
2392
+ slideToInner(initVisibleStart, false);
2188
2393
  }
2189
2394
  if (isFocus && !alreadyCallItemFocus) {
2190
2395
  onItemFocus(getItemById(focusId), preEdgeRect);
@@ -2203,6 +2408,7 @@ export const setup = (
2203
2408
  onUpdated(() => { });
2204
2409
 
2205
2410
  onBeforeUnmount(() => {
2411
+ taskManager.cancelAllTask();
2206
2412
  tryCancelDelayLoad();
2207
2413
  mounted = false;
2208
2414
  });