@shijiu/jsview-vue 2.0.1021 → 2.0.1073

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 (33) hide show
  1. package/package.json +4 -3
  2. package/utils/JsViewEngineWidget/CheckType.js +82 -0
  3. package/utils/JsViewEngineWidget/MetroWidget/AnimationManager.ts +72 -0
  4. package/utils/JsViewEngineWidget/MetroWidget/Const.ts +24 -0
  5. package/utils/JsViewEngineWidget/MetroWidget/ListWidget.vue +295 -0
  6. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +110 -1651
  7. package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +1867 -0
  8. package/utils/JsViewEngineWidget/MetroWidget/PageUpdater.ts +111 -0
  9. package/utils/JsViewEngineWidget/MetroWidget/RenderItem.ts +153 -0
  10. package/utils/JsViewEngineWidget/MetroWidget/VisibleInfo.ts +43 -0
  11. package/utils/JsViewEngineWidget/MetroWidget/WidgetRectInfo.ts +49 -0
  12. package/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.ts +1424 -0
  13. package/utils/JsViewEngineWidget/TemplateParser/Fence.ts +135 -0
  14. package/utils/JsViewEngineWidget/TemplateParser/ListMetroTemplate.ts +177 -0
  15. package/utils/JsViewEngineWidget/TemplateParser/MetroTemplate.ts +334 -0
  16. package/utils/JsViewEngineWidget/TemplateParser/TemplateItemAdder.ts +147 -0
  17. package/utils/JsViewEngineWidget/TemplateParser/index.ts +4 -0
  18. package/utils/JsViewEngineWidget/{WidgetCommon.js → WidgetCommon.ts} +64 -71
  19. package/utils/JsViewEngineWidget/index.js +2 -1
  20. package/utils/JsViewPlugin/JsvAudio/AudioProxy.js +26 -1
  21. package/utils/JsViewPlugin/JsvAudio/JsvAudio.vue +120 -133
  22. package/utils/JsViewPlugin/JsvAudio/JsvAudioBrowser.vue +11 -7
  23. package/utils/JsViewPlugin/JsvPlayer/GetVersion.js +1 -1
  24. package/utils/JsViewPlugin/JsvPlayer/JsvPlayerBrowser.vue +379 -41
  25. package/utils/JsViewPlugin/JsvPlayer/version.mjs +5 -5
  26. package/utils/JsViewVueTools/JsvHashHistory.js +2 -1
  27. package/utils/JsViewVueWidget/JsvRadarChart.vue +220 -0
  28. package/utils/JsViewVueWidget/JsvSystemAudio.vue +76 -44
  29. package/utils/JsViewVueWidget/index.js +1 -0
  30. package/utils/JsViewEngineWidget/MetroWidget/Const.js +0 -11
  31. package/utils/JsViewEngineWidget/MetroWidget/PageUpdater.js +0 -136
  32. package/utils/JsViewEngineWidget/MetroWidget/ToolFunctions.js +0 -18
  33. package/utils/JsViewEngineWidget/TemplateParser.js +0 -2004
@@ -17,7 +17,7 @@
17
17
  * height {int} (必选)控件的高
18
18
  * layoutType {String} 布局的类型, 目前支持 "relative"(默认)|"absolute", relative为自动布局,
19
19
  absolute为依据measures中给的top, left布局
20
- *
20
+ *
21
21
  * name {string} 用于设置焦点的名称
22
22
  * padding {object} 控件内边距, 默认为{left: 0, right: 0, top: 0, bottom: 0}
23
23
  * direction {enum} (必选)控件方向 HORIZONTAL/VERTICAL
@@ -85,6 +85,7 @@
85
85
  * flingPageWidth {}
86
86
  * flingPageEdge {}
87
87
  * disableClip {boolean} 取消显示范围的clipView
88
+
88
89
  * methods:
89
90
  getFocusBlockRef 获取此MetroWidget的 jsv-focus-block句柄,可以使用requestFocus完成获焦
90
91
 
@@ -131,10 +132,19 @@
131
132
  @params {int} type 锁的类型, 通过|来实现多个类型的复合
132
133
  SLIDE: 滚动动画锁
133
134
  CHILD_SLIDE_EVENT: 子组件发送的滚动事件锁
135
+ ON_KEY_DOWN: 按键锁
134
136
  @return {function} 解锁的函数
135
137
  unlock
136
138
  @description 解锁
137
139
  @params {int} type 参考lock的type参数
140
+ moveFocus
141
+ @description 移动焦点
142
+ @params {int | string | EdgeDirection} 可传三种类型的值:
143
+ 1. 方向键的数值 37|38|39|40,
144
+ 2. 字符串 left|top|right|bottom,
145
+ 3. EdgeDirection
146
+ getCustomerDataSize
147
+ @description 获取用户数据长度
138
148
  slots:
139
149
  renderItem: 该slot用于描画每个单元格
140
150
  background: 该slot描画在item后, 一般用于描画需要跟随MetroWidget滚动的内容
@@ -153,6 +163,11 @@
153
163
  获取当前焦点信息,id 为在可获得焦点元素列表中的索引,index 为在所有元素列表中的索引
154
164
  slideTo: {Function} (targetPosition : int, doAnim : Boolean) => void
155
165
  滚动到指定位置,注意这个位置是 item 的布局坐标,另外当某些item需要接管滚动时,itemConfig中takeOverSlide要为true。
166
+ updateItemSize: {(index: number, newSize: {width: number, height: number}, anchor: number, animInfo: {duration: number, onEnd: Function}) => void} 更新item的尺寸, 目前仅在list模式下可用.
167
+ params:
168
+ index: 更新item的index,
169
+ anchor: item大小变化时不动点的位置, 值为0-1
170
+
156
171
  }
157
172
  * onItemEdge: 若单元格内另有可接管按键的控件(如MetroWidget),该控件到达边缘需要通知MetroWidget时的回调
158
173
  * onAction: 单元格内控件需要通过onAction.register方法向MetroWidget注册 item 的回调,回调函数有
@@ -183,101 +198,14 @@
183
198
  -->
184
199
 
185
200
  <script setup>
186
- /* eslint-disable */
187
- import {
188
- ref,
189
- reactive,
190
- shallowRef,
191
- onMounted,
192
- onBeforeUnmount,
193
- onUpdated,
194
- toRaw,
195
- nextTick,
196
- } from "vue";
197
- import { Forge } from "@shijiu/jsview/dom/jsv-forge-define";
198
- import { TemplateParser, TemplateItemAdder } from "../TemplateParser";
199
- import { PageUpdater } from "./PageUpdater";
200
- import { SingleRangeModel } from "../RangeModel";
201
- import Dispatcher from "./Dispatcher";
202
- import { METRO_WIDGET } from "./Const";
201
+ import { ref, shallowRef, computed } from "vue";
202
+ import { setup, RENDER_ITEM_BREAK_KEY } from "./MetroWidgetSetup";
203
203
  import {
204
- EdgeDirection,
205
204
  VERTICAL,
206
205
  HORIZONTAL,
207
- getPositionRelativeToView,
208
206
  SlideSetting,
209
207
  SeamlessSlide,
210
208
  } from "../WidgetCommon";
211
- import { bindFunctions } from "./ToolFunctions";
212
-
213
- const _getPadding = function (padding) {
214
- return Object.assign(
215
- {
216
- left: 0,
217
- right: 0,
218
- top: 0,
219
- bottom: 0,
220
- },
221
- padding
222
- );
223
- };
224
-
225
- const _getTemplateParser = function (
226
- width,
227
- height,
228
- direction,
229
- padding,
230
- support_history_path,
231
- layout_type
232
- ) {
233
- let fixed_padding = _getPadding(padding);
234
- let page_size;
235
- let line_max;
236
- if (direction === VERTICAL) {
237
- line_max = width - fixed_padding.left - fixed_padding.right;
238
- page_size = height - fixed_padding.top - fixed_padding.bottom;
239
- } else {
240
- line_max = height - fixed_padding.top - fixed_padding.bottom;
241
- page_size = width - fixed_padding.left - fixed_padding.right;
242
- }
243
- return new TemplateParser(
244
- direction,
245
- line_max,
246
- page_size,
247
- layout_type,
248
- support_history_path
249
- );
250
- };
251
-
252
- // direction key 是 vertical 的值
253
- const directionFreeKeyMap = {
254
- pos: {
255
- true: "yPos",
256
- false: "xPos",
257
- },
258
- size: {
259
- true: "height",
260
- false: "width",
261
- },
262
- neighbor: {
263
- true: {
264
- 1: "bottom",
265
- "-1": "top",
266
- },
267
- false: {
268
- 1: "bottom",
269
- "-1": "top",
270
- },
271
- },
272
- margin: {
273
- true: "marginBottom",
274
- false: "marginRight",
275
- },
276
- center: {
277
- true: "centerYPos",
278
- false: "centerXPos",
279
- },
280
- };
281
209
 
