@shijiu/jsview-vue 2.1.200 → 2.1.339-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.
Files changed (120) hide show
  1. package/bin/browser/BrowserApic.vue.mjs +124 -0
  2. package/bin/browser/BrowserApic2.vue.mjs +118 -0
  3. package/bin/browser/BrowserApicLib.mjs +424 -0
  4. package/bin/browser/BrowserAudio.vue.mjs +263 -0
  5. package/bin/browser/BrowserJsvLatex.vue.mjs +110 -0
  6. package/bin/browser/BrowserJsvPlayer.vue.mjs +573 -0
  7. package/bin/browser/BrowserPreload.vue.mjs +154 -0
  8. package/bin/browser/BrowserQrcode.vue.mjs +178 -0
  9. package/bin/browser/BrowserSpray.vue.mjs +66 -0
  10. package/bin/browser/BrowserTextureAnim.vue.mjs +324 -0
  11. package/bin/export-sfc.mjs +12 -0
  12. package/bin/jsview-common.mjs +39 -0
  13. package/bin/jsview-vue.mjs +21106 -0
  14. package/index.js +3 -4
  15. package/package.json +1 -2
  16. package/tools/config/rollup.config.mjs +52 -0
  17. package/tools/config/tsconfig.json +18 -0
  18. package/tools/config/vite.config.ts +60 -0
  19. package/tools/jsview-vue-build.mjs +125 -0
  20. package/utils/JsViewEngineWidget/{JsvFocusBlock.vue → JsvFocus/JsvFocusBlock.vue} +11 -11
  21. package/utils/JsViewEngineWidget/{JsvFocusHub.ts → JsvFocus/JsvFocusHub.ts} +9 -3
  22. package/utils/JsViewEngineWidget/{JsvFocusManager.js → JsvFocus/JsvFocusManager.js} +6 -5
  23. package/utils/JsViewEngineWidget/MetroWidget/AnimationManager.ts +33 -10
  24. package/utils/JsViewEngineWidget/MetroWidget/ListWidget.vue +89 -57
  25. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +118 -62
  26. package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +504 -60
  27. package/utils/JsViewEngineWidget/MetroWidget/RenderItem.ts +11 -1
  28. package/utils/JsViewEngineWidget/MetroWidget/SlotComponent.vue +13 -0
  29. package/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.ts +1 -1
  30. package/utils/JsViewEngineWidget/TemplateParser/ListMetroTemplate.ts +1 -1
  31. package/utils/JsViewEngineWidget/TemplateParser/MetroTemplate.ts +34 -1
  32. package/utils/JsViewEngineWidget/TemplateParser/TemplateItemAdder.ts +52 -11
  33. package/utils/JsViewEngineWidget/index.js +3 -3
  34. package/utils/JsViewPlugin/JsvAudio/AudioProxy.js +9 -0
  35. package/utils/JsViewPlugin/JsvAudio/BrowserAudio/BrowserAudio.vue +11 -3
  36. package/utils/JsViewPlugin/JsvAudio/JsvAudio.vue +1 -0
  37. package/utils/JsViewPlugin/JsvAudio/JsvAudioBridgeProxy.js +8 -0
  38. package/utils/JsViewPlugin/JsvAudio/ScreenLockManager.js +16 -0
  39. package/utils/JsViewPlugin/JsvAudio/version.js +3 -3
  40. package/utils/JsViewPlugin/JsvAudio/version.mjs +3 -3
  41. package/utils/JsViewPlugin/JsvLatex/index.js +1 -1
  42. package/utils/JsViewPlugin/JsvPlayer/JsvPlayer.vue +1 -1
  43. package/utils/JsViewPlugin/JsvPlayer/index-0.9.js +3 -3
  44. package/utils/JsViewPlugin/JsvPlayer/index.js +2 -2
  45. package/utils/JsViewVueTools/DebugTool.js +2 -2
  46. package/utils/JsViewVueTools/DefaultKeyMap.js +1 -1
  47. package/utils/JsViewVueTools/JsvDynamicCssStyle.js +1 -1
  48. package/utils/JsViewVueTools/JsvDynamicKeyFrames.js +2 -2
  49. package/utils/JsViewVueTools/JsvImpactTracer.js +7 -7
  50. package/utils/JsViewVueTools/JsvPreDownloader.ts +1 -1
  51. package/utils/JsViewVueTools/JsvRefTaker.js +2 -1
  52. package/utils/JsViewVueTools/JsvRuntimeBridge.js +29 -29
  53. package/utils/JsViewVueTools/JsvStyleClass.js +3 -3
  54. package/utils/JsViewVueTools/JsvStyleSheetsDeclarer.js +1 -1
  55. package/utils/JsViewVueTools/JsvTextTools.js +4 -4
  56. package/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/CanvasTexture.ts +29 -1
  57. package/utils/JsViewVueTools/JsvTextureStore/CanvasTexture/CommandList.ts +6 -5
  58. package/utils/JsViewVueTools/JsvTextureStore/JsvTextureStore.ts +60 -2
  59. package/utils/JsViewVueTools/NinePatchHelper.js +1 -1
  60. package/utils/JsViewVueWidget/JsvActorMove/ActorControlBase.js +1 -1
  61. package/utils/JsViewVueWidget/JsvActorMove/JsvActorMoveControl.js +1 -1
  62. package/utils/JsViewVueWidget/JsvApic/{BrowserApic → JsvApic}/BrowserApic.vue +20 -23
  63. package/utils/JsViewVueWidget/JsvApic/{JsvApic.vue → JsvApic/JsvApic.vue} +3 -14
  64. package/utils/JsViewVueWidget/JsvApic/{index.js → JsvApic/index.js} +2 -4
  65. package/utils/JsViewVueWidget/JsvApic/JsvApic2/BrowserApic2.vue +116 -0
  66. package/utils/JsViewVueWidget/JsvApic/JsvApic2/JsvApic2.vue +137 -0
  67. package/utils/JsViewVueWidget/JsvApic/JsvApic2/index.js +17 -0
  68. package/utils/JsViewVueWidget/JsvApic/JsvBrowserApicLib/BrowserApicLib.js +4 -0
  69. package/utils/JsViewVueWidget/JsvApic/{BrowserApic → JsvBrowserApicLib}/NormalLoopTool.js +16 -18
  70. package/utils/JsViewVueWidget/JsvApic/JsvBrowserApicLib/PartLoopTool.js +90 -0
  71. package/utils/JsViewVueWidget/JsvApic/JsvBrowserApicLib/SingleLoopTool.js +17 -0
  72. package/utils/JsViewVueWidget/JsvApic/JsvBrowserApicLib/Viewer.js +111 -0
  73. package/utils/JsViewVueWidget/JsvApic/JsvCommonLoopToolBase.js +48 -0
  74. package/utils/JsViewVueWidget/JsvConnectLine/ArcLineManager.js +71 -0
  75. package/utils/JsViewVueWidget/JsvConnectLine/JsvConnectLine.vue +354 -0
  76. package/utils/JsViewVueWidget/JsvConnectLine/index.js +2 -0
  77. package/utils/JsViewVueWidget/JsvFreeMoveActor/ActorControl.ts +37 -18
  78. package/utils/JsViewVueWidget/JsvFreeMoveActor/ForgeTypeDefine.ts +7 -3
  79. package/utils/JsViewVueWidget/JsvFreeMoveActor/FreeMoveActor.vue +28 -2
  80. package/utils/JsViewVueWidget/JsvFreeMoveActor/JsvEnvBlocker.vue +12 -5
  81. package/utils/JsViewVueWidget/JsvFreeMoveActor/NexusNode.ts +21 -0
  82. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetAction.ts +47 -59
  83. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetCondition.ts +129 -12
  84. package/utils/JsViewVueWidget/JsvFreeMoveActor/SetState.ts +45 -0
  85. package/utils/JsViewVueWidget/JsvFreeMoveActor/index.js +10 -2
  86. package/utils/JsViewVueWidget/JsvGrid.vue +1 -1
  87. package/utils/JsViewVueWidget/JsvHole.js +1 -1
  88. package/utils/JsViewVueWidget/JsvInput/JsvInput.vue +1 -1
  89. package/utils/JsViewVueWidget/JsvLine/JsvLine.vue +2 -2
  90. package/utils/JsViewVueWidget/JsvLine/LineManager.js +6 -4
  91. package/utils/JsViewVueWidget/JsvMarquee.vue +7 -4
  92. package/utils/JsViewVueWidget/JsvPieChart.vue +1 -1
  93. package/utils/JsViewVueWidget/JsvPreload/JsvPreload.vue +1 -1
  94. package/utils/JsViewVueWidget/JsvPreload/index.js +1 -1
  95. package/utils/JsViewVueWidget/JsvProgressBar.vue +172 -0
  96. package/utils/JsViewVueWidget/JsvQrcode/JsvQrcode.vue +0 -1
  97. package/utils/JsViewVueWidget/JsvQrcode/index.js +1 -1
  98. package/utils/JsViewVueWidget/JsvRadarChart.vue +1 -1
  99. package/utils/JsViewVueWidget/JsvScaleTextBox.vue +0 -2
  100. package/utils/JsViewVueWidget/JsvSector.vue +1 -1
  101. package/utils/JsViewVueWidget/JsvSoundPool.js +1 -1
  102. package/utils/JsViewVueWidget/JsvSpray/index.js +1 -1
  103. package/utils/JsViewVueWidget/JsvSpriteAnim/FrameBuidler.ts +235 -0
  104. package/utils/JsViewVueWidget/JsvSpriteAnim/JsvSpriteAnim.vue +433 -401
  105. package/utils/JsViewVueWidget/JsvSpriteAnim/JsvSpriteLoader.vue +120 -0
  106. package/utils/JsViewVueWidget/JsvSpriteAnim/index.js +2 -2
  107. package/utils/JsViewVueWidget/JsvSwiper/JsvSwiper.vue +5 -5
  108. package/utils/JsViewVueWidget/JsvSwiper3D/JsvSwiper.vue +425 -422
  109. package/utils/JsViewVueWidget/JsvVisibleSensor/index.js +1 -1
  110. package/utils/JsViewVueWidget/index.js +7 -3
  111. package/utils/index.js +4 -0
  112. package/utils/JsViewVueWidget/JsvApic/BrowserApic/LoopToolBase.js +0 -25
  113. package/utils/JsViewVueWidget/JsvApic/BrowserApic/PartLoopTool.js +0 -119
  114. package/utils/JsViewVueWidget/JsvApic/BrowserApic/Viewer.js +0 -106
  115. /package/utils/JsViewPlugin/JsvLatex/{JsvLatexBrowser.vue → BrowserJsvLatex.vue} +0 -0
  116. /package/utils/JsViewPlugin/JsvPlayer/{JsvPlayerBrowser-0.9.vue → BrowserJsvPlayer-0.9.vue} +0 -0
  117. /package/utils/JsViewPlugin/JsvPlayer/{JsvPlayerBrowser.vue → BrowserJsvPlayer.vue} +0 -0
  118. /package/utils/JsViewVueWidget/JsvApic/{BrowserApic → JsvBrowserApicLib}/ApicDataBase.js +0 -0
  119. /package/utils/JsViewVueWidget/JsvApic/{BrowserApic → JsvBrowserApicLib}/GifData.js +0 -0
  120. /package/utils/JsViewVueWidget/JsvApic/{BrowserApic → JsvBrowserApicLib}/WebpData.js +0 -0
