@shijiu/jsview-vue-samples 2.3.151-test.0 → 3.0.0-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 (228) hide show
  1. package/ABImageAlt/App.vue +114 -0
  2. package/ABImageAlt/Item.vue +133 -0
  3. package/{MetroWidgetDemos/SkeletonDiagram/assets/imageList.json → ABImageAlt/assets/imageList.js} +9 -1
  4. package/ABImageAlt/data.js +17 -0
  5. package/AI_Check_Rules.txt +5 -0
  6. package/AnimPicture/App.vue +20 -10
  7. package/ApicSwitch/App.vue +90 -0
  8. package/ApicSwitch/TabItem.vue +65 -0
  9. package/ApicSwitch/WebpShow.vue +24 -0
  10. package/ApicSwitch/data.js +50 -0
  11. package/Basic/AI_skills_update.md +1 -0
  12. package/Basic/components/div/ColorFormatTest.vue +93 -0
  13. package/Basic/components/div/DivRadius.vue +97 -15
  14. package/Basic/components/div/DivTag3Group.vue +30 -0
  15. package/Basic/components/img/ImageType.vue +65 -0
  16. package/Basic/components/panel/Panel2.vue +13 -1
  17. package/Basic/components/text/TextAlign.vue +7 -1
  18. package/BlobLoadTest/App.vue +201 -0
  19. package/BreakLinesApi/App.vue +82 -0
  20. package/CanvasDrawChart/App.vue +11 -0
  21. package/CanvasDrawChart/Graph1.vue +104 -0
  22. package/CanvasDrawChart/Graph2.vue +115 -0
  23. package/CssPreprocessor/Scss/PanelData.js +1 -1
  24. package/CssPreprocessor/Scss/components/scss-group4/ScssMaps.vue +4 -3
  25. package/CssPreprocessor/Scss/components/scss-group5/ScssImporting.vue +2 -2
  26. package/DemoForOperator/Bounce/FreeMoveBuilder.js +1 -1
  27. package/DemoForOperator/Firework1/App.vue +12 -1
  28. package/DemoForOperator/Firework1/Fireworks.vue +18 -0
  29. package/DemoForOperator/FlipPage/FlipPage/FlipPage.vue +1 -0
  30. package/DemoForOperator/Focus/Alpha/Item.vue +1 -0
  31. package/DemoForOperator/Focus/Light/Item.vue +1 -0
  32. package/DemoForOperator/Focus/Normal/Item.vue +1 -0
  33. package/DemoForOperator/FrameShadow/FrameShadow.vue +1 -1
  34. package/DemoForOperator/Genie/App.vue +20 -6
  35. package/DemoForOperator/Genie/App2.vue +61 -0
  36. package/DemoForOperator/Genie/geniePakcer/GenieImage.vue +298 -0
  37. package/DemoForOperator/Genie/geniePakcer/GenieSlot.vue +292 -0
  38. package/DemoForOperator/Genie/geniePakcer/GenieTools.ts +463 -0
  39. package/DemoForOperator/Jigsaw/JigsawFull.vue +12 -7
  40. package/DemoForOperator/Jigsaw/JigsawSingle.vue +13 -7
  41. package/DemoForOperator/LongChatBox/App.vue +13 -13
  42. package/DemoForOperator/LongChatBox/Bubble.vue +78 -66
  43. package/DemoForOperator/LongChatBox/LongChat.vue +68 -36
  44. package/DemoForOperator/LongChatBox/testData.js +7 -44
  45. package/DemoForOperator/Sound/Bounce/FreeMoveBuilder.js +1 -1
  46. package/DemoForOperator/routeList.js +8 -2
  47. package/DemoHomepage/App.vue +74 -1
  48. package/DemoHomepage/components/BodyFrame.vue +1 -0
  49. package/DemoHomepage/components/TabFrame.vue +1 -1
  50. package/DemoHomepage/router.js +723 -160
  51. package/DemoHomepage/views/Homepage.vue +60 -2
  52. package/DemoHomepage/watchTest.vue +50 -0
  53. package/FilterDemo/AnimatePic.vue +63 -17
  54. package/FilterDemo/App.vue +3 -3
  55. package/FlexCellDemo/AI_skills_update.md +4 -0
  56. package/FlexCellDemo/TestFrame1.vue +12 -2
  57. package/FlexCellDemo/TestFrame2.vue +10 -1
  58. package/FlexCellDemo/TestFrame3.vue +114 -59
  59. package/FpsLimit/App.vue +102 -0
  60. package/FreeMoveChildAttract/App.vue +18 -8
  61. package/FreeMoveLink/App.vue +49 -20
  62. package/Hover/App.vue +144 -0
  63. package/HttpRequestSSE/SSEReader.js +200 -0
  64. package/ImpactStop/App.vue +2 -2
  65. package/Input/FullKeyboard.vue +3 -3
  66. package/Input/InputPanel.vue +63 -3
  67. package/JsvLine/App.vue +53 -38
  68. package/LatexDemo/App.vue +3 -1
  69. package/LatexFormula/App.vue +196 -0
  70. package/LongImage/App.vue +1 -1
  71. package/LongImage/LongImageScroll.vue +100 -47
  72. package/LongImage/Scroll.vue +28 -9
  73. package/LongText/LongTextScroll.vue +1 -0
  74. package/Markdown/App.vue +36 -0
  75. package/Markdown/Bubble.vue +109 -0
  76. package/Markdown/LongChat.vue +206 -0
  77. package/Markdown/Markdown/Markdown.vue +156 -0
  78. package/Markdown/Markdown/index.ts +1 -0
  79. package/Markdown/Markdown/marked/LICENSE.md +45 -0
  80. package/Markdown/Markdown/marked/index.ts +2 -0
  81. package/Markdown/Markdown/marked/marked.d.ts +756 -0
  82. package/Markdown/Markdown/marked/marked.js +71 -0
  83. package/Markdown/Markdown/parser.ts +1365 -0
  84. package/Markdown/data.js +581 -0
  85. package/MetroWidgetDemos/AI_skills_update.md +2 -0
  86. package/MetroWidgetDemos/ListExpand/ChildItem.vue +130 -0
  87. package/MetroWidgetDemos/ListExpand/ExpandItem.vue +375 -0
  88. package/MetroWidgetDemos/ListExpand/ExpandItem1.vue +403 -0
  89. package/MetroWidgetDemos/ListExpand/assets/arrow-down.png +0 -0
  90. package/MetroWidgetDemos/ListExpand/assets/up-arrow.png +0 -0
  91. package/MetroWidgetDemos/ListExpand/components/WidgetListHandler.vue +150 -0
  92. package/MetroWidgetDemos/ListExpand/index.vue +88 -0
  93. package/MetroWidgetDemos/ListExpand/list.js +2421 -0
  94. package/MetroWidgetDemos/RefreshDemo/App.vue +14 -1
  95. package/MetroWidgetDemos/RenderAccelerate/App.vue +142 -0
  96. package/MetroWidgetDemos/RenderAccelerate/AppPage.vue +78 -0
  97. package/MetroWidgetDemos/RenderAccelerate/AppTab.vue +62 -0
  98. package/MetroWidgetDemos/RenderAccelerate/ContentItem.vue +409 -0
  99. package/MetroWidgetDemos/RenderAccelerate/Item.vue +67 -0
  100. package/MetroWidgetDemos/RenderAccelerate/TabItem.vue +100 -0
  101. package/MetroWidgetDemos/RenderAccelerate/ViewSwiper.vue +215 -0
  102. package/MetroWidgetDemos/RenderAccelerate/WidgetItem.vue +107 -0
  103. package/MetroWidgetDemos/SkeletonDiagram/App.vue +35 -8
  104. package/MetroWidgetDemos/SkeletonDiagram/Item.vue +11 -2
  105. package/MetroWidgetDemos/SkeletonDiagram/assets/imageList.js +245 -0
  106. package/MetroWidgetDemos/SkeletonDiagram/data.js +3 -3
  107. package/MetroWidgetDemos/SpatialNav/App.vue +177 -0
  108. package/MetroWidgetDemos/SpatialNav/Buttons.vue +83 -0
  109. package/MetroWidgetDemos/SpatialNav/CustomFocus.vue +57 -0
  110. package/MetroWidgetDemos/{TripleWidget → SpatialNav}/Item.vue +1 -8
  111. package/MetroWidgetDemos/{TripleWidget/WidgetItem.vue → SpatialNav/SimpleFloor.vue} +14 -45
  112. package/MetroWidgetDemos/SpatialNav/StepMw.vue +113 -0
  113. package/MetroWidgetDemos/SpatialNav/TabContent/TabContent.vue +185 -0
  114. package/MetroWidgetDemos/SpatialNav/TripleSection/TripleSection.vue +69 -0
  115. package/MetroWidgetDemos/SpatialNav/TripleSection/WidgetItem.vue +100 -0
  116. package/MetroWidgetDemos/SpatialNav/TvSection/List.vue +75 -0
  117. package/MetroWidgetDemos/SpatialNav/TvSection/TvSection.vue +91 -0
  118. package/MetroWidgetDemos/basic2/App.vue +407 -0
  119. package/MetroWidgetDemos/basic2/Item.vue +68 -0
  120. package/MetroWidgetDemos/direction/App.vue +22 -0
  121. package/MetroWidgetDemos/gazeFocusDiff/App.vue +126 -0
  122. package/MetroWidgetDemos/gazeFocusDiff/Item.vue +87 -0
  123. package/MetroWidgetDemos/minimalUsage/App.vue +66 -0
  124. package/MetroWidgetDemos/minimalUsage/Item.vue +54 -0
  125. package/MetroWidgetDemos/ninePatchFocusPage/App.vue +22 -7
  126. package/MetroWidgetDemos/ninePatchFocusPage/Item.vue +7 -5
  127. package/MetroWidgetDemos/ninePatchFocusPage/focusConstants.js +2 -0
  128. package/MetroWidgetDemos/routeList.js +203 -12
  129. package/MetroWidgetDemos/slideSetting/App.vue +288 -99
  130. package/MetroWidgetDemos/zIndex/App.vue +117 -0
  131. package/MetroWidgetDemos/zIndex/Item.vue +61 -0
  132. package/NinePatchTester/App.vue +24 -31
  133. package/PreDecode/App.vue +140 -0
  134. package/ReactiveTest/App.vue +115 -0
  135. package/ReactiveTest/Item.vue +92 -0
  136. package/ReactiveTest/assets/imageList.js +245 -0
  137. package/ReactiveTest/component/TestSmartDiv.vue +50 -0
  138. package/ReactiveTest/component/TestSmartDivSrcList.vue +74 -0
  139. package/ReactiveTest/component/TestSmartImage.vue +46 -0
  140. package/ReactiveTest/component/TestSmartImageSrcList.vue +90 -0
  141. package/ReactiveTest/component/TestSmartImageStyle.vue +41 -0
  142. package/ReactiveTest/data.js +49 -0
  143. package/ScreenToBlob/App.vue +250 -0
  144. package/SecTorTest/App.vue +9 -3
  145. package/SpringFestival/SpringFestivalScene/FreeMoveBuilder.js +3 -3
  146. package/SyncDecode/App.vue +137 -0
  147. package/TextSizeLimit/App.vue +211 -0
  148. package/TransitPage/App.vue +2 -0
  149. package/assets/logo.png +0 -0
  150. package/package.json +5 -5
  151. package/DemoForOperator/Genie/geniePakcer/Genie.vue +0 -741
  152. package/DemoForOperator/LongChatBox/TextManager.ts +0 -147
  153. package/DemoForOperator/LongChatBox/VirtualList.vue +0 -298
  154. package/DemoForOperator/LongChatBox/utile.js +0 -331
  155. package/DivMetroPerformance/App.vue +0 -157
  156. package/DivMetroPerformance/Item.vue +0 -58
  157. package/DivMetroPerformance/assets/bg.jpg +0 -0
  158. package/DivMetroPerformance/assets/coupon_content.png +0 -0
  159. package/DivMetroPerformance/assets/coupon_left.png +0 -0
  160. package/DivMetroPerformance/assets/coupon_mid.png +0 -0
  161. package/DivMetroPerformance/assets/coupon_right.png +0 -0
  162. package/DivMetroPerformance/assets/focus_border.png +0 -0
  163. package/DivMetroPerformance/assets/holder_logo.png +0 -0
  164. package/DivMetroPerformance/assets/jrbm.png +0 -0
  165. package/DivMetroPerformance/assets/line_left.png +0 -0
  166. package/DivMetroPerformance/assets/line_mid.png +0 -0
  167. package/DivMetroPerformance/assets/line_right.png +0 -0
  168. package/DivMetroPerformance/assets/loading.png +0 -0
  169. package/DivMetroPerformance/assets/logo.png +0 -0
  170. package/DivMetroPerformance/assets/mcjx.png +0 -0
  171. package/DivMetroPerformance/assets/tao.png +0 -0
  172. package/DivMetroPerformance/assets/tmall.png +0 -0
  173. package/DivMetroPerformance/border.png +0 -0
  174. package/DivMetroPerformance/components/ContentItem.vue +0 -384
  175. package/DivMetroPerformance/components/MyTab.vue +0 -129
  176. package/DivMetroPerformance/data.js +0 -124
  177. package/DivMetroPerformance/utils/GridItem.vue +0 -28
  178. package/DivMetroPerformance/utils/GridPlate.vue +0 -85
  179. package/MediaDemo/App.vue +0 -127
  180. package/MediaDemo/assets/audio-poster.png +0 -0
  181. package/MediaDemo/components/Button.vue +0 -69
  182. package/MediaDemo/components/Controllor.vue +0 -286
  183. package/MediaDemo/components/StatusBar.vue +0 -100
  184. package/MediaDemo/components/frames/AudioFrame.vue +0 -39
  185. package/MediaDemo/components/frames/AudioPoster.vue +0 -48
  186. package/MediaDemo/components/frames/MediaFrame.vue +0 -153
  187. package/MediaDemo/components/frames/VideoFrame.vue +0 -39
  188. package/MetroWidgetDemos/TripleWidget/App.vue +0 -87
  189. package/MetroWidgetDemos/TripleWidget/SWidgetItem.vue +0 -99
  190. package/Parkour/App.vue +0 -13
  191. package/Parkour/Common/Context.js +0 -21
  192. package/Parkour/Common/MatchmanInfo.js +0 -62
  193. package/Parkour/Common/Random.js +0 -61
  194. package/Parkour/Common/Sound.js +0 -50
  195. package/Parkour/appConfig/HOW_TO_CONFIG.md +0 -20
  196. package/Parkour/appConfig/app.config.mjs +0 -5
  197. package/Parkour/appConfig/app_sign_private_key_sample.crt +0 -28
  198. package/Parkour/appConfig/app_sign_public_key_sample.pem +0 -9
  199. package/Parkour/appConfig/jsview.config.mjs +0 -39
  200. package/Parkour/assets/Bgimages/bg1.png +0 -0
  201. package/Parkour/assets/Bgimages/bg2.png +0 -0
  202. package/Parkour/assets/Bgimages/bg3.png +0 -0
  203. package/Parkour/assets/Bgimages/bg4.png +0 -0
  204. package/Parkour/assets/Bgimages/bg5.png +0 -0
  205. package/Parkour/assets/audio/jump.mp3 +0 -0
  206. package/Parkour/assets/audio/lose.mp3 +0 -0
  207. package/Parkour/assets/role_skin1/fail.json +0 -44
  208. package/Parkour/assets/role_skin1/fail.png +0 -0
  209. package/Parkour/assets/role_skin1/jump_down.json +0 -20
  210. package/Parkour/assets/role_skin1/jump_down.png +0 -0
  211. package/Parkour/assets/role_skin1/jump_up.json +0 -44
  212. package/Parkour/assets/role_skin1/jump_up.png +0 -0
  213. package/Parkour/assets/role_skin1/roll.json +0 -44
  214. package/Parkour/assets/role_skin1/roll.png +0 -0
  215. package/Parkour/assets/role_skin1/run.json +0 -52
  216. package/Parkour/assets/role_skin1/run.png +0 -0
  217. package/Parkour/components/Backdrop.vue +0 -61
  218. package/Parkour/components/GameSence.vue +0 -602
  219. package/Parkour/components/Matchman.vue +0 -85
  220. package/ThrowMoveDemo/AccelerateDemo.vue +0 -85
  221. package/ThrowMoveDemo/App.vue +0 -104
  222. package/ThrowMoveDemo/LRParabolicDemo.vue +0 -101
  223. package/ThrowMoveDemo/TargetDemo.vue +0 -87
  224. package/ThrowMoveDemo/UDParabolicDemo.vue +0 -92
  225. /package/{AnimPicture/assets → assets}/animated_webp.webp +0 -0
  226. /package/{AnimPicture/assets → assets}/ball_3.webp +0 -0
  227. /package/{AnimPicture/assets → assets}/girl_run.gif +0 -0
  228. /package/{AnimPicture/assets → assets}/quan.webp +0 -0