282
210
  const props = defineProps({
283
211
  padding: {
@@ -416,1525 +344,46 @@ const props = defineProps({
416
344
  },
417
345
  });
418
346
 
419
- let dataUpdateToken = ref(0);
420
- let templateParser = null;
421
- let innerData = [];
422
- let dataList = [];
423
- let pageUpdater = null;
424
- let enterFocusId = -1;
425
- let enterFocusRect = null;
426
- let focusId = 0;
427
- let preFocusId = -1;
428
- let preEdgeRect = null;
429
- let isFocus = false;
430
- let touchContainerW = ref(0);
431
- let touchContainerH = ref(0);
432
- let touchListener = null;
433
- let innerPadding = null;
434
- let slidePile = null;
435
- let dragDirection = Forge.DragSetting.DIRECTION_HORIZONTAL;
436
- let vertical = props.direction == VERTICAL;
437
- let preAnchorItemIndex = -1;
438
- let templateItemAdder = null;
439
- let itemRender = ref(!props.enableItemRenderBreak);
440
- let permanentItemList = [];
441
- let preUpdateVisibleStart = 0;
442
- let mounted = false;
443
- let focusNode = shallowRef(null);
444
- let pageRange = vertical ? props.height : props.width;
445
-
446
- let slideLock = false;
447
- let childSlideEventLock = false;
448
-
449
- let visibleInfo = {
450
- _start: 0,
451
- range: 0,
452
- padding: {
453
- start: 0,
454
- end: 0,
455
- },
456
- _startMax: 0,
457
-
458
- set start(value) {
459
- this._start = value;
460
- this._startMax = Math.max(this._start, this._startMax);
461
- },
462
-
463
- get start() {
464
- return this._start;
465
- },
466
-
467
- get end() {
468
- return this._start + this.range - 1;
469
- },
470
-
471
- get startMax() {
472
- return this._startMax;
473
- },
474
-
475
- get startWithPadding() {
476
- return this._start - this.padding.start;
477
- },
478
-
479
- get endWithPadding() {
480
- return this._start + this.range + this.padding.end - 1;
481
- },
482
- };
483
-
484
- let locateDiv = shallowRef(null);
485
- let slideDiv = shallowRef(null);
486
- let renderData = shallowRef([]);
487
- let slideDivLeft = ref(0);
488
- let slideDivTop = ref(0);
489
- let callFocusAfterUpdate = false;
490
- let renderBreakKey = props.enableItemRenderBreak
491
- ? "__QcodeJsviewMetroWidgetSlot"
492
- : "";
493
- let pageUpdateToken = ref(0);
494
-
495
- //methods
496
- const _onFocusChange = (id) => {
497
- props.onFocusChange?.(id);
498
- };
499
-
500
- const _getCurrentId = () => {
501
- return {
502
- id: focusId,
503
- index: templateParser.IdToIndex(focusId),
504
- };
505
- };
506
-
507
- const _getPosition = (index) => {
508
- let item = templateParser.GetItem(index);
509
- let x_offset = props.direction === VERTICAL ? 0 : -visibleInfo.start;
510
- let y_offset = props.direction === VERTICAL ? -visibleInfo.start : 0;
511
- return {
512
- left: item.xPos + x_offset,
513
- top: item.yPos + y_offset,
514
- width: item.width,
515
- height: item.height,
516
- };
517
- };
518
-
519
- const _getTemplatePosition = (index) => {
520
- let item = templateParser.GetItem(index);
521
- return {
522
- left: item.xPos,
523
- top: item.yPos,
524
- width: item.width,
525
- height: item.height,
526
- };
527
- };
528
-
529
- const _dispatchEvent = (event) => {
530
- switch (event.type) {
531
- case Dispatcher.Type.setEnterFocusId:
532
- setEnterFocusId(event.data);
533
- break;
534
- case Dispatcher.Type.setEnterFocusRect:
535
- setEnterFocusRect(event.data);
536
- break;
537
- case Dispatcher.Type.updateItem:
538
- break;
539
- case Dispatcher.Type.slideToItem:
540
- if (event.data) {
541
- slideToItem(event.data?.id, event.data?.doAnim);
542
- }
543
- break;
544
- case Dispatcher.Type.setFocusId:
545
- setFocusId(event.data?.id, event.data?.needSlide, event.data?.doAnim);
546
- break;
547
- default:
548
- break;
549
- }
550
- };
551
-
552
- const onItemClick = (index) => {
553
- if (isFocus && innerData[index]?.callbacks.callable("onClick")) {
554
- innerData[index].callbacks.onClick();
555
- }
556
- };
557
-
558
- const onItemBlur = (index) => {
559
- if (isFocus && innerData[index]?.callbacks.callable("onBlur")) {
560
- innerData[index].callbacks.onBlur();
561
- }
562
- };
563
-
564
- const onItemFocus = (index, rect) => {
565
- if (isFocus) {
566
- if (innerData[index]) {
567
- _itemOnFocusSideEffect(innerData[index], rect);
568
- if (innerData[index].callbacks.callable("onFocus")) {
569
- innerData[index].callbacks.onFocus(rect);
570
- } else {
571
- callFocusAfterUpdate = true;
572
- }
573
- }
574
- }
575
- };
576
-
577
- const setFocusId = (id, needSlide = true, doAnim = false, extraSetting) => {
578
- if (id == focusId) {
579
- return;
580
- }
581
- templateItemAdder.tryAddItemById(id);
582
- let next_focus_item = templateParser.GetItemById(id);
583
- if (next_focus_item) {
584
- if (needSlide) {
585
- slideToItem(templateParser.IdToIndex(id), doAnim);
586
- }
587
- let unlock = null;
588
- if (extraSetting) {
589
- if (extraSetting.lockChildSlideEvent) {
590
- unlock = lock(METRO_WIDGET.CHILD_SLIDE_EVENT);
591
- }
592
- }
593
-
594
- const cur_focus_item = templateParser.GetItemById(focusId);
595
- preFocusId = focusId;
596
- focusId = next_focus_item.id;
597
-
598
- let x_off_set = cur_focus_item.xPos - next_focus_item.xPos;
599
- let y_off_set = cur_focus_item.yPos - next_focus_item.yPos;
600
- preEdgeRect = {
601
- direction: null,
602
- rect: {
603
- x: x_off_set,
604
- y: y_off_set,
605
- width: cur_focus_item.width,
606
- height: cur_focus_item.height,
607
- },
608
- };
609
- _updateBlurItem();
610
- _updateFocusItem();
611
- onItemBlur(templateParser.IdToIndex(preFocusId));
612
- onItemFocus(templateParser.IdToIndex(focusId), preEdgeRect);
613
- unlock?.();
614
- }
615
- };
616
-
617
- const lock = (type) => {
618
- const unlocker = [];
619
- if (type & METRO_WIDGET.SLIDE) {
620
- slideLock = true;
621
- unlocker.push(() => {
622
- slideLock = false;
623
- });
624
- }
625
- if (type & METRO_WIDGET.CHILD_SLIDE_EVENT) {
626
- childSlideEventLock = true;
627
- unlocker.push(() => {
628
- childSlideEventLock = false;
629
- });
630
- }
631
- return () => {
632
- unlocker.map((item) => {
633
- item();
634
- });
635
- };
636
- };
637
-
638
- const unlock = (type) => {
639
- if (type & METRO_WIDGET.SLIDE) {
640
- slideLock = true;
641
- }
642
- if (type & METRO_WIDGET.CHILD_SLIDE_EVENT) {
643
- childSlideEventLock = true;
644
- }
645
- };
646
-
647
- const getFocusBlockRef = () => {
648
- return toRaw(focusNode.value);
649
- };
650
-
651
- const setEnterFocusId = (id) => {
652
- templateItemAdder.tryAddItemById(id);
653
- enterFocusId = id;
654
- };
655
-
656
- const setEnterFocusRect = (rect) => {
657
- enterFocusRect = rect;
658
- };
659
-
660
- const slideTo = (position, doAnim) => {
661
- templateItemAdder.tryAddItemByPosition(position);
662
- if (
663
- typeof position !== "undefined" &&
664
- position != null &&
665
- visibleInfo.start !== position
666
- ) {
667
- visibleInfo.start = position;
668
- let animObj = null;
669
- if (doAnim) {
670
- animObj = {
671
- easing: props.slideSetting.Easing,
672
- onstart: null,
673
- speed: props.slideSetting.Speed,
674
- onend: _onSlideEnd,
675
- };
676
- }
677
- _slideTo(visibleInfo.start, animObj);
678
-
679
- pageUpdater.update(
680
- templateParser,
681
- visibleInfo.startWithPadding,
682
- visibleInfo.endWithPadding,
683
- focusId,
684
- false,
685
- permanentItemList
686
- );
687
- if (doAnim) {
688
- pageUpdater.applyTmp();
689
- } else {
690
- pageUpdater.apply();
691
- }
692
- }
693
- };
694
-
695
- const slideToItem = (index, doAnim) => {
696
- templateItemAdder.tryAddItemByIndex(index);
697
- const targetItem = templateParser.GetItem(index);
698
- if (targetItem) {
699
- const direction = index - preAnchorItemIndex > 0 ? 1 : -1;
700
- const visible_start = _calculateVisibleStart(targetItem, direction);
701
- slideTo(visible_start, doAnim);
702
- }
703
- };
704
-
705
- const refreshData = (force_update) => {
706
- //由于data不支持reactive, 因此数据的更新只通过provideData
707
- if (!props.provideData) {
708
- console.error("refreshData: provideData is null.");
709
- return;
710
- }
711
- let _force_update = force_update;
712
- let template_list = templateParser.GetTemplate().List;
713
- if (!template_list || template_list.length === 0) {
714
- _force_update = true;
715
- }
716
- let new_list = toRaw(props.provideData());
717
- let needSlide = false;
718
- if (focusId >= new_list.length) {
719
- focusId = 0;
720
- preFocusId = -1;
721
- if (visibleInfo.start !== 0) {
722
- visibleInfo.start = 0;
723
- needSlide = true;
724
- }
725
- }
726
- let new_index = 0;
727
- if (!_force_update) {
728
- for (new_index = 0; new_index < new_list.length; ++new_index) {
729
- let already_add = false;
730
- for (let j = 0; j < template_list.length; ++j) {
731
- if (new_list[new_index] === template_list[j].data) {
732
- already_add = true;
733
- break;
734
- }
735
- }
736
- if (!already_add) {
737
- break;
738
- }
739
- }
740
- }
741
- let need_update_content = false;
742
- if (!_force_update && new_index === template_list.length) {
743
- //原始数据都在
744
- if (new_index !== new_list.length) {
745
- //增加数据
746
- need_update_content = true;
747
- templateItemAdder.updateData(new_list);
748
- } else {
749
- //数据没变
750
- }
751
- } else {
752
- pageUpdateToken.value++;
753
- //数据更改
754
- permanentItemList = [];
755
- need_update_content = true;
756
- templateParser = _getTemplateParser(
757
- props.width,
758
- props.height,
759
- props.direction,
760
- props.padding,
761
- props.supportHistoryPath,
762
- props.layoutType
763
- );
764
- innerData = [];
765
- dataList = new_list;
766
- templateItemAdder = new TemplateItemAdder(
767
- templateParser,
768
- dataList,
769
- props.measures,
770
- pageRange,
771
- _onTemplateAdd,
772
- props.name
773
- );
774
- }
775
- if (need_update_content) {
776
- if (props.onScroll) {
777
- templateItemAdder.tryAddItemByIndex(dataList.length - 1);
778
- } else {
779
- templateItemAdder.tryAddItemById(focusId);
780
- }
781
- let template_list = templateParser.GetTemplate().List;
782
- let last_item = template_list[template_list.length - 1];
783
- touchListener = _getTouchListener();
784
- innerPadding = _getPadding(props.padding);
785
- touchContainerW.value =
786
- props.direction === VERTICAL
787
- ? props.width
788
- : last_item
789
- ? last_item.xPos + last_item.width
790
- : 0;
791
- touchContainerH.value =
792
- props.direction === VERTICAL
793
- ? last_item
794
- ? last_item.yPos + last_item.height
795
- : 0
796
- : props.height;
797
- slidePile = new Forge.RectArea(
798
- 0,
799
- 0,
800
- props.width - innerPadding.left - innerPadding.right,
801
- props.height - innerPadding.top - innerPadding.bottom
802
- );
803
- dragDirection =
804
- props.direction === VERTICAL
805
- ? Forge.DragSetting.DIRECTION_VERTICAL
806
- : Forge.DragSetting.DIRECTION_HORIZONTAL;
807
- }
808
- pageUpdater.update(
809
- templateParser,
810
- visibleInfo.startWithPadding,
811
- visibleInfo.endWithPadding,
812
- focusId,
813
- false,
814
- permanentItemList
815
- );
816
- dataUpdateToken.value++;
817
- pageUpdater.apply();
818
- _updateFocusItem();
819
- onItemFocus(templateParser.IdToIndex(focusId), null);
820
- if (needSlide) {
821
- _slideTo(visibleInfo.start, null);
822
- } else if (need_update_content) {
823
- _onScroll();
824
- }
825
- };
826
-
827
- const getVisibleItems = () => {
828
- const info = templateParser.GetVisibleItemList(
829
- visibleInfo.startWithPadding,
830
- visibleInfo.endWithPadding,
831
- focusId,
832
- false,
833
- null
834
- );
835
- return {
836
- start: info.visibleStart,
837
- end: info.visibleEnd,
838
- dataList: dataList.slice(info.visibleStart, info.visibleEnd + 1),
839
- };
840
- };
841
-
842
- const exportObject = {
843
- lock,
844
- unlock,
845
- slideTo,
846
- setFocusId,
847
- getFocusBlockRef,
848
- setEnterFocusId,
849
- setEnterFocusRect,
850
- slideToItem,
851
- refreshData,
852
- _dispatchEvent,
853
- getVisibleItems,
854
- };
855
-
856
- const _calculateNearestItemByRect = (visible_range, enter_rect_info) => {
857
- let edge_direction = enter_rect_info.direction;
858
- let rect = enter_rect_info.rect;
859
- var direction = "";
860
- var point = { x: 0, y: 0 };
861
- switch (edge_direction) {
862
- case EdgeDirection.left:
863
- direction = "left";
864
- point.x = rect.x;
865
- point.y = rect.y + rect.height / 4;
866
- break;
867
- case EdgeDirection.right:
868
- direction = "right";
869
- point.x = rect.x + rect.width;
870
- point.y = rect.y + rect.height / 4;
871
- break;
872
- case EdgeDirection.top:
873
- direction = "up";
874
- point.x = rect.x + rect.width / 4;
875
- point.y = rect.y;
876
- break;
877
- case EdgeDirection.bottom:
878
- direction = "down";
879
- point.x = rect.x + rect.width / 4;
880
- point.y = rect.y + rect.height;
881
- break;
882
- default:
883
- break;
884
- }
885
-
886
- var src_x_range = new SingleRangeModel(point.x, point.x);
887
- var src_y_range = new SingleRangeModel(point.y, point.y);
888
-
889
- var min_distance_item = null;
890
- var min_distance = -1;
891
- var min_direction_weighted = 0;
892
- var distance = 0;
893
- var direction_weighted = 0; // 根据进入方向决定的权值,用于保证
894
-
895
- let key_pos = props.direction === VERTICAL ? "yPos" : "xPos";
896
- let key_width = props.direction === VERTICAL ? "height" : "width";
897
- for (let index = visible_range.start; index <= visible_range.end; index++) {
898
- let item = templateParser.GetItem(index);
899
- if (!item.focusable) continue;
900
- let full_show =
901
- item[key_pos] >= visibleInfo.start &&
902
- item[key_pos] + item[key_width] - 1 <= visibleInfo.end;
903
- if (full_show) {
904
- let x_pos =
905
- props.direction === VERTICAL
906
- ? item.xPos
907
- : item.xPos - visibleInfo.start;
908
- let y_pos =
909
- props.direction === VERTICAL
910
- ? item.yPos - visibleInfo.start
911
- : item.yPos;
912
- var target_x_range = new SingleRangeModel(x_pos, x_pos + item.width - 1);
913
- var target_y_range = new SingleRangeModel(y_pos, y_pos + item.height - 1);
914
- switch (direction) {
915
- case "left":
916
- if (point.x < x_pos + item.width - 1) {
917
- // 这个点在item左侧,不可能左移到item
918
- continue;
919
- }
920
- if (point.y < y_pos) {
921
- //1.该点在其上,计算point和item右上角的距离
922
- distance =
923
- Math.pow(point.x - (x_pos + item.width - 1), 2) +
924
- Math.pow(y_pos - point.y, 2);
925
- } else if (src_y_range.IsInterAct(target_y_range)) {
926
- //2.该点在其中,计算point和item右边框的垂直距离
927
- distance = Math.pow(point.x - (x_pos + item.width - 1), 2);
928
- } else if (point.y > y_pos + item.height - 1) {
929
- //3.该点在其下,计算point到item右下角的距离
930
- distance =
931
- Math.pow(point.x - (x_pos + item.width - 1), 2) +
932
- Math.pow(point.y - (y_pos + item.height - 1), 2);
933
- }
934
- // point与item右边框的距离作为权值
935
- direction_weighted = Math.abs(point.x - (x_pos + item.width - 1));
936
- break;
937
- case "right":
938
- if (point.x > x_pos) {
939
- // 这个点在item右侧,不可能右移到item
940
- continue;
941
- }
942
- if (point.y < y_pos) {
943
- //1.该点在其上, 计算point和item左上角的距离
944
- distance =
945
- Math.pow(x_pos - point.x, 2) + Math.pow(y_pos - point.y, 2);
946
- } else if (src_y_range.IsInterAct(target_y_range)) {
947
- //2.该点在其中,计算point和item左边框的垂直距离
948
- distance = Math.pow(x_pos - point.x, 2);
949
- //(x2-x1)^2
950
- } else if (point.y > y_pos + item.height - 1) {
951
- //3.该点在其下,计算point和item左下角的距离
952
- distance =
953
- Math.pow(x_pos - point.x, 2) +
954
- Math.pow(point.y - (y_pos + item.height - 1), 2);
955
- }
956
- // point与item左边框的距离作为权值
957
- direction_weighted = Math.abs(point.x - x_pos);
958
- break;
959
- case "up":
960
- if (point.y < y_pos + item.height - 1) {
961
- // 这个点在item上侧,不可能上移到item
962
- continue;
963
- }
964
- if (point.x < x_pos) {
965
- //1.该点在其前,计算point和item右下角的距离
966
- distance =
967
- Math.pow(point.x - x_pos, 2) +
968
- Math.pow(point.y - (y_pos + item.height - 1), 2);
969
- } else if (src_x_range.IsInterAct(target_x_range)) {
970
- //2.该点在其中,计算point和item下边框的垂直距离
971
- distance = Math.pow(point.y - (y_pos + item.height - 1), 2);
972
- } else if (point.x > x_pos + item.width - 1) {
973
- //3.该点在其后,计算point和item左下角的距离
974
- distance =
975
- Math.pow(point.x - (x_pos + item.width - 1), 2) +
976
- Math.pow(point.y - (y_pos + item.height - 1), 2);
977
- }
978
- // point与item下边框的距离作为权值
979
- direction_weighted = Math.abs(point.y - (y_pos + item.height - 1));
980
- break;
981
- case "down":
982
- if (point.y > y_pos) {
983
- // 这个点在item下侧,不可能下移到item
984
- continue;
985
- }
986
- if (point.x < x_pos) {
987
- //1.该点在其前,计算point和item右上角的距离
988
- distance =
989
- Math.pow(point.x - x_pos, 2) + Math.pow(y_pos - point.y, 2);
990
- } else if (src_x_range.IsInterAct(target_x_range)) {
991
- //2.该点在其中,计算point和item上边框的垂直距离
992
- distance = Math.pow(y_pos - point.y, 2);
993
- } else if (point.x > x_pos + item.width - 1) {
994
- //3.该点在其后,计算point和item左上角的距离
995
- distance =
996
- Math.pow(point.x - (x_pos + item.width - 1), 2) +
997
- Math.pow(y_pos - point.y, 2);
998
- }
999
- // point与item上边框的距离作为权值
1000
- direction_weighted = Math.abs(point.y - y_pos);
1001
- break;
1002
- default:
1003
- console.log("direction is error:" + direction);
1004
- break;
1005
- }
1006
- if (min_distance < 0) {
1007
- // 设置首个找到的项目
1008
- min_distance = distance;
1009
- min_direction_weighted = direction_weighted;
1010
- min_distance_item = item;
1011
- } else {
1012
- if (
1013
- min_direction_weighted > direction_weighted ||
1014
- (min_direction_weighted === direction_weighted &&
1015
- min_distance > distance)
1016
- ) {
1017
- // 先进行权值比较,在权值相等时,再比较距离
1018
- min_distance = distance;
1019
- min_direction_weighted = direction_weighted;
1020
- min_distance_item = item;
1021
- }
1022
- }
1023
- }
1024
- }
1025
-
1026
- if (min_distance_item) {
1027
- return min_distance_item.id;
1028
- } else {
1029
- return 0;
1030
- }
1031
- };
1032
-
1033
- const onKeyDown = (ev) => {
1034
- if (innerData.length == 0) {
1035
- const edgeDirectionMap = {
1036
- 37: EdgeDirection.left,
1037
- 38: EdgeDirection.top,
1038
- 39: EdgeDirection.right,
1039
- 40: EdgeDirection.bottom,
1040
- };
1041
- if (typeof edgeDirectionMap[ev.keyCode] !== "undefined") {
1042
- props.onEdge?.({
1043
- direction: edgeDirectionMap[ev.keyCode],
1044
- rect: {
1045
- x: 0,
1046
- y: 0,
1047
- width: 0,
1048
- height: 0,
1049
- },
1050
- });
1051
- return true;
1052
- }
1053
- return false;
1054
- }
1055
- let horizontal_direction = 0;
1056
- let vertical_direction = 0;
1057
- switch (ev.keyCode) {
1058
- case 37:
1059
- horizontal_direction = -1;
1060
- _moveToNext(horizontal_direction, vertical_direction);
1061
- break;
1062
- case 38:
1063
- vertical_direction = -1;
1064
- _moveToNext(horizontal_direction, vertical_direction);
1065
- break;
1066
- case 39:
1067
- horizontal_direction = 1;
1068
- _moveToNext(horizontal_direction, vertical_direction);
1069
- break;
1070
- case 40:
1071
- vertical_direction = 1;
1072
- _moveToNext(horizontal_direction, vertical_direction);
1073
- break;
1074
- case 13:
1075
- onItemClick(templateParser.IdToIndex(focusId));
1076
- break;
1077
- default:
1078
- //只接受上下左右确定键
1079
- return false;
1080
- }
1081
- return true;
1082
- };
1083
-
1084
- const _slideTo = (target, animObj) => {
1085
- if (props.direction === HORIZONTAL) {
1086
- _updatePosition(-target, 0, animObj);
1087
- } else {
1088
- _updatePosition(0, -target, animObj);
1089
- }
1090
- };
1091
-
1092
- const _onTemplateAdd = (item) => {
1093
- let obj = {
1094
- data: item,
1095
- index: innerData.length,
1096
- controller: reactive({
1097
- zIndex: item.normalZIndex >= 0 ? item.normalZIndex : 0,
1098
- }),
1099
- mounted: false,
1100
- itemDivRef: null,
1101
- touchInited: false,
1102
- refCallback(el) {
1103
- if (el == null) {
1104
- this.touchInited = false;
1105
- this.customerCallback = {};
1106
- }
1107
- this.itemDivRef = el;
1108
- },
1109
- slotMounted: ref(false),
1110
- slotDivRef(el) {
1111
- if (!this.slotMounted.value && el) {
1112
- this.slotMounted.value = true;
1113
- if (callFocusAfterUpdate && this.data.id === focusId) {
1114
- nextTick(() => {
1115
- onItemFocus(templateParser.IdToIndex(focusId), preEdgeRect);
1116
- });
1117
- callFocusAfterUpdate = false;
1118
- }
1119
- } else if (!el && this.slotMounted.value) {
1120
- this.slotMounted.value = false;
1121
- }
1122
- },
1123
- customerCallback: {},
1124
- register: {
1125
- register(name, func) {
1126
- this.customerCallback[name] = func;
1127
- },
1128
- unregister(name) {
1129
- delete this.customerCallback[name];
1130
- },
1131
- },
1132
- callbacks: {
1133
- callable(name) {
1134
- return this.slotMounted.value && this.customerCallback[name];
1135
- },
1136
- onFocus(preEdge) {
1137
- this.customerCallback.onFocus?.(preEdge);
1138
- },
1139
- onBlur() {
1140
- this.customerCallback.onBlur?.();
1141
- },
1142
- onClick() {
1143
- this.customerCallback.onClick?.();
1144
- },
1145
- onWidgetEdge(rect) {
1146
- this.customerCallback.onWidgetEdge?.(rect);
1147
- },
1148
- },
1149
- itemConfig: props.itemConfig?.(item.data),
1150
- query: {
1151
- id: item.id,
1152
- index: item.index,
1153
- position: _getPosition,
1154
- templatePosition: _getTemplatePosition,
1155
- getCurrentFocusId: _getCurrentId,
1156
- slideTo: slideTo,
1157
- },
1158
- };
1159
- bindFunctions(obj, obj);
1160
- innerData.push(obj);
1161
- if (item.permanent) {
1162
- permanentItemList.push({
1163
- index: innerData.length - 1,
1164
- alreadyShow: false,
1165
- });
1166
- }
1167
- const lastItem = templateParser.GetItem(-1);
1168
- if (props.direction == VERTICAL) {
1169
- touchContainerH.value = lastItem.yPos + lastItem.height - 1;
1170
- } else {
1171
- touchContainerW.value = lastItem.xPos + lastItem.width - 1;
1172
- }
1173
- };
1174
-
1175
- const _itemOnFocusSideEffect = (item, edgeRect) => {
1176
- _onFocusChange(item.data.id);
1177
- if (item.itemDivRef) {
1178
- let event = {
1179
- type: "focusRect",
1180
- direction: edgeRect?.direction?.description,
1181
- element: toRaw(item.itemDivRef),
1182
- };
1183
- _bubbleCustomerEvent(event);
1184
- }
1185
- };
1186
-
1187
- const _onCustomerEvent = (ev) => {
1188
- if (ev.type === "focusRect") {
1189
- if (childSlideEventLock) {
1190
- return true;
1191
- }
1192
- if (ev.ownerNode == exportObject) {
1193
- return false;
1194
- }
1195
- let item_div = ev.element;
1196
- let direction = 0;
1197
- if (props.direction == HORIZONTAL) {
1198
- if (ev.direction == "left") {
1199
- direction = -1;
1200
- } else if (ev.direction == "right") {
1201
- direction = 1;
1202
- }
1203
- } else {
1204
- if (ev.direction == "top") {
1205
- direction = -1;
1206
- } else if (ev.direction == "bottom") {
1207
- direction = 1;
1208
- }
1209
- }
1210
- const item_layout = item_div.jsvGetRelativePosition(toRaw(locateDiv.value));
1211
-
1212
- let obj = {
1213
- xPos: item_layout.left,
1214
- yPos: item_layout.top,
1215
- width: item_layout.width,
1216
- height: item_layout.height,
1217
- centerYPos: Math.floor(item_layout.top + item_layout.height / 2),
1218
- centerXPos: Math.floor(item_layout.left + item_layout.width / 2),
1219
- index: templateParser.IdToIndex(focusId),
1220
- };
1221
-
1222
- let cur_slide = _calculateVisibleStart(obj, direction);
1223
- if (cur_slide != visibleInfo.start) {
1224
- visibleInfo.start = cur_slide;
1225
- pageUpdater.update(
1226
- templateParser,
1227
- visibleInfo.startWithPadding - props.keepTraceRange * pageRange,
1228
- Math.min(
1229
- visibleInfo.startMax +
1230
- visibleInfo.range +
1231
- visibleInfo.padding.end -
1232
- 1,
1233
- visibleInfo.endWithPadding + props.keepTraceRange * pageRange
1234
- ),
1235
- focusId,
1236
- true,
1237
- permanentItemList
1238
- );
1239
- pageUpdater.applyTmp();
1240
- _slideTo(visibleInfo.start, {
1241
- easing: "",
1242
- onstart: null,
1243
- speed: props.slideSetting.Speed,
1244
- onend: _onSlideEnd,
1245
- });
1246
- return true;
1247
- }
1248
- }
1249
- return false;
1250
- };
1251
-
1252
- const _bubbleCustomerEvent = (event) => {
1253
- if (props.sendFocusRectEvent && event) {
1254
- event.ownerNode = exportObject;
1255
- toRaw(focusNode.value)?.bubbleCustomerEvent(event);
1256
- }
1257
- };
1258
-
1259
- const _moveToNext = (
1260
- horizontal_direction,
1261
- vertical_direction,
1262
- item_edge_rect
1263
- ) => {
1264
- let cur_focus_item = templateParser.GetItemById(focusId);
1265
- let next_focus_item = templateParser.GetNextItem(
1266
- focusId,
1267
- vertical_direction,
1268
- horizontal_direction,
1269
- props.focusMoveType
1270
- );
1271
- if (next_focus_item !== null) {
1272
- preFocusId = focusId;
1273
- templateItemAdder.tryAddItem(next_focus_item, 1);
1274
- focusId = next_focus_item.id;
1275
-
1276
- let direction =
1277
- props.direction === VERTICAL ? vertical_direction : horizontal_direction;
1278
-
1279
- let cur_visible_start = _calculateVisibleStart(next_focus_item, direction);
1280
- if (
1281
- !innerData[templateParser.IdToIndex(focusId)].itemConfig?.takeOverSlide &&
1282
- visibleInfo.start !== cur_visible_start
1283
- ) {
1284
- if (next_focus_item.doSlide) {
1285
- visibleInfo.start = cur_visible_start;
1286
- let animObj = {
1287
- easing: "",
1288
- onstart: null,
1289
- speed: props.slideSetting.Speed,
1290
- onend: _onSlideEnd,
1291
- };
1292
- _slideTo(visibleInfo.start, animObj);
1293
- pageUpdater.update(
1294
- templateParser,
1295
- visibleInfo.startWithPadding - props.keepTraceRange * pageRange,
1296
- Math.min(
1297
- visibleInfo.startMax +
1298
- visibleInfo.range +
1299
- visibleInfo.padding.end -
1300
- 1,
1301
- visibleInfo.endWithPadding + props.keepTraceRange * pageRange
1302
- ),
1303
- next_focus_item.id,
1304
- false,
1305
- permanentItemList
1306
- );
1307
- } else {
1308
- //不做滚动时,保证获焦的item创建
1309
- pageUpdater.update(
1310
- templateParser,
1311
- cur_visible_start,
1312
- cur_visible_start + visibleInfo.range + visibleInfo.padding.end - 1,
1313
- next_focus_item.id,
1314
- false,
1315
- permanentItemList
1316
- );
1317
- }
1318
- pageUpdater.applyTmp();
1319
- }
1320
-
1321
- let rect;
1322
- let x_off_set = cur_focus_item.xPos - next_focus_item.xPos;
1323
- let y_off_set = cur_focus_item.yPos - next_focus_item.yPos;
1324
- if (item_edge_rect && item_edge_rect.rect) {
1325
- item_edge_rect.rect.x += x_off_set;
1326
- item_edge_rect.rect.y += y_off_set;
1327
- rect = item_edge_rect;
1328
- } else {
1329
- let direction;
1330
- if (horizontal_direction > 0) {
1331
- direction = EdgeDirection.right;
1332
- } else if (horizontal_direction < 0) {
1333
- direction = EdgeDirection.left;
1334
- } else if (vertical_direction > 0) {
1335
- direction = EdgeDirection.bottom;
1336
- } else if (vertical_direction < 0) {
1337
- direction = EdgeDirection.top;
1338
- }
1339
- rect = {
1340
- direction,
1341
- rect: {
1342
- x: x_off_set,
1343
- y: y_off_set,
1344
- width: cur_focus_item.width,
1345
- height: cur_focus_item.height,
1346
- },
1347
- };
1348
- }
1349
- preEdgeRect = rect;
1350
- _updateBlurItem();
1351
- _updateFocusItem();
1352
- onItemBlur(templateParser.IdToIndex(preFocusId));
1353
- onItemFocus(templateParser.IdToIndex(focusId), preEdgeRect);
1354
- } else {
1355
- let x_off_set = props.direction === VERTICAL ? 0 : visibleInfo.start;
1356
- let y_off_set = props.direction === VERTICAL ? visibleInfo.start : 0;
1357
- let edge;
1358
- if (horizontal_direction === 1) {
1359
- edge = EdgeDirection.right;
1360
- }
1361
- if (horizontal_direction === -1) {
1362
- edge = EdgeDirection.left;
1363
- }
1364
- if (vertical_direction === 1) {
1365
- edge = EdgeDirection.bottom;
1366
- }
1367
- if (vertical_direction === -1) {
1368
- edge = EdgeDirection.top;
1369
- }
1370
- let rect = {
1371
- x: cur_focus_item.xPos - x_off_set,
1372
- y: cur_focus_item.yPos - y_off_set,
1373
- width: cur_focus_item.width,
1374
- height: cur_focus_item.height,
1375
- };
1376
- props.onEdge?.({ direction: edge, rect: rect });
1377
- innerData[templateParser.IdToIndex(focusId)].callbacks.onWidgetEdge?.({
1378
- direction: edge,
1379
- });
1380
- }
1381
- };
1382
-
1383
- const _calculateVisibleStart = (target_item, direction) => {
1384
- if (!target_item) {
1385
- console.error("MetroWidget: _calculateVisibleStart target item is null");
1386
- return 0;
1387
- }
1388
- preAnchorItemIndex = target_item.index;
1389
- let pos_key = directionFreeKeyMap.pos[vertical];
1390
- let size_key = directionFreeKeyMap.size[vertical];
1391
- let center_key = directionFreeKeyMap.center[vertical];
1392
- let new_visible_start = visibleInfo.start;
1393
-
1394
- switch (props.slideSetting.Type) {
1395
- case SlideSetting.Type.FIX_POSITION:
1396
- //FIX_POSITION 模式会将当前 item 的中心固定到指定位置
1397
- new_visible_start = Math.ceil(
1398
- target_item[center_key] -
1399
- visibleInfo.range * props.slideSetting.FixPercent
1400
- );
1401
- break;
1402
- case SlideSetting.Type.WHOLE_PAGE:
1403
- if (typeof target_item.pageHeadIndex == "undefined") {
1404
- //TODO 子控制滚动时whole page滚动
1405
- console.error(
1406
- "child controlled whole page slide type is not supported."
1407
- );
1408
- } else {
1409
- new_visible_start = templateParser.GetItem(target_item.pageHeadIndex)[
1410
- pos_key
1411
- ];
1412
- }
1413
-
1414
- break;
1415
- case SlideSetting.Type.SEAMLESS:
1416
- if (
1417
- target_item[size_key] >=
1418
- visibleInfo.range *
1419
- (props.slideSetting.EndPercent - props.slideSetting.StartPercent)
1420
- ) {
1421
- //尺寸较大的item
1422
- new_visible_start = target_item[center_key] - visibleInfo.range * 0.5;
1423
- } else {
1424
- if (direction > 0) {
1425
- if (
1426
- target_item[pos_key] + target_item[size_key] >
1427
- visibleInfo.start +
1428
- visibleInfo.range * props.slideSetting.EndPercent
1429
- ) {
1430
- new_visible_start =
1431
- target_item[pos_key] +
1432
- target_item[size_key] -
1433
- visibleInfo.range * props.slideSetting.EndPercent;
1434
- }
1435
- } else if (direction < 0) {
1436
- if (
1437
- target_item[pos_key] <
1438
- visibleInfo.start +
1439
- visibleInfo.range * props.slideSetting.StartPercent
1440
- ) {
1441
- new_visible_start =
1442
- target_item[pos_key] -
1443
- visibleInfo.range * props.slideSetting.StartPercent;
1444
- }
1445
- } else {
1446
- //不是沿widget方向的移动
1447
- if (target_item[pos_key] < visibleInfo.start) {
1448
- new_visible_start =
1449
- target_item[pos_key] -
1450
- visibleInfo.range * props.slideSetting.StartPercent;
1451
- } else if (
1452
- target_item[pos_key] + target_item[size_key] >
1453
- visibleInfo.end
1454
- ) {
1455
- new_visible_start =
1456
- target_item[pos_key] +
1457
- target_item[size_key] -
1458
- visibleInfo.range * props.slideSetting.EndPercent;
1459
- }
1460
- }
1461
- }
1462
- break;
1463
- default:
1464
- console.error(
1465
- "MetroWidget: undefined slide type",
1466
- props.slideSetting.Type
1467
- );
1468
- }
1469
-
1470
- if ((props.slideSetting.BoundaryProtect & SlideSetting.START_PROTECT) > 0) {
1471
- let boundary = 0;
1472
- //首个元素是占位符时, 在保证获焦区域完全展示的前提下要保证首个不可获焦元素的完全展示
1473
- if (
1474
- !templateParser.GetItem(0).focusable &&
1475
- target_item[pos_key] + target_item[size_key] <= visibleInfo.range
1476
- ) {
1477
- boundary = templateParser.GetItem(0)[size_key];
1478
- }
1479
- new_visible_start = new_visible_start < boundary ? 0 : new_visible_start;
1480
- }
1481
- if ((props.slideSetting.BoundaryProtect & SlideSetting.END_PROTECT) > 0) {
1482
- let last_item = templateParser.GetItem(-1);
1483
- let last_visible_start =
1484
- last_item[pos_key] + last_item[size_key] - visibleInfo.range;
1485
- last_visible_start = last_visible_start < 0 ? 0 : last_visible_start;
1486
- let boundary = last_visible_start;
1487
- if (
1488
- !last_item.focusable &&
1489
- target_item[pos_key] - last_visible_start >= 0
1490
- ) {
1491
- //最后元素是占位符, 在保证获焦区域完全展示的前提下要保证不可获焦元素的完全展示
1492
- boundary = last_item[pos_key] - visibleInfo.range;
1493
- }
1494
- new_visible_start =
1495
- new_visible_start > boundary ? last_visible_start : new_visible_start;
1496
- }
1497
- return Math.round(new_visible_start);
1498
- };
1499
-
1500
- const _onFocusableItemEdge = (edge_info) => {
1501
- let horizontal_direction = 0;
1502
- let vertical_direction = 0;
1503
- switch (edge_info.direction) {
1504
- case EdgeDirection.left:
1505
- horizontal_direction = -1;
1506
- break;
1507
- case EdgeDirection.right:
1508
- horizontal_direction = 1;
1509
- break;
1510
- case EdgeDirection.top:
1511
- vertical_direction = -1;
1512
- break;
1513
- case EdgeDirection.bottom:
1514
- vertical_direction = 1;
1515
- break;
1516
- default:
1517
- break;
1518
- }
1519
- _moveToNext(horizontal_direction, vertical_direction, edge_info);
1520
- };
1521
-
1522
- const _ifValidEnterRect = (rect_info) => {
1523
- return rect_info && rect_info.direction && rect_info.rect;
1524
- };
1525
-
1526
- const _setZIndex = (index, z_index, is_focus) => {
1527
- if (innerData[index]) {
1528
- let data = innerData[index].data,
1529
- i = z_index;
1530
- if (is_focus && data.focusZIndex >= 0) {
1531
- i = data.focusZIndex;
1532
- } else if (data.normalZIndex >= 0) {
1533
- i = data.normalZIndex;
1534
- }
1535
- innerData[index].controller.zIndex = i;
1536
- }
1537
- };
1538
-
1539
- const _onFocus = (params) => {
1540
- isFocus = true;
1541
- preFocusId = -1;
1542
- if (innerData.length === 0) {
1543
- console.warn(`MetroWidget: ${props.name} get focus while data is empty.`);
1544
- return;
1545
- }
1546
- let focus_id =
1547
- typeof enterFocusId !== "undefined" &&
1548
- enterFocusId >= 0 &&
1549
- enterFocusId < templateParser.GetTemplate().List.length
1550
- ? enterFocusId
1551
- : focusId;
1552
- focus_id = _ifValidEnterRect(enterFocusRect)
1553
- ? _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect)
1554
- : focus_id;
1555
-
1556
- preEdgeRect = enterFocusRect;
1557
- focusId = focus_id;
1558
- enterFocusId = -1;
1559
- enterFocusRect = null;
1560
- _updateFocusItem();
1561
- onItemFocus(templateParser.IdToIndex(focusId), preEdgeRect);
1562
- props.onFocus?.();
1563
- };
1564
-
1565
- const _onBlur = () => {
1566
- isFocus = false;
1567
- enterFocusId = -1;
1568
- enterFocusRect = null;
1569
- preEdgeRect = null;
1570
- if (innerData.length === 0) {
1571
- return;
1572
- }
1573
- preFocusId = focusId;
1574
- _updateBlurItem();
1575
- innerData[templateParser.IdToIndex(preFocusId)].callbacks.onBlur();
1576
-
1577
- props.onBlur?.();
1578
- };
1579
-
1580
- const _onSlideEnd = (event) => {
1581
- if (event && event.stopPropagation) {
1582
- event.stopPropagation();
1583
- }
1584
- pageUpdater.apply();
1585
- };
1586
-
1587
- const _updateFocusItem = () => {
1588
- _setZIndex(templateParser.IdToIndex(focusId), innerData.length, true);
1589
- };
1590
-
1591
- const _updateBlurItem = () => {
1592
- _setZIndex(templateParser.IdToIndex(preFocusId), 0, false);
1593
- };
1594
-
1595
- const _updateFocusByDragInfo = (viewX, viewY) => {
1596
- let enterFocusRect = null;
1597
- //模拟最小区域作为输入区域
1598
- if (props.direction === VERTICAL) {
1599
- enterFocusRect = {
1600
- direction: EdgeDirection.top,
1601
- rect: {
1602
- x: props.left - viewX,
1603
- y: props.top - viewY,
1604
- width: 10,
1605
- height: 10,
1606
- },
1607
- };
1608
- } else {
1609
- enterFocusRect = {
1610
- direction: EdgeDirection.left,
1611
- rect: {
1612
- x: props.left - viewX,
1613
- y: props.top - viewY,
1614
- width: 10,
1615
- height: 10,
1616
- },
1617
- };
1618
- }
1619
- focusId = _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect);
1620
- };
1621
-
1622
- const _onDragUpdateItem = (visible_start, visible_end) => {
1623
- templateItemAdder.tryAddItemByPosition(visible_end);
1624
- pageUpdater.update(
1625
- templateParser,
1626
- visible_start,
1627
- visible_end,
1628
- 0,
1629
- false,
1630
- permanentItemList
1631
- );
1632
- pageUpdater.apply();
1633
-
1634
- Forge.sRenderBridge.InstantPerformSwap();
1635
- };
1636
-
1637
- const _getTouchListener = () => {
1638
- if (!props.enableTouch) {
1639
- return null;
1640
- }
1641
- let callback = {
1642
- OnDragStart: (msg) => {
1643
- if (mounted) {
1644
- Promise.resolve().then(() => {
1645
- let cur_visible_start = visibleInfo.start - pageRange * 2;
1646
- let cur_visible_end = visibleInfo.start + pageRange * 3 - 1;
1647
- preUpdateVisibleStart = cur_visible_start;
1648
- _onDragUpdateItem(cur_visible_start, cur_visible_end);
1649
- });
1650
- }
1651
- return true;
1652
- },
1653
- OnMoved: (msg) => {
1654
- if (mounted) {
1655
- Promise.resolve().then(() => {
1656
- if (
1657
- typeof msg.viewY != "undefined" &&
1658
- typeof msg.viewX != "undefined"
1659
- ) {
1660
- if (props.direction === VERTICAL) {
1661
- visibleInfo.start = -msg.viewY;
1662
- } else {
1663
- visibleInfo.start = -msg.viewX;
1664
- }
1665
- if (visibleInfo.start < 0) {
1666
- visibleInfo.start = 0;
1667
- }
1668
- }
1669
- if (
1670
- Math.abs(visibleInfo.start - preUpdateVisibleStart) <= pageRange
1671
- ) {
1672
- let cur_visible_start = visibleInfo.start - pageRange * 2;
1673
- let cur_visible_end = visibleInfo.start + pageRange * 3 - 1;
1674
- preUpdateVisibleStart = cur_visible_start;
1675
- _onDragUpdateItem(cur_visible_start, cur_visible_end);
1676
- }
1677
- });
1678
- }
1679
-
1680
- return true;
1681
- },
1682
- OnDragEnd: (msg) => {
1683
- _updatePosition(msg["viewX"], msg["viewY"], null);
1684
- preUpdateVisibleStart = visibleInfo.start;
1685
- _onDragUpdateItem(
1686
- visibleInfo.startWithPadding,
1687
- visibleInfo.endWithPadding
1688
- );
1689
- _updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
1690
- return true;
1691
- },
1692
- OnFling: (msg) => {
1693
- _updatePosition(msg["viewX"], msg["viewY"], null);
1694
- preUpdateVisibleStart = visibleInfo.start;
1695
- _onDragUpdateItem(
1696
- visibleInfo.startWithPadding,
1697
- visibleInfo.endWithPadding
1698
- );
1699
- _updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
1700
- return true;
1701
- },
1702
- OnRelease: (msg) => {
1703
- return true;
1704
- },
1705
- };
1706
- return callback;
1707
- };
1708
-
1709
- const _updatePage = (range_list) => {
1710
- let list = [];
1711
- for (let range of range_list) {
1712
- list = list.concat(innerData.slice(range.start, range.end + 1));
1713
- }
1714
- renderData.value = list;
1715
- if (props.enableItemRenderBreak) {
1716
- itemRender.value = false;
1717
- nextTick(() => {
1718
- itemRender.value = true;
1719
- });
1720
- }
1721
- };
1722
-
1723
- const _onScroll = () => {
1724
- if (props.onScroll) {
1725
- const lastItem = templateParser.GetItem(-1);
1726
- let totalWidth;
1727
- if (vertical) {
1728
- totalWidth = lastItem.yPos + lastItem.height - 1;
1729
- } else {
1730
- totalWidth = lastItem.xPos + lastItem.width - 1;
1731
- }
1732
- props.onScroll(visibleInfo.start, visibleInfo.range, totalWidth);
1733
- }
1734
- };
1735
-
1736
- //之前rootview相关的代码
1737
- const _updatePosition = (x, y, anim_info) => {
1738
- if (slideLock) return;
1739
- if (toRaw(slideDiv.value)) {
1740
- let pre_left = slideDivLeft.value,
1741
- pre_top = slideDivTop.value;
1742
- //jsvMaskView的位置更新时会被设置位0,因此不能通过ResetLayoutParams设置位置
1743
- slideDivLeft.value = x;
1744
- slideDivTop.value = y;
1745
- if (anim_info) {
1746
- let delta_x = Math.abs(pre_left - x);
1747
- let delta_y = Math.abs(pre_top - y);
1748
- let duration = Math.round(
1749
- delta_x === 0 ? delta_y / anim_info.speed : delta_x / anim_info.speed
1750
- );
1751
- let slide_animation = new Forge.TranslateAnimation(
1752
- pre_left - x,
1753
- 0,
1754
- pre_top - y,
1755
- 0,
1756
- duration,
1757
- anim_info.easing
1758
- );
1759
- slide_animation.SetAnimationListener(
1760
- new Forge.AnimationListener(anim_info.onstart, anim_info.onend, null)
1761
- );
1762
- toRaw(slideDiv.value)
1763
- .jsvGetProxyView(true)
1764
- .StartAnimation(slide_animation);
1765
- }
1766
- _onScroll();
1767
- }
1768
- };
1769
-
1770
- const _initRootTouch = () => {
1771
- if (props.enableTouch && toRaw(slideDiv.value)) {
1772
- let view = toRaw(slideDiv.value).jsvGetProxyView(true);
1773
- var drag_setting = new Forge.DragSetting(
1774
- dragDirection,
1775
- 20,
1776
- false,
1777
- slidePile,
1778
- props.flingPageWidth,
1779
- props.flingPageEdge
1780
- );
1781
- view.EnableDrag(drag_setting, touchListener, "translateMat(dx,dy,0)");
1782
- }
1783
- };
1784
-
1785
- const _initItemViewTouch = (itemDivRef, index) => {
1786
- if (props.enableTouch) {
1787
- if (itemDivRef) {
1788
- // 为view添加触控处理
1789
- let view = itemDivRef.jsvGetProxyView(true);
1790
- let dragSetting = new Forge.DragSetting(
1791
- Forge.DragSetting.DIRECTION_DISABLE,
1792
- 20,
1793
- false,
1794
- new Forge.RectArea(0, 0, 0, 0),
1795
- -1,
1796
- 3 / 4
1797
- );
1798
- let callback = {
1799
- OnTap: (msg) => {
1800
- return onItemClick(index);
1801
- },
1802
- };
1803
- view.EnableDrag(dragSetting, callback, "translateMat(dx,dy,0)");
1804
- }
1805
- }
1806
- };
1807
-
1808
- //init
1809
- pageUpdater = new PageUpdater(_updatePage);
1810
- if (props.dispatcher) {
1811
- props.dispatcher.registerComponent(exportObject);
1812
- }
1813
- innerPadding = _getPadding(props.padding);
1814
- dragDirection = vertical
1815
- ? Forge.DragSetting.DIRECTION_VERTICAL
1816
- : Forge.DragSetting.DIRECTION_HORIZONTAL;
1817
- visibleInfo.range = vertical
1818
- ? props.height - innerPadding.top - innerPadding.bottom
1819
- : props.width - innerPadding.left - innerPadding.right;
1820
- visibleInfo.padding = vertical
1821
- ? { start: innerPadding.top, end: innerPadding.bottom }
1822
- : { start: innerPadding.left, end: innerPadding.right };
1823
-
1824
- if (props.provideData) {
1825
- dataList = toRaw(props.provideData());
1826
- } else if (props.data) {
1827
- dataList = toRaw(props.data);
1828
- }
1829
-
1830
- templateParser = _getTemplateParser(
1831
- props.width,
1832
- props.height,
1833
- props.direction,
1834
- props.padding,
1835
- props.supportHistoryPath,
1836
- props.layoutType
1837
- );
1838
-
1839
- templateItemAdder = new TemplateItemAdder(
1840
- templateParser,
1841
- dataList,
1842
- props.measures,
1843
- pageRange,
1844
- _onTemplateAdd,
1845
- props.name
347
+ const renderBreakKey = props.enableItemRenderBreak ? RENDER_ITEM_BREAK_KEY : "";
348
+ const touchContainerW = ref(0);
349
+ const touchContainerH = ref(0);
350
+ const itemRender = ref(!props.enableItemRenderBreak);
351
+ const locateDiv = shallowRef(null);
352
+ const renderData = shallowRef([]);
353
+ const slideDiv = shallowRef(null);
354
+ const slideDivLeft = ref(0);
355
+ const slideDivTop = ref(0);
356
+ const itemResizeSlideDiv = shallowRef(null);
357
+ const itemResizeSlideLeft = ref(0);
358
+ const itemResizeSlideTop = ref(0);
359
+ const focusNode = shallowRef(null);
360
+ const pageUpdateToken = ref(0);
361
+
362
+ const {
363
+ widgetRectInfo,
364
+ focusBlockOnFocus,
365
+ focusBlockOnBlur,
366
+ focusBlockOnKeyDown,
367
+ focusBlockOnCustomerEvent,
368
+ _onFocusableItemEdge,
369
+ exportObject,
370
+ } = setup(
371
+ props,
372
+ touchContainerW,
373
+ touchContainerH,
374
+ itemRender,
375
+ locateDiv,
376
+ renderData,
377
+ slideDiv,
378
+ slideDivLeft,
379
+ slideDivTop,
380
+ itemResizeSlideDiv,
381
+ itemResizeSlideLeft,
382
+ itemResizeSlideTop,
383
+ focusNode,
384
+ pageUpdateToken,
385
+ "common"
1846
386
  );
1847
- if (props.onScroll) {
1848
- templateItemAdder.tryAddItemByIndex(dataList.length - 1);
1849
- } else {
1850
- templateItemAdder.tryAddItem(null, 2);
1851
- }
1852
-
1853
- let template_list = templateParser.GetTemplate().List;
1854
-
1855
- //触控相关
1856
- let last_item = template_list[template_list.length - 1];
1857
- if (last_item) {
1858
- touchListener = _getTouchListener();
1859
- touchContainerW.value =
1860
- props.direction === VERTICAL
1861
- ? props.width
1862
- : last_item.xPos + last_item.width;
1863
- touchContainerH.value =
1864
- props.direction === VERTICAL
1865
- ? last_item.yPos + last_item.height
1866
- : props.height;
1867
- }
1868
- slidePile = new Forge.RectArea(
1869
- 0,
1870
- 0,
1871
- props.width - innerPadding.left - innerPadding.right,
1872
- props.height - innerPadding.top - innerPadding.bottom
1873
- );
1874
- let init_focus_id = 0;
1875
- let cur_visible_start = 0;
1876
-
1877
- if (typeof props.initFocusId == "number") {
1878
- templateItemAdder.tryAddItemById(props.initFocusId);
1879
- const item = templateParser.GetItemById(props.initFocusId);
1880
- if (item) {
1881
- init_focus_id = props.initFocusId;
1882
- if (item.doSlide) {
1883
- cur_visible_start = _calculateVisibleStart(item, 1);
1884
- }
1885
- }
1886
- }
1887
- focusId = init_focus_id;
1888
- visibleInfo.start = cur_visible_start;
1889
-
1890
- pageUpdater.update(
1891
- templateParser,
1892
- visibleInfo.startWithPadding,
1893
- visibleInfo.endWithPadding,
1894
- 0,
1895
- false,
1896
- permanentItemList
1897
- );
1898
- let list = [];
1899
- for (let range of pageUpdater.rangeList) {
1900
- list = list.concat(innerData.slice(range.start, range.end + 1));
1901
- }
1902
- renderData.value = list;
1903
-
1904
- onMounted(() => {
1905
- mounted = true;
1906
- _initRootTouch();
1907
- for (let item of renderData.value) {
1908
- _initItemViewTouch(toRaw(item.itemDivRef), item.index);
1909
- }
1910
-
1911
- if (visibleInfo.start) {
1912
- _slideTo(visibleInfo.start, null);
1913
- }
1914
-
1915
- onItemFocus(templateParser.IdToIndex(focusId), preEdgeRect);
1916
-
1917
- if (props.enableItemRenderBreak) {
1918
- nextTick(() => {
1919
- itemRender.value = true;
1920
- });
1921
- }
1922
- });
1923
-
1924
- onUpdated(() => {
1925
- for (let item of renderData.value) {
1926
- if (!item.touchInited) {
1927
- _initItemViewTouch(toRaw(item.itemDivRef), item.index);
1928
- }
1929
- }
1930
- });
1931
-
1932
- onBeforeUnmount(() => {
1933
- mounted = false;
1934
- if (props.dispatcher) {
1935
- props.dispatcher.unregisterComponent();
1936
- }
1937
- });
1938
387
 
1939
388
  defineExpose(exportObject);
1940
389
  </script>
@@ -1949,8 +398,14 @@ defineExpose(exportObject);
1949
398
  overflow: disableClip ? null : 'hidden',
1950
399
  }"