@@ -1,10 +1,12 @@
1
1
  import {
2
+ ref,
2
3
  reactive,
3
4
  onMounted,
4
5
  onBeforeUnmount,
5
6
  onUpdated,
6
7
  toRaw,
7
8
  nextTick,
9
+ computed,
8
10
  } from "vue";
9
11
  import { Forge } from "@shijiu/jsview/dom/jsv-forge-define";
10
12
  import {
@@ -23,10 +25,9 @@ import {
23
25
  } from "../WidgetCommon";
24
26
  import { RenderItem } from "./RenderItem";
25
27
  import { VisibleInfo } from "./VisibleInfo";
26
- // import { AnimationManager, AnimationTools } from "./AnimationManager";
27
28
  import { WidgetRectInfo } from "./WidgetRectInfo";
28
- import { checkType } from "../CheckType";
29
29
  import { TaskType, MacroEndTaskManager, AnimationManager } from "./AnimationManager.ts"
30
+ import ActorControl from "../../JsViewVueWidget/JsvFreeMoveActor/ActorControl.ts";
30
31
 
31
32
  const TAG = "MetroWidget";
32
33
 
@@ -70,6 +71,9 @@ const _getMetroTemplate = function (
70
71
  return metroWidget;
71
72
  };
72
73
 
74
+ const TOUCH_MODE = 1; //触控模式
75
+ const FOCUS_MODE = 2; //按键模式
76
+
73
77
  export const setup = (
74
78
  props,
75
79
  itemRender,
@@ -80,6 +84,8 @@ export const setup = (
80
84
  slideDivTop,
81
85
  focusNode,
82
86
  pageUpdateToken,
87
+ touchDiv,
88
+ touchDivSize,
83
89
  templateMode) => {
84
90
 
85
91
  if (props.itemConfig) {
@@ -94,6 +100,53 @@ export const setup = (
94
100
  props.layoutType,
95
101
  templateMode
96
102
  );
103
+
104
+ const TouchState = {
105
+ IDLE: 0,
106
+ TAP: 1,
107
+ DRAG: 2,
108
+ FLING: 3,
109
+ };
110
+
111
+ const mode = {
112
+ _mode: FOCUS_MODE,
113
+ _touchState: TouchState.IDLE,
114
+
115
+ _duringTouch: false,
116
+ _duringFling: false,
117
+ touchStart() {
118
+ this._mode = TOUCH_MODE;
119
+ this._touchState = TouchState.TAP;
120
+ },
121
+ touchEnd() {
122
+ this._touchState = TouchState.IDLE;
123
+ },
124
+ flingStart() {
125
+ this._touchState = TouchState.FLING;
126
+ },
127
+ flingEnd() { },
128
+ dragStart() {
129
+ this._touchState = TouchState.DRAG;
130
+ },
131
+ dragEnd() { },
132
+ keyDown() {
133
+ this._mode = FOCUS_MODE;
134
+ this._touchState = TouchState.IDLE;
135
+ },
136
+ duringFling() {
137
+ return this._touchState == TouchState.FLING;
138
+ },
139
+ duringTouch() {
140
+ return this._touchState != TouchState.IDLE;
141
+ },
142
+ getMode() {
143
+ return this._mode;
144
+ },
145
+ getTouchState() {
146
+ return this._touchState;
147
+ }
148
+ }
149
+
97
150
  let innerData = [];
98
151
  let dataList = [];
99
152
  let pageUpdater = null;
@@ -114,6 +167,8 @@ export const setup = (
114
167
  let onKeyDownLock = false;
115
168
  let visibleInfo = new VisibleInfo();
116
169
  let preSlideDirection = 0;
170
+ let alreadyCallItemFocus = false;
171
+ const currentFocusIndex = ref(0);
117
172
 
118
173
  const DEFAULT_ANIMATION_DURATION = 200;
119
174
 
@@ -140,6 +195,7 @@ export const setup = (
140
195
  let size_key = vertical ? "height" : "width";
141
196
  let doAnim = false;
142
197
 
198
+ let existOnFocusChange = false;
143
199
  for (let task of taskList) {
144
200
  if (task.type == TaskType.RESIZE_ITEM) {
145
201
  resizeTaskMap[task.params.index] = task;
@@ -162,6 +218,8 @@ export const setup = (
162
218
  } else if (task.type == TaskType.SLIDE) {
163
219
  //滚动动画取最后一个
164
220
  slideTask = task;
221
+ } else if (task.type == TaskType.ON_FOCUS_CHANGE) {
222
+ existOnFocusChange = true;
165
223
  }
166
224
  }
167
225
 
@@ -172,7 +230,9 @@ export const setup = (
172
230
  }
173
231
  }
174
232
 
233
+ let existItemResize = false;
175
234
  if (resizeList.length > 0) {
235
+ existItemResize = true;
176
236
  //TODO 应该是尺寸变化后的可视item需要记录位置, 但暂时先记录20个
177
237
  metroTemplate.cacheLayout(minIndex, minIndex + 20);
178
238
  //resize
@@ -188,9 +248,11 @@ export const setup = (
188
248
  const focusItem = getItemById(focusId);
189
249
  const start = focusItem.templateInfo[pos_key] + focusItem.templateInfo[size_key] * anchorInfo.anchor - 1 - anchorInfo.anchorPosition;
190
250
  visibleInfo.start = normalizeVisibleStart(start, focusItem.templateInfo);
191
- if (!isItemVisible(focusItem)) {
192
- visibleInfo.start = _calculateVisibleStart(getItemById(focusId).templateInfo, preSlideDirection);
193
- }
251
+
252
+ // resize的item不能完整显示时不需要调整
253
+ // if (!isItemVisible(focusItem)) {
254
+ // visibleInfo.start = _calculateVisibleStart(getItemById(focusId).templateInfo, preSlideDirection);
255
+ // }
194
256
  } else {
195
257
  visibleInfo.start = _calculateVisibleStart(getItemById(focusId).templateInfo, preSlideDirection);
196
258
  }
@@ -198,21 +260,31 @@ export const setup = (
198
260
  //只有resize引起的slide动画时, 动画时长使用resize设置, 否者使用slideSetting设置
199
261
  slideInfo = {
200
262
  target: -visibleInfo.start,
201
- animObj: doAnim ? {
263
+ };
264
+ if (doAnim) {
265
+ slideInfo.animObj = {
202
266
  easing: "",
203
267
  onStart: null,
204
- speed: slideTask ? props.slideSetting.Speed : null,
205
- duration: slideTask ? props.slideSetting.Duration : duration,
268
+ speed: null,
269
+ duration,
206
270
  onEnd: (animDone) => {
207
271
  },
208
- } : {
209
- //resize无动画时正常slide
210
- easing: "",
211
- onStart: null,
212
- onEnd: null,
213
- speed: props.slideSetting.Speed,
214
- duration: props.slideSetting.Duration,
215
- },
272
+ }
273
+ } else {
274
+ //resize无动画时正常slide
275
+ if (slideTask) {
276
+ slideInfo.animObj = slideTask.params?.animObj
277
+ } else {
278
+ //默认滚动
279
+ slideInfo.animObj = {
280
+ //resize无动画时正常slide
281
+ easing: "",
282
+ onStart: null,
283
+ onEnd: null,
284
+ speed: props.slideSetting.Speed,
285
+ duration: props.slideSetting.Duration,
286
+ }
287
+ }
216
288
  }
217
289
  }
218
290
  const handler = pageUpdater.update(
@@ -255,21 +327,59 @@ export const setup = (
255
327
  }
256
328
 
257
329
  //处理滚动动画
330
+ let viewSlid = false;
258
331
  if (slideInfo) {
259
332
  const target = slideInfo.target;
260
- let preLeft = slideDivLeft.value;
261
- let preTop = slideDivTop.value;
262
- slideDivLeft.value = vertical ? 0 : target;
263
- slideDivTop.value = vertical ? target : 0;
264
- if (slideInfo.animObj) {
265
- animationManager.startSlideAnim(
266
- slideDiv.value,
267
- vertical ? [0, preTop - slideDivTop.value] : [preLeft - slideDivLeft.value, 0],
268
- [0, 0],
269
- slideInfo.animObj);
270
- }
271
- _onScroll();
333
+ viewSlid = executeSlide(target, slideInfo);
272
334
  }
335
+
336
+ //回调
337
+ if (existItemResize) {
338
+ props.onAllItemResizeDone?.();
339
+ }
340
+ if (viewSlid || existOnFocusChange) {
341
+ props.onFocusRectChange?.();
342
+ }
343
+ }
344
+
345
+ const executeSlide = (target, slideInfo) => {
346
+ let preLeft = slideDivLeft.value;
347
+ let preTop = slideDivTop.value;
348
+ slideDivLeft.value = vertical ? 0 : target;
349
+ slideDivTop.value = vertical ? target : 0;
350
+ let viewSlid = preLeft != slideDivLeft.value || preTop != slideDivTop.value;
351
+ visibleInfo.start = -target;
352
+ const updater = pageUpdater.update(
353
+ metroTemplate,
354
+ visibleInfo.startWithPadding - props.keepTraceRange * pageRange,
355
+ Math.min(
356
+ visibleInfo.startMax +
357
+ visibleInfo.range +
358
+ visibleInfo.padding.end -
359
+ 1,
360
+ visibleInfo.endWithPadding + props.keepTraceRange * pageRange
361
+ ),
362
+ focusId,
363
+ true,
364
+ permanentItemList
365
+ );
366
+ if (slideInfo.animObj) {
367
+ updater.applyTmp();
368
+ animationManager.startSlideAnim(
369
+ slideDiv.value,
370
+ vertical ? [0, preTop - slideDivTop.value] : [preLeft - slideDivLeft.value, 0],
371
+ [0, 0],
372
+ {
373
+ ...slideInfo.animObj,
374
+ onEnd: () => {
375
+ updater.apply()
376
+ }
377
+ });
378
+ } else {
379
+ updater.apply();
380
+ }
381
+ _onScroll();
382
+ return viewSlid
273
383
  }
274
384
 
275
385
  const onMacroEndTaskBreak = (list) => {
@@ -297,6 +407,9 @@ export const setup = (
297
407
  }
298
408
 
299
409
  const _slideTo = (target, animObj) => {
410
+ if (slideLock) {
411
+ return
412
+ };
300
413
  macroEndTaskManager.addTask(TaskType.SLIDE, { target: -target, animObj })
301
414
  };
302
415
 
@@ -395,7 +508,8 @@ export const setup = (
395
508
  };
396
509
 
397
510
  const onItemFocus = (focusItem, rect) => {
398
- if (!focusItem) return;
511
+ //触控模式不触发item的onFocus
512
+ if (!focusItem || mode.getMode() != FOCUS_MODE) return;
399
513
  setItemZIndex(focusItem, innerData.length, true);
400
514
  if (isFocus) {
401
515
  _itemOnFocusSideEffect(focusItem, rect);
@@ -403,9 +517,24 @@ export const setup = (
403
517
  if (!called) {
404
518
  callFocusAfterUpdate = true;
405
519
  }
520
+ return called;
406
521
  }
522
+ return false;
407
523
  };
408
524
 
525
+ const setFocusByUid = (uid, needSlide = true, doAnim = false, extraSetting) => {
526
+ if (!uid) { return; }
527
+ //添加item
528
+ templateItemAdder.tryAddItemByUid(uid);
529
+ const item = metroTemplate.getItemByUid(uid);
530
+ if (!item) {
531
+ console.warn(TAG, `setFocusByUid failed: uid ${uid} not exist.`);
532
+ return;
533
+ }
534
+
535
+ setFocusId(item.id, needSlide, doAnim, extraSetting);
536
+ }
537
+
409
538
  const setFocusId = (id, needSlide = true, doAnim = false, extraSetting) => {
410
539
  if (id == focusId) {
411
540
  return;
@@ -413,10 +542,9 @@ export const setup = (
413
542
  templateItemAdder.tryAddItemById(id);
414
543
  let next_focus_item = getItemById(id);
415
544
  if (next_focus_item) {
416
- preFocusId = focusId;
417
- const preFocusItem = getItemById(preFocusId);
418
545
  const nextTemplateInfo = next_focus_item.templateInfo;
419
- focusId = nextTemplateInfo.id;
546
+ _changeFocusId(nextTemplateInfo.id);
547
+ const preFocusItem = getItemById(preFocusId);
420
548
  onItemBlur(preFocusItem);
421
549
  onItemFocus(next_focus_item, preEdgeRect);
422
550
  if (needSlide) {
@@ -557,6 +685,36 @@ export const setup = (
557
685
  }
558
686
  };
559
687
 
688
+ const slideToDiv = (div, doAnim) => {
689
+ if (div) {
690
+ const item_layout = div.jsvGetRelativePosition(toRaw(locateDiv.value));
691
+ const direction = 1;
692
+
693
+ let fakeItem = {
694
+ templateInfo: {
695
+ left: item_layout.left,
696
+ top: item_layout.top,
697
+ width: item_layout.width,
698
+ height: item_layout.height,
699
+ centerYPos: Math.floor(item_layout.top + item_layout.height / 2),
700
+ centerXPos: Math.floor(item_layout.left + item_layout.width / 2),
701
+ index: id2Index(focusId),
702
+ },
703
+ };
704
+
705
+ let cur_slide = _calculateVisibleStart(fakeItem.templateInfo, direction);
706
+ if (cur_slide != visibleInfo.start) {
707
+ _slideTo(cur_slide, doAnim ? {
708
+ easing: "",
709
+ onStart: null,
710
+ speed: props.slideSetting.Speed,
711
+ duration: props.slideSetting.Duration,
712
+ onEnd: null,
713
+ } : null);
714
+ }
715
+ }
716
+ }
717
+
560
718
  const refreshData = (force_update) => {
561
719
  //由于data不支持reactive, 因此数据的更新只通过provideData
562
720
  if (!props.provideData) {
@@ -569,8 +727,7 @@ export const setup = (
569
727
  }
570
728
  let new_list = toRaw(props.provideData());
571
729
  if (focusId >= new_list.length) {
572
- focusId = new_list.length - 1;
573
- preFocusId = -1;
730
+ _changeFocusId(new_list.length - 1, false)
574
731
  }
575
732
  let new_index = 0;
576
733
  if (!_force_update) {
@@ -616,8 +773,9 @@ export const setup = (
616
773
  dataList,
617
774
  props.measures,
618
775
  pageRange,
619
- _onTemplateAdd,
620
- props.name
776
+ _onTemplateItemAdd,
777
+ props.name,
778
+ _onTemplateAddDone
621
779
  );
622
780
  }
623
781
  if (need_update_content) {
@@ -678,21 +836,43 @@ export const setup = (
678
836
  return id2Index(focusId);
679
837
  }
680
838
 
839
+ const getCurMode = () => {
840
+ return mode.getMode();
841
+ }
842
+
843
+ const getTemplatePosition = (index) => {
844
+ return _getTemplatePosition(index);
845
+ }
846
+
847
+ const lockSlide = () => {
848
+ slideLock = true;
849
+ }
850
+
851
+ const unlockSlide = () => {
852
+ slideLock = false;
853
+ }
854
+
681
855
  const exportObject = {
856
+ lockSlide,
857
+ unlockSlide,
682
858
  lock,
683
859
  unlock,
684
860
  slideTo,
685
861
  setFocusId,
862
+ setFocusByUid,
686
863
  getFocusBlockRef,
687
864
  setEnterFocusId,
688
865
  setEnterFocusRect,
689
866
  slideToItem,
867
+ slideToDiv,
690
868
  refreshData,
691
869
  getVisibleItems,
692
870
  moveFocus,
693
871
  getCustomerDataSize,
694
872
  setZIndex,
695
873
  getCurrentFocusIndex,
874
+ getCurMode,
875
+ getTemplatePosition,
696
876
  };
697
877
 
698
878
  const _calculateNearestItemByRect = (visibleSet, enter_rect_info) => {
@@ -894,6 +1074,21 @@ export const setup = (
894
1074
  if (onKeyDownLock) {
895
1075
  return true;
896
1076
  }
1077
+ if (mode.getMode() == TOUCH_MODE) {
1078
+ if (mode.duringTouch()) {
1079
+ //touch过程中的按键不处理
1080
+ return true;
1081
+ } else {
1082
+ //切换为focus_mode
1083
+ mode.keyDown();
1084
+ //touch切换为focus的首次按键只显示焦点
1085
+ const focusItem = _getVisibleFocusableItem();
1086
+ _changeFocusId(focusItem.id, false);
1087
+ onItemFocus(focusItem);
1088
+ return true;
1089
+ }
1090
+ }
1091
+
897
1092
  switch (ev.keyCode) {
898
1093
  case 37:
899
1094
  _moveToNext(-1, 0);
@@ -924,7 +1119,24 @@ export const setup = (
924
1119
  );
925
1120
  };
926
1121
 
927
- const _onTemplateAdd = (customerData, templateItem, measuresObj) => {
1122
+ const _onTemplateAddDone = () => {
1123
+ //update slideDiv size
1124
+ const lastTemplateInfo = getItemByIndex(
1125
+ metroTemplate.getTailItemIndex()
1126
+ )?.templateInfo;
1127
+ if (lastTemplateInfo) {
1128
+ if (vertical) {
1129
+ touchDivSize.width = props.width;
1130
+ touchDivSize.height = lastTemplateInfo.top + lastTemplateInfo.height - 1;
1131
+ } else {
1132
+ touchDivSize.width = lastTemplateInfo.left + lastTemplateInfo.width - 1;
1133
+ touchDivSize.height = props.height;
1134
+ }
1135
+ resetDragRect(touchDivSize.width, touchDivSize.height);
1136
+ }
1137
+ }
1138
+
1139
+ const _onTemplateItemAdd = (customerData, templateItem, measuresObj) => {
928
1140
  let focusZIndex = -1,
929
1141
  normalZIndex = -1;
930
1142
  if (
@@ -950,10 +1162,6 @@ export const setup = (
950
1162
  itemSlide: measuresObj.itemSlide ?? METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS,
951
1163
  };
952
1164
 
953
- if (props.itemConfig) {
954
- const c = props.itemConfig(customerData);
955
- }
956
-
957
1165
  const renderStyle = reactive({
958
1166
  left: templateItem.left,
959
1167
  top: templateItem.top,
@@ -987,6 +1195,7 @@ export const setup = (
987
1195
  widgetHandler: exportObject,
988
1196
  }
989
1197
  );
1198
+ item.enableTap = measuresObj.enableTap ?? false;
990
1199
 
991
1200
  innerData.push(item);
992
1201
  if (item.itemConfig.permanent) {
@@ -1005,11 +1214,11 @@ export const setup = (
1005
1214
  direction: edgeRect?.direction?.description,
1006
1215
  element: toRaw(item.rootDiv),
1007
1216
  };
1008
- _bubbleCustomerEvent(event);
1217
+ _bubbleCustomEvent(event);
1009
1218
  }
1010
1219
  };
1011
1220
 
1012
- const focusBlockOnCustomerEvent = (ev) => {
1221
+ const focusBlockOnCustomEvent = (ev) => {
1013
1222
  if (ev.type === "focusRect") {
1014
1223
  if (childSlideEventLock) {
1015
1224
  return true;
@@ -1083,10 +1292,17 @@ export const setup = (
1083
1292
  return false;
1084
1293
  };
1085
1294
 
1086
- const _bubbleCustomerEvent = (event) => {
1295
+ const _changeFocusId = (id, cache_pre = true) => {
1296
+ preFocusId = cache_pre ? focusId : -1;
1297
+ focusId = id;
1298
+ currentFocusIndex.value = id2Index(id);
1299
+ macroEndTaskManager.addTask(TaskType.ON_FOCUS_CHANGE);
1300
+ }
1301
+
1302
+ const _bubbleCustomEvent = (event) => {
1087
1303
  if (props.sendFocusRectEvent && event) {
1088
1304
  event.ownerNode = exportObject;
1089
- toRaw(focusNode.value)?.bubbleCustomerEvent(event);
1305
+ toRaw(focusNode.value)?.bubbleCustomEvent(event);
1090
1306
  }
1091
1307
  };
1092
1308
 
@@ -1129,9 +1345,8 @@ export const setup = (
1129
1345
  props.focusMoveType
1130
1346
  );
1131
1347
  if (next_focus_item !== null) {
1132
- preFocusId = focusId;
1348
+ _changeFocusId(next_focus_item.id);
1133
1349
  const preFocusItem = getItemById(preFocusId);
1134
- focusId = next_focus_item.id;
1135
1350
 
1136
1351
  templateItemAdder.tryAddItem(next_focus_item.templateInfo, 1);
1137
1352
 
@@ -1243,7 +1458,11 @@ export const setup = (
1243
1458
  };
1244
1459
  }
1245
1460
 
1246
- props.onEdge?.({ direction: edge, rect: rect });
1461
+ props.onEdge?.({
1462
+ direction: edge,
1463
+ rect: rect,
1464
+ childEdgeInfo: item_edge_rect
1465
+ });
1247
1466
  innerData[id2Index(focusId)]?.onWidgetEdge({
1248
1467
  direction: edge,
1249
1468
  });
@@ -1431,7 +1650,6 @@ export const setup = (
1431
1650
 
1432
1651
  const focusBlockOnFocus = (params) => {
1433
1652
  isFocus = true;
1434
- preFocusId = -1;
1435
1653
  if (innerData.length === 0) {
1436
1654
  console.log(`MetroWidget: ${props.name} get focus while data is empty.`);
1437
1655
  return;
@@ -1445,12 +1663,11 @@ export const setup = (
1445
1663
  focus_id = _ifValidEnterRect(enterFocusRect)
1446
1664
  ? _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect)
1447
1665
  : focus_id;
1448
-
1449
1666
  preEdgeRect = enterFocusRect;
1450
- focusId = focus_id;
1667
+ _changeFocusId(focus_id, false);
1451
1668
  enterFocusId = -1;
1452
1669
  enterFocusRect = null;
1453
- onItemFocus(getItemById(focusId), preEdgeRect);
1670
+ alreadyCallItemFocus = onItemFocus(getItemById(focusId), preEdgeRect);
1454
1671
  props.onFocus?.();
1455
1672
  };
1456
1673
 
@@ -1477,6 +1694,20 @@ export const setup = (
1477
1694
  }
1478
1695
  };
1479
1696
 
1697
+ const _getVisibleFocusableItem = () => {
1698
+ const focusItem = getItemById(focusId);
1699
+ if (isItemVisible(focusItem)) {
1700
+ return focusItem;
1701
+ } else {
1702
+ //遍历renderList, 找到第一个可见的 focusable item
1703
+ for (let item of renderData.value) {
1704
+ if (item.templateInfo.focusable && isItemVisible(item)) {
1705
+ return item;
1706
+ }
1707
+ }
1708
+ }
1709
+ }
1710
+
1480
1711
  const _onScroll = () => {
1481
1712
  if (props.onScroll) {
1482
1713
  const lastTemplateInfo = getItemByIndex(
@@ -1494,6 +1725,214 @@ export const setup = (
1494
1725
  }
1495
1726
  };
1496
1727
 
1728
+ //touch setting
1729
+ let actorController = null;
1730
+ const touchLoadItemRect = visibleInfo.range;
1731
+ const reachAnchorGroup = 2;
1732
+ const wallConditionGroup = 1;
1733
+
1734
+ const getVisibleStart = (moveInfo) => {
1735
+ if (vertical) {
1736
+ return -(slideDivTop.value + Math.round(moveInfo.yPos));
1737
+ } else {
1738
+ return -(slideDivLeft.value + Math.round(moveInfo.xPos));
1739
+ }
1740
+ }
1741
+
1742
+ const mergeTouchSlideToSlideDiv = () => {
1743
+ if (vertical) {
1744
+ slideDivTop.value = -visibleInfo.start;
1745
+ } else {
1746
+ slideDivLeft.value = -visibleInfo.start;
1747
+ }
1748
+
1749
+ const walls = getTouchWall();
1750
+ actorController.run([
1751
+ actorController.state().removeConditionByGroup(wallConditionGroup),
1752
+ actorController
1753
+ .condition(wallConditionGroup, true)
1754
+ .boxPosition(walls.left, walls.top, walls.right, walls.bottom)
1755
+ .then([actorController.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
1756
+ actorController
1757
+ .action()
1758
+ .teleportTo(0, 0)]);
1759
+ }
1760
+
1761
+ const onTouchDown = (data) => {
1762
+ mode.touchStart();
1763
+ mode.flingEnd();
1764
+
1765
+ //blur item
1766
+ onItemBlur(getItemById(focusId));
1767
+
1768
+ visibleInfo.start = getVisibleStart(data);
1769
+ templateItemAdder.tryAddItemByPosition(visibleInfo.end + visibleInfo.range);
1770
+
1771
+ const updater = pageUpdater.update(
1772
+ metroTemplate,
1773
+ visibleInfo.startWithPadding - visibleInfo.range,
1774
+ visibleInfo.endWithPadding + visibleInfo.range,
1775
+ 0,
1776
+ false,
1777
+ permanentItemList
1778
+ );
1779
+ updater.apply();
1780
+
1781
+ //创建锚点
1782
+ const anchorArea = 2 * Forge.sRenderBridge.GetScreenInfo().designedWidth;
1783
+ let anchorPosList = [];
1784
+ let anchorSpacing = visibleInfo.range * 2 / 3;
1785
+ let anchorPos = anchorSpacing;
1786
+ while (anchorPos < anchorArea) {
1787
+ anchorPosList.push(-visibleInfo.start + anchorPos);
1788
+ anchorPosList.push(-visibleInfo.start - visibleInfo.range - anchorPos + 1);
1789
+ anchorPos += anchorSpacing;
1790
+ }
1791
+ const reachConditionList = anchorPosList.map(pos => {
1792
+ actorController
1793
+ .condition(reachAnchorGroup)
1794
+ .reachPosition(pos, undefined)
1795
+ .then([(data) => { updateRenderItems(true, true) }])
1796
+ })
1797
+ reachConditionList.unshift(
1798
+ actorController.state().removeConditionByGroup(reachAnchorGroup),
1799
+ )
1800
+ actorController.run(reachConditionList);
1801
+ }
1802
+
1803
+ const onTouchRelease = () => {
1804
+ if (mode.getTouchState() == TouchState.TAP) {
1805
+ //只点击, 没有移动或者fling
1806
+ mergeTouchSlideToSlideDiv();
1807
+ updateRenderItems(false, false);
1808
+ mode.touchEnd();
1809
+ }
1810
+ }
1811
+
1812
+ const onDragStart = (data) => {
1813
+ mode.dragStart()
1814
+ visibleInfo.start = getVisibleStart(data);
1815
+ }
1816
+
1817
+ const onDragEnd = (data) => {
1818
+ visibleInfo.start = getVisibleStart(data);
1819
+
1820
+ actorController.run([
1821
+ actorController.state().removeConditionByGroup(reachAnchorGroup),
1822
+ ]);
1823
+ mergeTouchSlideToSlideDiv();
1824
+ updateRenderItems(false, false);
1825
+ mode.touchEnd()
1826
+ }
1827
+
1828
+ const onFlingStart = (data) => {
1829
+ mode.flingStart();
1830
+ visibleInfo.start = getVisibleStart(data);
1831
+ updateRenderItems(true, true);
1832
+ }
1833
+
1834
+ const onFlingProgress = (data) => {
1835
+ visibleInfo.start = getVisibleStart(data);
1836
+ updateRenderItems(true, true);
1837
+ }
1838
+
1839
+ const onFlingEnd = (data) => {
1840
+ visibleInfo.start = getVisibleStart(data);
1841
+ //记录拖拽的距离
1842
+ if (mode.duringFling()) {
1843
+ mergeTouchSlideToSlideDiv();
1844
+ updateRenderItems(false, false);
1845
+ mode.flingEnd();
1846
+ mode.touchEnd();
1847
+ }
1848
+ }
1849
+
1850
+ const getTouchWall = () => {
1851
+ const boxSize = metroTemplate.getBoundingBoxSize();
1852
+ let wall = {
1853
+ left: 0,
1854
+ top: 0,
1855
+ right: 0,
1856
+ bottom: 0,
1857
+ }
1858
+ if (vertical) {
1859
+ wall.top = -boxSize.height + props.height - slideDivTop.value;
1860
+ wall.bottom = -slideDivTop.value;
1861
+ } else {
1862
+ wall.left = -boxSize.width + props.width - slideDivLeft.value;
1863
+ wall.right = -slideDivLeft.value;
1864
+ }
1865
+ return wall;
1866
+ }
1867
+
1868
+ const updateRenderItems = (applyTmp, expand) => {
1869
+ templateItemAdder.tryAddItemByPosition(visibleInfo.start + visibleInfo.range);
1870
+ const updater = pageUpdater.update(
1871
+ metroTemplate,
1872
+ expand ? visibleInfo.start - visibleInfo.range : visibleInfo.startWithPadding,
1873
+ expand ? visibleInfo.start + 2 * visibleInfo.range : visibleInfo.endWithPadding,
1874
+ 0,
1875
+ true,
1876
+ permanentItemList
1877
+ );
1878
+ applyTmp ? updater.applyTmp() : updater.apply();
1879
+ }
1880
+
1881
+ const resetDragRect = () => {
1882
+ if (actorController != null) {
1883
+ const walls = getTouchWall();
1884
+ //更新wall设置
1885
+ actorController.run([
1886
+ actorController.state().removeConditionByGroup(wallConditionGroup),
1887
+ actorController
1888
+ .condition(wallConditionGroup, true)
1889
+ .boxPosition(walls.left, walls.top, walls.right, walls.bottom)
1890
+ .then([actorController.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
1891
+ ]);
1892
+ }
1893
+ }
1894
+
1895
+ const initTouch = () => {
1896
+ actorController = new ActorControl();
1897
+ const divView = touchDiv.value.jsvGetProxyView();
1898
+ actorController.bindForgeView(divView, true);
1899
+ divView.DragEnables?.(4 | 0x08 | 0x10); // 只激活drag
1900
+
1901
+ const walls = getTouchWall();
1902
+ //注册回调
1903
+ actorController.run([
1904
+ actorController
1905
+ .condition(undefined, true)
1906
+ .onTouchDown()
1907
+ .then([onTouchDown]),
1908
+ actorController
1909
+ .condition(undefined, true)
1910
+ .onDragStart()
1911
+ .then([onDragStart]),
1912
+ actorController
1913
+ .condition(undefined, true)
1914
+ .onDragEnd()
1915
+ .then([onDragEnd]),
1916
+ actorController
1917
+ .condition(undefined, true)
1918
+ .onFlingStart()
1919
+ .then([onFlingStart]),
1920
+ actorController
1921
+ .condition(undefined, true)
1922
+ .onFlingProgress()
1923
+ .then([onFlingProgress]),
1924
+ actorController
1925
+ .condition(undefined, true)
1926
+ .onFlingEnd()
1927
+ .then([onFlingEnd]),
1928
+
1929
+ actorController
1930
+ .condition(wallConditionGroup, true)
1931
+ .boxPosition(walls.left, walls.top, walls.right, walls.bottom)
1932
+ .then([actorController.state().setHitWallOverflow()]), //TODO 通过prop设置哪个方向overflow
1933
+ ]);
1934
+ }
1935
+
1497
1936
  //init
1498
1937
  pageUpdater = new PageUpdater(_updatePage);
1499
1938
  visibleInfo.range = vertical
@@ -1509,16 +1948,14 @@ export const setup = (
1509
1948
  dataList = toRaw(props.data);
1510
1949
  }
1511
1950
 
1512
- window.metroTemplate = metroTemplate;
1513
- window.innerData = innerData;
1514
-
1515
1951
  templateItemAdder = new TemplateItemAdder(
1516
1952
  metroTemplate,
1517
1953
  dataList,
1518
1954
  props.measures,
1519
1955
  pageRange,
1520
- _onTemplateAdd,
1521
- props.name
1956
+ _onTemplateItemAdd,
1957
+ props.name,
1958
+ _onTemplateAddDone
1522
1959
  );
1523
1960
  if (props.onScroll) {
1524
1961
  templateItemAdder.tryAddItemByIndex(dataList.length - 1);
@@ -1553,11 +1990,12 @@ export const setup = (
1553
1990
  updater.apply();
1554
1991
 
1555
1992
  onMounted(() => {
1993
+ _changeFocusId(focusId, false);
1556
1994
  mounted = true;
1557
1995
  if (visibleInfo.start) {
1558
1996
  _slideTo(visibleInfo.start, null);
1559
1997
  }
1560
- if (isFocus) {
1998
+ if (isFocus && !alreadyCallItemFocus) {
1561
1999
  onItemFocus(getItemById(focusId), preEdgeRect);
1562
2000
  }
1563
2001
 
@@ -1566,6 +2004,9 @@ export const setup = (
1566
2004
  itemRender.value = true;
1567
2005
  });
1568
2006
  }
2007
+ if (props.enableTouch) {
2008
+ initTouch();
2009
+ }
1569
2010
  });
1570
2011
 
1571
2012
  onUpdated(() => { });
@@ -1579,9 +2020,12 @@ export const setup = (
1579
2020
  focusBlockOnFocus,
1580
2021
  focusBlockOnBlur,
1581
2022
  focusBlockOnKeyDown,
1582
- focusBlockOnCustomerEvent,
2023
+ focusBlockOnCustomEvent,
1583
2024
  _onFocusableItemEdge,
1584
2025
  exportObject,
1585
2026
  setZIndex,
2027
+ onTouchDown,
2028
+ onTouchRelease,
2029
+ currentFocusIndex,
1586
2030
  }
1587
- }
2031
+ }