@shijiu/jsview-vue 0.9.766 → 0.9.804

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 (88) hide show
  1. package/dom/bin/jsview-browser-debug-dom.min.js +1 -1
  2. package/dom/bin/jsview-dom.min.js +1 -1
  3. package/dom/bin/jsview-engine-js-browser.min.js +1 -1
  4. package/dom/target_core_revision.js +4 -4
  5. package/package.json +1 -1
  6. package/samples/Basic/components/anim/AnimTransition.vue +4 -4
  7. package/samples/DemoHomepage/App.vue +30 -6
  8. package/samples/DemoHomepage/components/TabFrame.vue +7 -0
  9. package/samples/DemoHomepage/router.js +21 -18
  10. package/samples/DemoHomepage/views/Homepage.vue +5 -1
  11. package/samples/FilterDemo/VideoLayer.vue +2 -2
  12. package/samples/FocusBlockDemos/AutoFocus/App.vue +56 -0
  13. package/samples/FocusBlockDemos/AutoFocus/BaseBlock.vue +82 -0
  14. package/samples/FocusBlockDemos/AutoFocus/DialogBlock.vue +89 -0
  15. package/samples/FocusBlockDemos/AutoFocus/DialogContorls.js +47 -0
  16. package/samples/FocusBlockDemos/AutoFocus/FocusNamesDefine.js +9 -0
  17. package/samples/FocusBlockDemos/AutoFocus/PlaneBlock.vue +71 -0
  18. package/samples/FocusBlockDemos/ProgressiveFocusControl/App.vue +84 -0
  19. package/samples/FocusBlockDemos/ProgressiveFocusControl/BaseBlock.vue +77 -0
  20. package/samples/FocusBlockDemos/ProgressiveFocusControl/DownPlaneBlock.vue +83 -0
  21. package/samples/FocusBlockDemos/ProgressiveFocusControl/FocusNamesDefine.js +12 -0
  22. package/samples/FocusBlockDemos/ProgressiveFocusControl/UpPlaneBlock.vue +83 -0
  23. package/samples/GiftRain/App.vue +248 -0
  24. package/samples/GiftRain/audio/boom.mp3 +0 -0
  25. package/samples/GiftRain/audio/get.mp3 +0 -0
  26. package/samples/GiftRain/common/Sound.js +48 -0
  27. package/samples/GiftRain/components/RedPacket.vue +161 -0
  28. package/samples/GiftRain/components/Score.vue +55 -0
  29. package/samples/GiftRain/components/SpriteTranslate.vue +72 -0
  30. package/samples/GridDemo/Item.vue +1 -0
  31. package/samples/ImpactStop/App.vue +2 -2
  32. package/samples/Marquee/App.vue +34 -3
  33. package/samples/MetroWidgetDemos/PingPong/App.vue +22 -11
  34. package/samples/MetroWidgetDemos/PingPong/AppPage.vue +3 -3
  35. package/samples/MetroWidgetDemos/{Item.vue → PingPong/Item.vue} +1 -3
  36. package/samples/MetroWidgetDemos/PingPong/ViewSwiper.vue +3 -3
  37. package/samples/MetroWidgetDemos/{WidgetItem.vue → PingPong/WidgetItem.vue} +6 -1
  38. package/samples/MetroWidgetDemos/basic/App.vue +162 -0
  39. package/samples/MetroWidgetDemos/basic/Item.vue +43 -0
  40. package/samples/MetroWidgetDemos/direction/App.vue +158 -0
  41. package/samples/MetroWidgetDemos/direction/Item.vue +45 -0
  42. package/samples/MetroWidgetDemos/focusableItemBasic/App.vue +67 -0
  43. package/samples/MetroWidgetDemos/{Advanced → focusableItemBasic}/ButtonItem.vue +16 -20
  44. package/samples/MetroWidgetDemos/focusableItemMetroWidget/App.vue +74 -0
  45. package/samples/MetroWidgetDemos/{Advanced/widgets → focusableItemMetroWidget}/Item.vue +12 -30
  46. package/samples/MetroWidgetDemos/{Advanced/widgets → focusableItemMetroWidget}/WidgetItem.vue +10 -9
  47. package/samples/MetroWidgetDemos/focusableItemMix/App.vue +88 -0
  48. package/samples/MetroWidgetDemos/focusableItemMix/ButtonItem.vue +86 -0
  49. package/samples/MetroWidgetDemos/focusableItemMix/Item.vue +43 -0
  50. package/samples/MetroWidgetDemos/index.js +6 -0
  51. package/samples/MetroWidgetDemos/layoutType/App.vue +180 -0
  52. package/samples/MetroWidgetDemos/layoutType/Item.vue +45 -0
  53. package/samples/MetroWidgetDemos/padding/App.vue +222 -0
  54. package/samples/MetroWidgetDemos/padding/Item.vue +64 -0
  55. package/samples/MetroWidgetDemos/routeList.js +64 -0
  56. package/samples/MetroWidgetDemos/slideSetting/App.vue +225 -0
  57. package/samples/MetroWidgetDemos/slideSetting/Item.vue +45 -0
  58. package/samples/NinePatchDemo/App.vue +78 -122
  59. package/samples/NinePatchDemo/Item.vue +28 -26
  60. package/samples/Swiper/App.vue +148 -0
  61. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +15 -12
  62. package/utils/JsViewEngineWidget/TemplateParser.js +6 -1
  63. package/utils/JsViewPlugin/JsvAudio/AudioProxy.js +17 -1
  64. package/utils/JsViewPlugin/JsvAudio/JsvAudio.vue +15 -38
  65. package/utils/JsViewPlugin/JsvAudio/version.js +10 -10
  66. package/utils/JsViewPlugin/JsvPlayer/version.js +5 -5
  67. package/utils/JsViewVueTools/JsvTextTools.js +26 -3
  68. package/utils/JsViewVueWidget/JsvActorMove/JsvActorMove.vue +1 -1
  69. package/utils/JsViewVueWidget/JsvFilterView.vue +1 -1
  70. package/utils/JsViewVueWidget/JsvMarquee.vue +81 -20
  71. package/utils/JsViewVueWidget/JsvNinePatch.vue +1 -1
  72. package/utils/JsViewVueWidget/JsvPosterDiv.vue +1 -1
  73. package/utils/JsViewVueWidget/JsvPosterImage.vue +1 -1
  74. package/utils/JsViewVueWidget/JsvSpray/JsvSpray.vue +43 -9
  75. package/utils/JsViewVueWidget/JsvSwiper/JsvSwiper.vue +115 -79
  76. package/utils/JsViewVueWidget/JsvSwiper/index.js +3 -2
  77. package/utils/JsViewVueWidget/JsvTextBox.vue +1 -1
  78. package/utils/JsViewVueWidget/JsvVisibleSensor/JsvVisibleSensor.vue +1 -1
  79. package/samples/MetroWidgetDemos/Advanced/App.vue +0 -46
  80. package/samples/MetroWidgetDemos/Advanced/Buttons.vue +0 -70
  81. package/samples/MetroWidgetDemos/Advanced/Mixed.vue +0 -77
  82. package/samples/MetroWidgetDemos/Advanced/widgets/Widgets.vue +0 -116
  83. package/samples/MetroWidgetDemos/Advanced/widgets/focus1.png +0 -0
  84. package/samples/MetroWidgetDemos/Simple/AbsoluteTemplate.vue +0 -75
  85. package/samples/MetroWidgetDemos/Simple/App.vue +0 -45
  86. package/samples/MetroWidgetDemos/Simple/RelativeTemplate.vue +0 -111
  87. package/samples/MetroWidgetDemos/data.js +0 -205
  88. package/utils/JsViewVueWidget/JsvSwiper/Indicator.vue +0 -35