1951
400
  >
1952
- <div :style="{ left: innerPadding.left, top: innerPadding.top }">
401
+ <div
402
+ :style="{
403
+ left: widgetRectInfo.padding.left,
404
+ top: widgetRectInfo.padding.top,
405
+ }"
406
+ >
1953
407
  <div
408
+ id="slideDiv"
1954
409
  key="touchcontainer"
1955
410
  ref="slideDiv"
1956
411
  :style="{
@@ -1968,58 +423,62 @@ defineExpose(exportObject);
1968
423
  ref="focusNode"
1969
424
  :name="name"
1970
425
  :onAction="{
1971
- onFocus: _onFocus,
1972
- onBlur: _onBlur,
1973
- onKeyDown: onKeyDown,
1974
- onCustomerEvent: _onCustomerEvent,
426
+ onFocus: focusBlockOnFocus,
427
+ onBlur: focusBlockOnBlur,
428
+ onKeyDown: focusBlockOnKeyDown,
429
+ onCustomerEvent: focusBlockOnCustomerEvent,
1975
430
  }"
1976
431
  >
1977
432
  <div
1978
- v-for="item in renderData"
1979
- :key="pageUpdateToken + '_' + item.index"
1980
- :ref="item.refCallback"
433
+ id="itemResizeSlide"
434
+ key="itemResizeSlide"
435
+ ref="itemResizeSlideDiv"
1981
436
  :style="{