@@ -0,0 +1,87 @@
1
+ <script setup>
2
+ import { computed, ref } from "vue";
3
+
4
+ const props = defineProps({
5
+ data: {
6
+ type: Object,
7
+ required: true,
8
+ },
9
+ onAction: {
10
+ type: Object,
11
+ required: true,
12
+ },
13
+ widgetTag: {
14
+ type: String,
15
+ default: "",
16
+ },
17
+ });
18
+
19
+ const gazed = ref(false);
20
+ const focused = ref(false);
21
+
22
+ /**
23
+ * 这份样例的可视化策略:
24
+ * - gazed 只受 onGaze/onIgnore 影响(即使 widget 没有获焦也会更新)
25
+ * - focused 只受 onFocus/onBlur 影响(用于验证:当 widget 不作为 focusBlock owner 时是否不触发)
26
+ */
27
+ const modeText = computed(() => {
28
+ if (focused.value && gazed.value) return "FOCUS+GAZE";
29
+ if (focused.value) return "FOCUS";
30
+ if (gazed.value) return "GAZE";
31
+ return "";
32
+ });
33
+
34
+ const onIgnore = () => {
35
+ gazed.value = false;
36
+ };
37
+
38
+ const onGaze = () => {
39
+ gazed.value = true;
40
+ };
41
+
42
+ const onBlur = () => {
43
+ // onBlur:失去 focus-tree 焦点(该回调通常依赖 widget 获焦状态)
44
+ focused.value = false;
45
+ };
46
+
47
+ const onFocus = () => {
48
+ // onFocus:获得 focus-tree 焦点(该回调通常依赖 widget 获焦状态)
49
+ focused.value = true;
50
+ };
51
+
52
+ const onClick = () => {
53
+ // 留一个最小日志,便于排查/对齐回调时序
54
+ // 注意:控制台日志不影响 gaze/focus 可视化
55
+ console.log("gazeFocusDiff onClick:", props.data?.id);
56
+ };
57
+
58
+ // 通过 onAction.register 绑定 item 回调
59
+ props.onAction.register("onGaze", onGaze);
60
+ props.onAction.register("onIgnore", onIgnore);
61
+ props.onAction.register("onFocus", onFocus);
62
+ props.onAction.register("onBlur", onBlur);
63
+ props.onAction.register("onClick", onClick);
64
+ </script>
65
+
66
+ <template>
67
+ <div
68
+ :style="{
69
+ width: data.width,
70
+ height: data.height,
71
+ borderRadius: 10,
72
+ lineHeight: `${data.height}px`,
73
+ fontSize: 26,
74
+ textAlign: 'center',
75
+ color: focused ? '#0C1B30' : '#FFFFFF',
76
+ backgroundColor: focused
77
+ ? '#7DE4FF'
78
+ : gazed
79
+ ? '#35557D'
80
+ : '#1F2A44',
81
+ border: focused ? '0px solid transparent' : gazed ? '2px solid #FFD166' : '0px solid transparent',
82
+ }"
83
+ >
84
+ {{ widgetTag ? ("[" + widgetTag + "] ") : "" }}{{ data.title }}{{ modeText ? (' / ' + modeText) : '' }}
85
+ </div>
86
+ </template>
87
+
@@ -0,0 +1,66 @@
1
+ <!--
2
+ * @file
3
+ *
4
+ * 【界面概述】
5
+ * MetroWidget 最简用法示例:展示一个可上下移动焦点的纵向列表。
6
+ *
7
+ * 【控件介绍(最小必需项)】
8
+ * MetroWidget:
9
+ * props:
10
+ * width {int} (必选) 控件宽度
11
+ * height {int} (必选) 控件高度
12
+ * direction {enum} (必选) 布局方向,这里使用 VERTICAL
13
+ * name {string} 焦点名称,用于 setFocus
14
+ * data {array} 数据列表(与 provideData 二选一)
15
+ * measures {function} (必选) 返回每个 item 的布局信息
16
+ -->
17
+ <script setup>
18
+ import { MetroWidget, VERTICAL, useFocusHub } from "jsview";
19
+ import { onMounted } from "vue";
20
+ import Item from "./Item.vue";
21
+
22
+ const focusHub = useFocusHub();
23
+
24
+ const listData = [
25
+ { id: 0, title: "Item 0", width: 420, height: 80, marginBottom: 16 },
26
+ { id: 1, title: "Item 1", width: 420, height: 80, marginBottom: 16 },
27
+ { id: 2, title: "Item 2", width: 420, height: 80, marginBottom: 16 },
28
+ { id: 3, title: "Item 3", width: 420, height: 80, marginBottom: 16 },
29
+ { id: 4, title: "Item 4", width: 420, height: 80, marginBottom: 16 },
30
+ ];
31
+
32
+ const measures = (item) => ({
33
+ width: item.width,
34
+ height: item.height,
35
+ marginBottom: item.marginBottom,
36
+ });
37
+
38
+ onMounted(() => {
39
+ focusHub.setFocus("minimalMetroWidget");
40
+ });
41
+ </script>
42
+
43
+ <template>
44
+ <div
45
+ :style="{
46
+ width: 1280,
47
+ height: 720,
48
+ backgroundColor: '#0C1B30',
49
+ }"
50
+ />
51
+
52
+ <metro-widget
53
+ name="minimalMetroWidget"
54
+ :left="80"
55
+ :top="80"
56
+ :width="460"
57
+ :height="920"
58
+ :direction="VERTICAL"
59
+ :data="listData"
60
+ :measures="measures"
61
+ >
62
+ <template #renderItem="{ data, onAction }">
63
+ <item :data="data" :onAction="onAction" />
64
+ </template>
65
+ </metro-widget>
66
+ </template>
@@ -0,0 +1,54 @@
1
+ <script setup>
2
+ import { ref } from "vue";
3
+
4
+ const props = defineProps({
5
+ data: {
6
+ type: Object,
7
+ required: true,
8
+ },
9
+ onAction: {
10
+ type: Object,
11
+ required: true,
12
+ },
13
+ });
14
+
15
+ const gazed = ref(false);
16
+
17
+ const onIgnore = () => {
18
+ gazed.value = false;
19
+ };
20
+
21
+ const onGaze = () => {
22
+ gazed.value = true;
23
+ };
24
+
25
+ const onClick = () => {
26
+ console.log("minimalUsage item onClick:", props.data);
27
+ };
28
+
29
+ // item 回调使用说明:
30
+ // 1) onClick:在当前 item 上按确认键时触发,用于执行业务动作(跳转/播放/打开详情等)。
31
+ // 2) onGaze:触发凝视进入时回调(如遥控器停留/凝视交互场景),常用于预览或延迟高亮。
32
+ // 3) onIgnore:凝视离开或凝视被取消时回调,常用于清理 onGaze 启动的状态或定时器。
33
+ // 使用方式:通过 onAction.register(事件名, 回调函数) 进行注册。
34
+ props.onAction.register("onClick", onClick);
35
+ props.onAction.register("onGaze", onGaze);
36
+ props.onAction.register("onIgnore", onIgnore);
37
+ </script>
38
+
39
+ <template>
40
+ <div
41
+ :style="{
42
+ width: data.width,
43
+ height: data.height,
44
+ lineHeight: data.height,
45
+ fontSize: 32,
46
+ textAlign: 'center',
47
+ color: gazed ? '#0C1B30' : '#FFFFFF',
48
+ backgroundColor: gazed ? '#7DE4FF' : '#35557D',
49
+ borderRadius: 10,
50
+ }"
51
+ >
52
+ {{ data.title }}
53
+ </div>
54
+ </template>
@@ -10,10 +10,11 @@ import {
10
10
  useFocusHub,
11
11
  JsvNinePatch,
12
12
  METRO_WIDGET_CONST,
13
+ JsvTextureBuilder,
13
14
  } from "jsview";