@@ -0,0 +1,148 @@
1
+ <!--
2
+ * @Author: ChenChanghua
3
+ * @Date: 2023-02-10 14:45:39
4
+ * @Description: file content
5
+ -->
6
+ <script setup>
7
+ import { JsvSwiper, useFocusHub, EdgeDirection } from "jsview";
8
+ import { ref, onMounted } from "vue";
9
+
10
+ const focusHub = useFocusHub();
11
+
12
+ const mySwiper = ref(null);
13
+
14
+ function randomColor() {
15
+ let randomColor = Math.round(Math.random() * 2 ** 24).toString(16);
16
+ return (
17
+ "#" + new Array(6 - randomColor.length).fill("0").join("") + randomColor
18
+ );
19
+ }
20
+ let data = [];
21
+ for (let i = 0; i < 10; i++) {
22
+ data.push({
23
+ width: 400,
24
+ height: 300,
25
+ index: i,
26
+ backgroundColor: randomColor(),
27
+ });
28
+ }
29
+
30
+ const swiper1 = {
31
+ onChange: (currentId) => {
32
+ console.log("swiper1: onChange", currentId);
33
+ },
34
+ onClick: (currentId) => {
35
+ console.log("swiper1: onClick", currentId);
36
+ },
37
+ onEdge: (info) => {
38
+ if (info.direction == EdgeDirection.bottom) {
39
+ focusHub.setFocus("mySwiper2");
40
+ }
41
+ },
42
+ };
43
+
44
+ const swiper2 = {
45
+ onChange: (currentId) => {
46
+ console.log("swiper2: onChange", currentId);
47
+ },
48
+ onClick: (currentId) => {
49
+ console.log("swiper2: onClick", currentId);
50
+ },
51
+ onEdge: (info) => {
52
+ if (info.direction == EdgeDirection.top) {
53
+ focusHub.setFocus("mySwiper1");
54
+ }
55
+ },
56
+ };
57
+ onMounted(() => {
58
+ focusHub.setFocus("mySwiper1");
59
+ });
60
+ </script>
61
+
62
+ <template>
63
+ <div>
64
+ <jsv-swiper
65
+ name="mySwiper1"
66
+ ref="mySwiper1"
67
+ :totalFrame="data.length"
68
+ :layoutInfo="{
69
+ left: 50,
70
+ top: 50,
71
+ width: 400,
72
+ height: 200,
73
+ }"
74
+ :animation="{
75
+ duration: 300,
76
+ easing: 'linear',
77
+ }"
78
+ :autoplayInterval="1000"
79
+ :onChange="swiper1.onChange"
80
+ :onClick="swiper1.onClick"
81
+ :onEdge="swiper1.onEdge"
82
+ >
83
+ <template #itemView="{ dataIndex, focused }">
84
+ <div
85
+ :style="{
86
+ width: data[dataIndex].width,
87
+ height: data[dataIndex].height,
88
+ backgroundColor: data[dataIndex].backgroundColor,
89
+ fontSize: 40,
90
+ color: focused ? '#FF0000' : '#FFFFFF',
91
+ }"
92
+ >
93
+ {{ data[dataIndex].index }}
94
+ </div>
95
+ </template>
96
+ </jsv-swiper>
97
+
98
+ <jsv-swiper
99
+ name="mySwiper2"
100
+ ref="mySwiper2"
101
+ :totalFrame="data.length"
102
+ :layoutInfo="{
103
+ left: 50,
104
+ top: 300,
105
+ width: 400,
106
+ height: 200,
107
+ }"
108
+ :animation="{
109
+ duration: 300,
110
+ easing: 'linear',
111
+ }"
112
+ :autoplayInterval="1000"
113
+ :onChange="swiper2.onChange"
114
+ :onClick="swiper2.onClick"
115
+ :onEdge="swiper2.onEdge"
116
+ :reverseSwipe="true"
117
+ :dotSize="20"
118
+ :disableLoopWhenFocus="true"
119
+ >
120
+ <template #itemView="{ dataIndex, focused }">
121
+ <div
122
+ :style="{
123
+ width: data[dataIndex].width,
124
+ height: data[dataIndex].height,
125
+ backgroundColor: data[dataIndex].backgroundColor,
126
+ fontSize: 40,
127
+ color: focused ? '#FF0000' : '#FFFFFF',
128
+ }"
129
+ >
130
+ {{ data[dataIndex].index }}
131
+ </div>
132
+ </template>
133
+ <template #indicatorDot="{ dataIndex, currentIndex }">
134
+ <div
135
+ :style="{
136
+ width: 20,
137
+ height: 20,
138
+ backgroundColor:
139
+ dataIndex == currentIndex
140
+ ? 'rgba(100, 100, 100, 0.7)'
141
+ : '#ff0000',
142
+ borderRadius: 10,
143
+ }"
144
+ ></div>
145
+ </template>
146
+ </jsv-swiper>
147
+ </div>
148
+ </template>
@@ -1,8 +1,8 @@
1
1
  <!--