1982
- left: item.data.xPos,
1983
- top: item.data.yPos,
1984
- width: item.data.width,
1985
- height: item.data.height,
1986
- zIndex: item.controller.zIndex,
437
+ left: itemResizeSlideLeft,
438
+ top: itemResizeSlideTop,
1987
439
  }"
1988
440
  >
1989
441
  <div
1990
- v-if="
1991
- !enableItemRenderBreak || item.slotMounted.value || itemRender
1992
- "
1993
- :key="renderBreakKey"
1994
- :ref="item.slotDivRef"
442
+ v-for="item in renderData"
443
+ :key="pageUpdateToken + '_' + item.index"
444
+ :ref="item.divRef"
445
+ :style="{
446
+ ...item.renderStyle,
447
+ }"
1995
448
  >
1996
- <slot
1997
- name="renderItem"
449
+ <div
450
+ v-if="!enableItemRenderBreak || item.mounted || itemRender"
1998
451
  :key="renderBreakKey"
1999
- :data="item.data.data"
2000
- :onEdge="_onFocusableItemEdge"
2001
- :onAction="item.register"
2002
- :query="item.query"
2003
- :onItemEdge="_onFocusableItemEdge"
2004
- ></slot>
452
+ :ref="item.slotRef"
453
+ >
454
+ <slot
455
+ name="renderItem"
456
+ :key="renderBreakKey"
457
+ :data="item.customerData"
458
+ :onEdge="_onFocusableItemEdge"
459
+ :onAction="item.registerObj"
460
+ :query="item.query"
461
+ :onItemEdge="_onFocusableItemEdge"
462
+ ></slot>
463
+ </div>
464
+ <div
465
+ v-if="
466
+ enableItemRenderBreak &&
467
+ placeHolderSetting &&
468
+ !item.mounted.value
469
+ "
470
+ :style="{
471
+ width:
472
+ item.renderStyle.width -
473
+ (placeHolderSetting.gap ? placeHolderSetting.gap : 0),
474
+ height:
475
+ item.renderStyle.height -
476
+ (placeHolderSetting.gap ? placeHolderSetting.gap : 0),
477
+ backgroundColor: placeHolderSetting.backgroundColor,
478
+ borderRadius: placeHolderSetting.borderRadius,
479
+ }"
480
+ ></div>
2005
481
  </div>
2006
- <div
2007
- v-if="
2008
- enableItemRenderBreak &&
2009
- placeHolderSetting &&
2010
- !item.slotMounted.value
2011
- "
2012
- :style="{
2013
- width:
2014
- item.data.width -
2015
- (placeHolderSetting.gap ? placeHolderSetting.gap : 0),
2016
- height:
2017
- item.data.height -
2018
- (placeHolderSetting.gap ? placeHolderSetting.gap : 0),
2019
- backgroundColor: placeHolderSetting.backgroundColor,
2020
- borderRadius: placeHolderSetting.borderRadius,
2021
- }"
2022
- ></div>
2023
482
  </div>
2024
483
  </jsv-focus-block>
2025
484
  </div>