14
- import { onMounted, reactive, provide } from "vue";
15
+ import { onMounted, onBeforeUnmount, reactive, provide, shallowRef } from "vue";
15
16
  import PageRow from "./PageRow.vue";
16
- import focusImg from "../../assets/focus1.png";
17
+ import { FOCUS_CORNER_RADIUS } from "./focusConstants";
17
18
 
18
19
  const focusHub = useFocusHub();
19
20
 
@@ -25,6 +26,16 @@ const focusSize = reactive({
25
26
  });
26
27
  provide("focusSize", focusSize);
27
28
 
29
+ // 使用CanvasTexture构建本地焦点框,避免依赖在线或静态图片资源
30
+ const focusTextureUrl = shallowRef("");
31
+ const focusTextureInfo = JsvTextureBuilder.buildCircleNinePatchTexture({
32
+ cornerRadius: FOCUS_CORNER_RADIUS, // +1是为了包裹得更加无缝
33
+ circleLineWidth: 7,
34
+ circleColor: "rgba(176, 140, 255, 0.95)",
35
+ });
36
+ focusTextureUrl.value = `jsvtexturestore://${focusTextureInfo.texAccessName}`;
37
+ const focusTextureSourceId = focusTextureInfo.texAccessName;
38
+
28
39
  const provideData = () => {
29
40
  const data = [];
30
41
  for (let i = 0; i < 10; i++) {
@@ -53,6 +64,10 @@ const measures = (item) => {
53
64
  onMounted(() => {
54
65
  focusHub.setFocus("mwWidget");
55
66
  });
67
+
68
+ onBeforeUnmount(() => {
69
+ JsvTextureStoreApi.deleteTexture(focusTextureSourceId);
70
+ });
56
71
  </script>
57
72
 
58
73
  <template>
@@ -93,11 +108,11 @@ onMounted(() => {
93
108
  top: focusSize.top,
94
109
  left: focusSize.left,
95
110
  }"
96
- :imageUrl="focusImg"
97
- :imageWidth="55"
98
- :centerWidth="1"
99
- :borderOutset="13"
100
- :imageDspWidth="55"
111
+ :imageUrl="focusTextureUrl"
112
+ :imageWidth="focusTextureInfo.ImageWidth"
113
+ :centerWidth="focusTextureInfo.CenterWidth"
114
+ :borderOutset="focusTextureInfo.BorderOutset"
115
+ :imageDspWidth="focusTextureInfo.ImageDspWidth"
101
116
  :animTime="0.2"
102
117
  :waitForInit="true"
103
118
  ></jsv-nine-patch>
@@ -5,6 +5,7 @@
5
5
  -->
6
6
  <script setup>
7
7
  import { ref, shallowRef, inject } from "vue";
8
+ import { FOCUS_CORNER_RADIUS } from "./focusConstants";
8
9
 
9
10
  const props = defineProps({
10
11
  data: Object,
@@ -20,10 +21,11 @@ const onFocus = () => {
20
21
  focused.value = true;
21
22
  divRef.value?.jsvGetBoundingClientRect().then(
22
23
  (data) => {
23
- focusSize.width = data.width;
24
- focusSize.height = data.height;
25
- focusSize.left = data.left;
26
- focusSize.top = data.top;
24
+ // 略微缩小焦点框位置和尺寸信息, 以规避和卡片边缘之间留缝
25
+ focusSize.width = data.width - 4;
26
+ focusSize.height = data.height - 4;
27
+ focusSize.left = data.left + 2;
28
+ focusSize.top = data.top + 2;
27
29
  },
28
30
  (error) => {
29
31
  console.log("get absolute position failed", error);
@@ -60,7 +62,7 @@ props.onAction.register("onClick", onClick);
60
62
  fontSize: 30,
61
63
  color: '#FFFFFF',
62
64
  backgroundColor: data.color,
63
- borderRadius: 10,
65
+ borderRadius: FOCUS_CORNER_RADIUS,
64
66
  }"
65
67
  >
66
68
  {{ data.content }}
@@ -0,0 +1,2 @@
1
+ // 焦点框圆角与卡片圆角统一使用同一常量
2
+ export const FOCUS_CORNER_RADIUS = 10;
@@ -4,54 +4,122 @@
4
4
  * @Description: file content
5
5
  */
6
6
  export default [
7
+ /*
8
+ * 一个MetroWidget所需要的最少的配置
9
+ */
7
10
  {
8
- meta: { nameText: "基础示例", },
9
- name: "metroWidget-基础示例",
10
- path: "/metroWidget/basic",
11
- component: () => import("@shijiu/jsview-vue-samples/MetroWidgetDemos/basic/App.vue"),
11
+ meta: { nameText: "最简用法", },
12
+ name: "metroWidget-最简用法",
13
+ path: "/metroWidget/minimalUsage",
14
+ component: () =>
15
+ import("@shijiu/jsview-vue-samples/MetroWidgetDemos/minimalUsage/App.vue"),
16
+ },
17
+
18
+ /*
19
+ * 不规则排版顺序样例
20
+ *
21
+ * 展示MetroWidget的layoutType = relative 状态下对不规则排版顺序的样例
22
+ */
23
+ {
24
+ meta: { nameText: "不规则排版顺序样例", },
25
+ name: "metroWidget-不规则排版顺序样例",
26
+ path: "/metroWidget/basic2",
27
+ component: () => import("@shijiu/jsview-vue-samples/MetroWidgetDemos/basic2/App.vue"),
12
28
  },
29
+
30
+ /*
31
+ * 测试MetroWidget的direction属性
32
+ *
33
+ * 关联场景:
34
+ * 所有MetroWidget都会考虑direction, 不设则为默认值
35
+ */
13
36
  {
14
37
  meta: { nameText: "direction", },
15
38
  name: "metroWidget-direction",
16
39
  path: "/metroWidget/direction",
17
40
  component: () => import("@shijiu/jsview-vue-samples/MetroWidgetDemos/direction/App.vue"),
18
41
  },
42
+
43
+ /*
44
+ * 测试MetroWidget的padding属性
45
+ *
46
+ * 关联场景:
47
+ * 为了解决当焦点元素放大时, 会超过MetroWidget的边界, 可能导致焦点元素被Clip掉的问题场景
48
+ */
19
49
  {
20
50
  meta: { nameText: "padding", },
21
51
  name: "metroWidget-padding",
22
52
  path: "/metroWidget/padding",
23
53
  component: () => import("@shijiu/jsview-vue-samples/MetroWidgetDemos/padding/App.vue"),
24
54
  },
55
+
56
+ /*
57
+ * 滚动策略
58
+ *
59
+ * 用MetroWiget搭建的各类界面的滚动策略的验证, 展示了
60
+ * 1. 无缝滚动, 全默认值, 默认在靠边缘左右两端开始触发滚动
61
+ * 2. 整页滚动
62
+ * 3. 无缝滚动,焦点尽量为居中的场景
63
+ * 4. 第一屏不滚动的无缝滚动
64
+ * 5. 无缝左右滚动, 且移动时,不用保障数据的最边缘和可视区域边缘对接
65
+ *
66
+ */
25
67
  {
26
68
  meta: { nameText: "slideSetting", },
27
69
  name: "metroWidget-slideSetting",
28
70
  path: "/metroWidget/slideSetting",
29
71
  component: () => import("@shijiu/jsview-vue-samples/MetroWidgetDemos/slideSetting/App.vue"),
30
72
  },
73
+
74
+ /*
75
+ * 仅测试, AI编程时, 不要参考
76
+ * 测试layoutType = absolute 和 layoutType = relative 的样例
77
+ *
78
+ */
31
79
  {
32
80
  meta: { nameText: "layoutType", },
33
81
  name: "metroWidget-layoutType",
34
82
  path: "/metroWidget/layoutType",
35
83
  component: () => import("@shijiu/jsview-vue-samples/MetroWidgetDemos/layoutType/App.vue"),
36
84
  },
85
+
86
+ /*
87
+ * 仅测试, AI编程时, 不要参考, 为已经废弃的写法
88
+ * 测试老版本MetroWidget的嵌套用法(mw+focusblock)的兼容性
89
+ *
90
+ */
37
91
  {
38
92
  meta: { nameText: "嵌套(基础)", },
39
93
  name: "metroWidget-嵌套(基础)",
40
94
  path: "/metroWidget/focusableItemBasic",
41
95
  component: () => import("@shijiu/jsview-vue-samples/MetroWidgetDemos/focusableItemBasic/App.vue"),
42
96
  },
97
+
98
+ /*
99
+ * 仅测试, AI编程时, 不要参考, 为已经废弃的写法
100
+ * 测试老版本MetroWidget的嵌套用法(mw+focusblock)的兼容性, 另一种写法
101
+ *
102
+ */
43
103
  {
44
104
  meta: { nameText: "嵌套(混合)", },
45
105
  name: "metroWidget-嵌套(混合)",
46
106
  path: "/metroWidget/focusableItemMix",
47
107
  component: () => import("@shijiu/jsview-vue-samples/MetroWidgetDemos/focusableItemMix/App.vue"),
48
108
  },
109
+
110
+ /*
111
+ * 仅测试, AI编程时, 不要参考, 为已经废弃的写法
112
+ * 测试老版本MetroWidget的嵌套用法(mw+mw)的兼容性
113
+ *
114
+ */
49
115
  {
50
116
  meta: { nameText: "嵌套(MetroWidget)", },
51
117
  name: "metroWidget-嵌套(MetroWidget)",
52
118
  path: "/metroWidget/focusableItemMetroWidget",
53
119
  component: () => import("@shijiu/jsview-vue-samples/MetroWidgetDemos/focusableItemMetroWidget/App.vue"),
54
120
  },
121
+
122
+
55
123
  {
56
124
  meta: { nameText: "乒乓模式", },
57
125
  name: "metroWidget-乒乓模式",
@@ -59,13 +127,30 @@ export default [
59
127
  component: () =>
60
128
  import("@shijiu/jsview-vue-samples/MetroWidgetDemos/PingPong/App.vue"),
61
129
  },
130
+
131
+ /*
132
+ * 仅测试, AI编程时, 不要参考
133
+ * mw重建性能测试, 重试每个item有大量子元素的场景下重建整个metrowidget的性能
134
+ *
135
+ */
62
136
  {
63
- meta: { nameText: "性能测试", },
64
- name: "metroWidget-性能测试",
137
+ meta: { nameText: "mw重建性能测试", },
138
+ name: "metroWidget-mw重建性能测试",
65
139
  path: "/metroWidget/PerformanceTest",
66
140
  component: () =>
67
141
  import("@shijiu/jsview-vue-samples/MetroWidgetDemos/PerformanceTest/App.vue"),
68
142
  },
143
+
144
+ /*
145
+ * 骨架图
146
+ *
147
+ * 对应的应用场景:
148
+ * 适用于所有海报平铺的场景, 例如EPG的海报区域
149
+ * 主要特点:
150
+ * 1. 开启MetroWidget组件的骨架图配置选项, 以解决按键快速操作时, 海报组件内部太复杂会卡按键响应的问题
151
+ * 2. 每个海报位使用 JsvPosterDiv 或者 JsvPosterImage 组件来实现
152
+ * 此组件实现了海报加载会淡出的效果
153
+ */
69
154
  {
70
155
  meta: { nameText: "骨架图", },
71
156
  name: "metroWidget-骨架图",
@@ -73,13 +158,34 @@ export default [
73
158
  component: () =>
74
159
  import("@shijiu/jsview-vue-samples/MetroWidgetDemos/SkeletonDiagram/App.vue"),
75
160
  },
161
+
162
+ /*
163
+ * .9焦点漂移效果页面
164
+ *
165
+ * 对应的应用场景:
166
+ * 焦点框要在多个MetroWidget之间漂移, 且漂移前后的x,y,width,height需要触发对应的transition动画的场景。
167
+ * 主要特点:
168
+ * 1. 使用 JsvNinePatch 组件来实现焦点框的漂移效果, 此组件独立于所有MetroWidget之外
169
+ * 2. 通过div.jsvGetBoundingClientRect来获取焦点框的实际位置和尺寸信息,
170
+ * 应用在JsvNinePatch的style中来让其和MetroWidget的卡片对齐, 并触发transition动画
171
+ *
172
+ * div元素异步获取显示位置的扩展接口 jsvGetBoundingClientRect 的经典使用场景
173
+ */
76
174
  {
77
- meta: { nameText: ".9焦点页面", },
78
- name: "metroWidget-.9焦点页面",
175
+ meta: { nameText: ".9焦点漂移效果页面", },
176
+ name: "metroWidget-.9焦点漂移效果页面",
79
177
  path: "/metroWidget/ninePatchFocusPage",
80
178
  component: () =>
81
179
  import("@shijiu/jsview-vue-samples/MetroWidgetDemos/ninePatchFocusPage/App.vue"),
82
180
  },
181
+
182
+ /*
183
+ * item尺寸更新
184
+ *
185
+ * 对应的应用场景:
186
+ * 一个横排的MetroWidget, 一横排多个item, 聚焦的item进行左右放大, 将左右的item推开的场景。
187
+ * MetroWidget的 <template #renderItem> 中的 query.updateItemSize 的经典使用场景。
188
+ */
83
189
  {
84
190
  meta: { nameText: "item尺寸更新", },
85
191
  name: "metroWidget-item尺寸更新",
@@ -87,13 +193,29 @@ export default [
87
193
  component: () =>
88
194
  import("@shijiu/jsview-vue-samples/MetroWidgetDemos/itemSizeUpdate/App.vue"),
89
195
  },
196
+
197
+ /*
198
+ * 焦点就近移动
199
+ *
200
+ * 对应的应用场景:
201
+ * 多层MetroWidget嵌套后,
202
+ * 使用SpatialNavigator组件和默认的onEdge回调,
203
+ * 就可以完成焦点在子MetroWidget之间移动的样例。
204
+ */
90
205
  {
91
- meta: { nameText: "三层嵌套", },
92
- name: "metroWidget-三层嵌套",
93
- path: "/metroWidget/TripleWidget",
206
+ meta: { nameText: "焦点就近移动", },
207
+ name: "metroWidget-焦点就近移动",
208
+ path: "/metroWidget/SpatialNav",
94
209
  component: () =>
95
- import("@shijiu/jsview-vue-samples/MetroWidgetDemos/TripleWidget/App.vue"),
210
+ import("@shijiu/jsview-vue-samples/MetroWidgetDemos/SpatialNav/App.vue"),
96
211
  },
212
+
213
+ /*
214
+ * 数据刷新demo
215
+ *
216
+ * 对应的应用场景:
217
+ * refreshData的经典使用场景。
218
+ */
97
219
  {
98
220
  meta: { nameText: "数据刷新demo", },
99
221
  name: "metroWidget-数据刷新demo",
@@ -101,6 +223,16 @@ export default [
101
223
  component: () =>
102
224
  import("@shijiu/jsview-vue-samples/MetroWidgetDemos/RefreshDemo/App.vue"),
103
225
  },
226
+
227
+ /*
228
+ * 剧集翻页
229
+ *
230
+ * 对应的应用场景:
231
+ * 大屏详情UI中, 上方为单个剧集组成的MetroWidget, 下方为剧集的集合组成的MetroWidget,
232
+ * 类似如下形式
233
+ * 第一行MetroWidget: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
234
+ * 第二行MetroWidget: 1-5, 5-10, 11-15
235
+ */
104
236
  {
105
237
  meta: { nameText: "剧集翻页", },
106
238
  name: "metroWidget-剧集翻页",
@@ -108,6 +240,11 @@ export default [
108
240
  component: () =>
109
241
  import("@shijiu/jsview-vue-samples/MetroWidgetDemos/SeamlessSlide/App.vue"),
110
242
  },
243
+
244
+ /*
245
+ * 仅测试, AI编程时, 不要参考
246
+ * 无滚动的平铺的MetroWidget打开enableItemRenderBreak后, 屏幕的内容分批绘制, 不影响按键响应的场景测试
247
+ */
111
248
  {
112
249
  meta: { nameText: "多item分段显示", },
113
250
  name: "metroWidget-多item分段显示",
@@ -115,4 +252,58 @@ export default [
115
252
  component: () =>
116
253
  import("@shijiu/jsview-vue-samples/MetroWidgetDemos/MassiveItems/App.vue"),
117
254
  },
255
+ // {
256
+ // meta: { nameText: "Fbo加速", },
257
+ // name: "metroWidget-Fbo加速",
258
+ // path: "/metroWidget/RenderAccelerate",
259
+ // component: () =>
260
+ // import("@shijiu/jsview-vue-samples/MetroWidgetDemos/RenderAccelerate/App.vue"),
261
+ // },
262
+
263
+ /*
264
+ * 列表展开
265
+ *
266
+ * 对应的应用场景:
267
+ * 绘制竖向的带有分类的列表界面, 且列表可以向抽屉一样展开的场景
268
+ * 也是 MetroWidget的 query.updateItemSize 的经典使用场景
269
+ */
270
+ {
271
+ meta: { nameText: "列表展开", },
272
+ name: "metroWidget-列表展开",
273
+ path: "/metroWidget/ListExpand",
274
+ component: () =>
275
+ import("@shijiu/jsview-vue-samples/MetroWidgetDemos/ListExpand/index.vue"),
276
+ },
277
+
278
+ /*
279
+ * gaze vs focus
280
+ *
281
+ * 展示MetroWidget的onGaze/onIgnore和onFocus/onBlur回调的差异
282
+ */
283
+ {
284
+ meta: { nameText: "gaze vs focus", },
285
+ name: "metroWidget-gazeVsFocus",
286
+ path: "/metroWidget/gazeVsFocus",
287
+ component: () =>
288
+ import("@shijiu/jsview-vue-samples/MetroWidgetDemos/gazeFocusDiff/App.vue"),
289
+ },
290
+
291
+ /*
292
+ * 焦点层级
293
+ *
294
+ * 对应的应用场景:
295
+ * item之间有视觉上的遮挡关系(measure结果的位置不会重叠, 只是item内部的template绘制会用负坐标往外延展)的场景,
296
+ * 确认是否能将焦点正确露出的验证
297
+ *
298
+ * 验证MetroWidget的在聚焦过程中的变化, 具体为
299
+ * 在onGaze时,对应的项目zIndex会高于其他项目
300
+ * 在onIgnore时,对应的项目zIndex会低于其他项目
301
+ */
302
+ {
303
+ meta: { nameText: "焦点层级", },
304
+ name: "metroWidget-zIndex",
305
+ path: "/metroWidget/zIndex",
306
+ component: () =>
307
+ import("@shijiu/jsview-vue-samples/MetroWidgetDemos/zIndex/App.vue"),
308
+ },
118
309
  ]