2
2
  * @Author: ChenChanghua
3
3
  * @Date: 2021-09-22 16:08:58
4
- * @LastEditors: ChenChanghua
5
- * @LastEditTime: 2022-12-19 11:17:10
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2023-03-09 11:17:00
6
6
  * @Description: file content
7
7
  -->
8
8
 
@@ -36,7 +36,7 @@
36
36
  @description 整页滚动的设置类
37
37
  @constructor {Object} {speed, easing, boundProtect}
38
38
  SeamlessSlide
39
- @description 平滑滚动的设置类
39
+ @description 无缝滚动的设置类
40
40
  @constructor {Object} {startPercent, endPercent, speed, easing, boundProtect}
41
41
  FixPositionSlide
42
42
  @description 固定位置滚动的设置类
@@ -371,7 +371,7 @@ const props = defineProps({
371
371
  slideSetting: {
372
372
  type: SlideSetting,
373
373
  default() {
374
- return new SeamlessSlide(0.2, 0.8);
374
+ return new SeamlessSlide({ startPercent: 0.2, endPercent: 0.8 });
375
375
  },
376
376
  },
377
377
  layoutType: {
@@ -548,24 +548,26 @@ const _dispatchEvent = (event) => {
548
548
  };
549
549
 
550
550
  const onItemClick = (index) => {
551
- if (isFocus && innerData[index].callbacks.callable("onClick")) {
551
+ if (isFocus && innerData[index]?.callbacks.callable("onClick")) {
552
552
  innerData[index].callbacks.onClick();
553
553
  }
554
554
  };
555
555
 
556
556
  const onItemBlur = (index) => {
557
- if (isFocus && innerData[index].callbacks.callable("onBlur")) {
557
+ if (isFocus && innerData[index]?.callbacks.callable("onBlur")) {
558
558
  innerData[index].callbacks.onBlur();
559
559
  }
560
560
  };
561
561
 
562
562
  const onItemFocus = (index, rect) => {
563
563
  if (isFocus) {
564
- _itemOnFocusSideEffect(innerData[index], rect);
565
- if (innerData[index].callbacks.callable("onFocus")) {
566
- innerData[index].callbacks.onFocus(rect);
567
- } else {
568
- callFocusAfterUpdate = true;
564
+ if (innerData[index]) {
565
+ _itemOnFocusSideEffect(innerData[index], rect);
566
+ if (innerData[index].callbacks.callable("onFocus")) {
567
+ innerData[index].callbacks.onFocus(rect);
568
+ } else {
569
+ callFocusAfterUpdate = true;
570
+ }
569
571
  }
570
572
  }
571
573
  };
@@ -1320,7 +1322,7 @@ const _moveToNext = (
1320
1322
  let rect;
1321
1323
  let x_off_set = cur_focus_item.xPos - next_focus_item.xPos;
1322
1324
  let y_off_set = cur_focus_item.yPos - next_focus_item.yPos;
1323
- if (item_edge_rect) {
1325
+ if (item_edge_rect && item_edge_rect.rect) {
1324
1326
  item_edge_rect.rect.x += x_off_set;
1325
1327
  item_edge_rect.rect.y += y_off_set;
1326
1328
  rect = item_edge_rect;
@@ -1551,6 +1553,7 @@ const _onFocus = (params) => {
1551
1553
  focus_id = _ifValidEnterRect(enterFocusRect)
1552
1554
  ? _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect)
1553
1555
  : focus_id;
1556
+
1554
1557
  preEdgeRect = enterFocusRect;
1555
1558
  focusId = focus_id;
1556
1559
  enterFocusId = -1;
@@ -1065,7 +1065,12 @@ class TemplateParser {
1065
1065
  }
1066
1066
 
1067
1067
  IdToIndex(id) {
1068
- return this._Template.IdsMap[id];
1068
+ const index = this._Template.IdsMap[id];
1069
+ if (typeof index !== "undefined") {
1070
+ return index;
1071
+ } else {
1072
+ return -1;
1073
+ }
1069
1074
  }
1070
1075
 
1071
1076
  /**
@@ -247,8 +247,24 @@ class AudioProxy {
247
247
  get currentTime() { return this.getProperty("currentTime"); }
248
248
 
249
249
  setSrc(url, head) {
250
+ if (!url) {
251
+ console.error("JsvAudio: src is null");
252
+ return;
253
+ }
254
+ let realUrl = url.trim();
255
+ if (window.JsView) {
256
+ // jsview上
257
+ if (realUrl.startsWith("/") || realUrl.startsWith("file://")) {
258
+ //本地文件
259
+ realUrl = url;
260
+ } else {
261
+ realUrl = new window.JsView.Dom.UrlRef(url).href;
262
+ }
263
+ } else {
264
+ realUrl = url;
265
+ }
250
266
  const param = {
251
- url: url,
267
+ url: realUrl,
252
268
  head: JSON.stringify(head),
253
269
  };
254
270
  this.setProperty("src", param);
@@ -92,22 +92,6 @@ export default {
92
92
  return {};
93
93
  },
94
94
  },
95
- /**
96
- * 属性,Boolean类型,活跃状态
97
- */
98
- active: { type: Boolean, default: true },
99
- },
100
-
101
- watch: {
102
- active(newValue) {
103
- console.log("active newValue: " + newValue);
104
- if (this.audio) {
105
- if (newValue) {
106
- //同key的player切换时需要切换回调
107
- this.registerEvent();
108
- }
109
- }
110
- },
111
95
  },
112
96
  setup() {
113
97
  return {
@@ -122,26 +106,22 @@ export default {
122
106
  console.log("player key:" + key);
123
107
 
124
108
  this.audio = sAudioManager.createAudio(key);
109
+ this.registerEvent();
110
+ if (this.src && this.src !== "") {
111
+ this.audio.src = this.src;
112
+ }
125
113
 
126
- if (this.active) {
127
- this.registerEvent();
128
- if (this.src && this.src !== "") this.audio.src = this.src;
129
-
130
- if (this.currentTime !== 0) this.audio.currentTime = this.currentTime;
131
-
132
- if (this.autoplay) {
133
- this.audio.autoplay = this.autoplay;
134
- }
135
-
136
- if (this.muted) {
137
- this.audio.muted = this.muted;
138
- }
114
+ if (this.autoplay) {
115
+ this.audio.autoplay = this.autoplay;
116
+ }
139
117
 
140
- if (this.loop) {
141
- this.audio.loop = this.loop;
142
- }
118
+ if (this.muted) {
119
+ this.audio.muted = this.muted;
143
120
  }
144
121
 
122
+ if (this.loop) {
123
+ this.audio.loop = this.loop;
124
+ }
145
125
  this.onRef?.(this.audio);
146
126
  },
147
127
 
@@ -154,13 +134,10 @@ export default {
154
134
 
155
135
  methods: {
156
136
  registerEvent() {
157
- if (this.audio && this.active) {
137
+ if (this.audio) {
158
138
  this.audio.addEventListener("end", this.onEnded);
159
139
  this.audio.addEventListener("error", this.onError);
160
- this.audio.addEventListener("loadstart", () => {
161
- console.log("JsAudio received loadstart event.");
162
- this.onLoadStart();
163
- });
140
+ this.audio.addEventListener("loadstart", this.onLoadStart);
164
141
  this.audio.addEventListener("loadedmetadata", this.onLoadedMetaData);
165
142
  this.audio.addEventListener("load", this.onLoad);
166
143
  this.audio.addEventListener("audiofocusloss", this.onAudioFocusLoss);
@@ -172,5 +149,5 @@ export default {
172
149
  </script>
173
150
 
174
151
  <template>
175
- <div :style="{width: 1, height: 1}" backgroundColor="rgba(0,0,0,1)"></div>
152
+ <div :style="{ width: 1, height: 1 }" backgroundColor="rgba(0,0,0,1)"></div>
176
153
  </template>
@@ -3,17 +3,17 @@
3
3
  * @Date: 2023-02-22 18:22:26
4
4
  * @Description: file content
5
5
  */
6
- let PluginInfo={
6
+ let PluginInfo = {
7
7
  // downloadUrl:"http://192.168.0.63:8080/plugin/JsvAudio-164.zip", //插件下载地址
8
- packageName:"com.qcode.jsvaudio",
9
- name:"音频插件",
10
- version:"1.0.1", //插件需要的版本号
11
- versionCodeMin:1,
12
- versionCodeMax:1,
13
- bridgeName:"jsvAudioBridge", //插件bridge注册到jsview的名称
14
- className:"com.qcode.jsvaudio.JsvAudio", //插件初始化类名称
15
- initMethod:"createInstance", //插件初始化方法
16
- listener:"top.JsvAudioPluginLoadResult", //插件加载结果回调
8
+ packageName: "com.qcode.jsvaudio",
9
+ name: "音频插件",
10
+ version: "1.0.19", //插件需要的版本号
11
+ versionCodeMin: 19,
12
+ versionCodeMax: 19,
13
+ bridgeName: "jsvAudioBridge", //插件bridge注册到jsview的名称
14
+ className: "com.qcode.jsvaudio.JsvAudio", //插件初始化类名称
15
+ initMethod: "createInstance", //插件初始化方法
16
+ listener: "top.JsvAudioPluginLoadResult", //插件加载结果回调
17
17
  listener2: "top.JsvAudioPluginStatus",
18
18
  // debug:true,
19
19
  // md5:"baafc8ea737adcad5443f44cc0112498"
@@ -1,17 +1,17 @@
1
1
  let PluginInfo={
2
- // downloadUrl:"http://10.61.2.170:8080/plugin/JsvPlayer-194.zip", //插件下载地址
2
+ // downloadUrl:"http://192.168.0.85:8080/plugin/JsvPlayer-199.zip", //插件下载地址
3
3
  packageName:"com.qcode.jsvplayer",
4
4
  name:"播放器插件",
5
- version:"1.9.6", //插件需要的版本号
6
- versionCodeMin:196,
7
- versionCodeMax:196,
5
+ version:"2.0.2", //插件需要的版本号
6
+ versionCodeMin:202,
7
+ versionCodeMax:202,
8
8
  bridgeName:"jsvPlayerBridge", //插件bridge注册到jsview的名称
9
9
  className:"com.qcode.jsvplayer.JsvPlayer", //插件初始化类名称
10
10
  initMethod:"createInstance", //插件初始化方法
11
11
  listener:"top.JsvPlayerPluginLoadResult", //插件加载结果回调
12
12
  listener2: "top.JsvPlayerPluginStatus",
13
13
  // debug:true,
14
- md5:"e671a5c28a8fece02115625430c6b56d"
14
+ md5:"6de8d620492bf0143bbccc62636a6271"
15
15
  };
16
16
 
17
17
  // 不要用export default,update-env脚本不能解析
@@ -1,10 +1,12 @@
1
1
  /*
2
2
  * @Author: ChenChanghua
3
3
  * @Date: 2022-11-29 14:26:20
4
- * @LastEditors: ChenChanghua
5
- * @LastEditTime: 2022-11-29 14:27:03
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2023-03-09 13:34:59
6
6
  * @Description: file content
7
7
  */
8
+ import { Forge } from "../../dom/jsv-forge-define";
9
+
8
10
  const getTextWidth = (text, style) => {
9
11
  const textParams = {
10
12
  str: text ? text : "",
@@ -15,4 +17,25 @@ const getTextWidth = (text, style) => {
15
17
  };
16
18
  return window.PlatformUtils.GetTextWidth(textParams);
17
19
  };
18
- export { getTextWidth };
20
+
21
+ const isRtl = (str) => {
22
+ //arabic
23
+ for (let i = 0; i < str.length; i++) {
24
+ let c = str.charCodeAt(i);
25
+ if (c != 32) {
26
+ if (c >= 0x0600 && c <= 0x06ff) {
27
+ return true;
28
+ } else {
29
+ return false;
30
+ }
31
+ }
32
+ }
33
+ return false;
34
+ }
35
+
36
+ const TextTools = {
37
+ getTextWidth,
38
+ isRtl,
39
+ }
40
+
41
+ export { getTextWidth, TextTools };
@@ -35,7 +35,7 @@
35
35
  -->
36
36
  <script setup>
37
37
  import JsvActorMoveControl from "./JsvActorMoveControl";
38
- import { shallowRef, onMounted } from "vue";
38
+ import { shallowRef, onMounted, defineProps, defineExpose } from "vue";
39
39
 
40
40
  const props = defineProps({
41
41
  control: {
@@ -12,7 +12,7 @@
12
12
  -->
13
13
  <script setup>
14
14
  import { Forge, ForgeExtension } from "../../dom/jsv-forge-define";
15
- import { onBeforeUnmount, watchEffect } from "vue";
15
+ import { onBeforeUnmount, watchEffect, defineProps } from "vue";
16
16
 
17
17
  const props = defineProps({
18
18
  width: {
@@ -5,19 +5,16 @@
5
5
  * text {String} 文字内容
6
6
  * style {Object} 样式
7
7
  * slideSpeed {int} 滚动速度 px/s, 默认60
8
+ * slideDirection{String} 滚动方向 ste(start to end)/ets(end to start)/ltr/rtl
8
9
  * forceSlide {boolean} 短文字是否滚动,默认false
10
+ * 说明
11
+ * JsvMarquee会识别阿拉伯字符自动设置direction
9
12
  -->
10
13
 
11
14
  <script setup>
12
15
  import { Forge } from "../../dom/jsv-forge-define";
13
- import { getTextWidth } from "../JsViewVueTools/JsvTextTools";
14
- import {
15
- shallowRef,
16
- computed,
17
- toRaw,
18
- onMounted,
19
- onBeforeUnmount,
20
- } from "vue";
16
+ import { TextTools } from "../JsViewVueTools/JsvTextTools";
17
+ import { shallowRef, computed, toRaw, onMounted, onBeforeUnmount, defineProps } from "vue";
21
18
 
22
19
  const defaultFontStyle = () => {
23
20
  return {
@@ -55,6 +52,14 @@ const props = defineProps({
55
52
  type: Number,
56
53
  default: 60,
57
54
  },
55
+ slideDirection: {
56
+ type: String,
57
+ validator(value) {
58
+ // The value must match one of these strings
59
+ return ["ste", "ets", "ltr", "rtl"].includes(value);
60
+ },
61
+ default: "ste",
62
+ },
58
63
  forceSlide: {
59
64
  type: Boolean,
60
65
  default: false,
@@ -65,6 +70,15 @@ const textDiv = shallowRef(null);
65
70
  let animState = 0;
66
71
  let animIdleHandler = -1;
67
72
  let asyncStartHandler = -1;
73
+
74
+ const _direction = computed(() => {
75
+ if (props.style?.direction == "rtl" || props.style.direction == "ltr") {
76
+ return props.style.direction;
77
+ } else {
78
+ return TextTools.isRtl(props.text) ? "rtl" : "ltr";
79
+ }
80
+ });
81
+
68
82
  const fontStyle = computed(() => {
69
83
  let { left, top, width, height, ...rest } = props.style;
70
84
  let r = defaultFontStyle();
@@ -73,12 +87,14 @@ const fontStyle = computed(() => {
73
87
  //滚送时必需start对齐
74
88
  r.textAlign = "start";
75
89
  }
90
+ r.direction = _direction.value;
76
91
  return r;
77
92
  });
93
+
78
94
  //rtl文字需要先获得文字宽度
79
95
  let textWidth =
80
96
  fontStyle.value.direction == "rtl"
81
- ? getTextWidth(props.text, fontStyle.value)
97
+ ? TextTools.getTextWidth(props.text, fontStyle.value)
82
98
  : 0;
83
99
  const slideDivLeft = computed(() =>
84
100
  fontStyle.value.direction == "rtl" && props.style.width < textWidth
@@ -86,16 +102,61 @@ const slideDivLeft = computed(() =>
86
102
  : 0
87
103
  );
88
104
 
105
+ const getAnimInfo = (state) => {
106
+ const info = {
107
+ start: 0,
108
+ end: 0,
109
+ };
110
+ const isRtl = _direction.value == "rtl";
111
+ if (state == 0) {
112
+ //滚出
113
+ if (isRtl) {
114
+ if (props.slideDirection == "rtl" || props.slideDirection == "ste") {
115
+ info.end = textWidth;
116
+ } else {
117
+ //反向滚动
118
+ info.end = -props.style.width;
119
+ }
120
+ } else {
121
+ if (props.slideDirection == "ltr" || props.slideDirection == "ste") {
122
+ info.end = -textWidth;
123
+ } else {
124
+ //反向滚动
125
+ info.end = props.style.width;
126
+ }
127
+ }
128
+ } else {
129
+ //滚入
130
+ if (isRtl) {
131
+ if (props.slideDirection == "rtl" || props.slideDirection == "ste") {
132
+ info.start = -props.style.width;
133
+ } else {
134
+ //反向滚动
135
+ info.start = textWidth;
136
+ }
137
+ } else {
138
+ if (props.slideDirection == "ltr" || props.slideDirection == "ste") {
139
+ info.start = props.style.width;
140
+ } else {
141
+ //反向滚动
142
+ info.start = -textWidth;
143
+ }
144
+ }
145
+ }
146
+ return info;
147
+ };
148
+
89
149
  const slideStep = () => {
150
+ let animInfo = getAnimInfo(animState);
90
151
  if (animState == 0) {
91
152
  // 文字从原始位置,移动出屏幕(每次完整移动,停顿1秒)
92
- let start = 0,
93
- end = fontStyle.value.direction == "rtl" ? textWidth : -textWidth;
153
+ // let start = 0,
154
+ // end = fontStyle.value.direction == "rtl" ? textWidth : -textWidth;
94
155
  animIdleHandler = setTimeout(() => {
95
156
  animIdleHandler = -1;
96
157
  const anim = new Forge.TranslateFrameAnimation(
97
- start,
98
- end,
158
+ animInfo.start,
159
+ animInfo.end,
99
160
  props.slideSpeed,
100
161
  true,
101
162
  0,
@@ -119,14 +180,14 @@ const slideStep = () => {
119
180
  }, 1000);
120
181
  } else {
121
182
  // 文字从屏幕外部,移动回屏幕中的文字原始位置
122
- let start =
123
- fontStyle.value.direction == "rtl"
124
- ? -props.style.width
125
- : props.style.width,
126
- end = 0;
183
+ // let start =
184
+ // fontStyle.value.direction == "rtl"
185
+ // ? -props.style.width
186
+ // : props.style.width,
187
+ // end = 0;
127
188
  const anim = new Forge.TranslateFrameAnimation(
128
- start,
129
- end,
189
+ animInfo.start,
190
+ animInfo.end,
130
191
  props.slideSpeed,
131
192
  true,
132
193
  props.style.width,
@@ -17,7 +17,7 @@
17
17
  -->
18
18
 
19
19
  <script setup>
20
- import { ref, watchEffect, computed } from "vue";
20
+ import { ref, watchEffect, computed, defineProps } from "vue";
21
21
 
22
22
  const props = defineProps({
23
23
  style: {
@@ -10,7 +10,7 @@
10
10
  -->
11
11
  <script setup>
12
12
 
13
- import { reactive, watchEffect } from "vue";
13
+ import { reactive, watchEffect, defineProps } from "vue";
14
14
 
15
15
  const props = defineProps({
16
16
  style: Object,
@@ -8,7 +8,7 @@
8
8
 
9
9
  <script setup>
10
10
 
11
- import { reactive, watchEffect } from "vue";
11
+ import { reactive, watchEffect, defineProps } from "vue";
12
12
 
13
13
  const props = defineProps({
14
14
  colorSpace: {