@shijiu/jsview-vue-samples 2.3.0 → 2.3.151-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 (117) hide show
  1. package/DashPath/App.vue +17 -16
  2. package/DashPath/AppForOperator.vue +2 -4
  3. package/DemoForOperator/AnimPic/AnimPic.vue +24 -2
  4. package/DemoForOperator/Banger/Banger/Banger.vue +73 -9
  5. package/DemoForOperator/Blur/Blur.vue +146 -0
  6. package/DemoForOperator/Blur/BlurInOut/BlurInOut.vue +158 -0
  7. package/DemoForOperator/Blur/BlurInOut/StaticBgSlide.vue +162 -0
  8. package/DemoForOperator/Blur/BlurPopup/BlurPopup.vue +113 -0
  9. package/DemoForOperator/BookFlip/App.vue +115 -0
  10. package/DemoForOperator/BookFlip/BookFlip/FlipPage.vue +179 -0
  11. package/DemoForOperator/BookFlip/BookFlip/FlippingBook.vue +310 -0
  12. package/DemoForOperator/BookFlip/BookFlip/flip.glsl +135 -0
  13. package/DemoForOperator/BookFlip/BookPage.vue +82 -0
  14. package/DemoForOperator/Bounce/Bounce.vue +33 -1
  15. package/DemoForOperator/ChunLian/Couplets.vue +44 -1
  16. package/DemoForOperator/ClickSpriteAnim/App.vue +130 -0
  17. package/DemoForOperator/ClickSpriteAnim/Item.vue +74 -0
  18. package/DemoForOperator/DominantColor/App.vue +187 -0
  19. package/DemoForOperator/EpisodeList/EpisodeList/Controller.vue +0 -3
  20. package/DemoForOperator/EpisodeList/EpisodeList/EpisodeList.vue +76 -2
  21. package/DemoForOperator/Firework1/App.vue +1 -1
  22. package/DemoForOperator/Firework1/Fireworks.vue +50 -11
  23. package/DemoForOperator/FlipPage/FlipPage/FlipPage.vue +29 -1
  24. package/DemoForOperator/Focus/Alpha/AlphaFocusBox.vue +27 -2
  25. package/DemoForOperator/Focus/Light/LightFocusBox.vue +42 -1
  26. package/DemoForOperator/Focus/Normal/NormalFocusBox.vue +12 -0
  27. package/DemoForOperator/FrameShadow/App.vue +193 -0
  28. package/DemoForOperator/FrameShadow/FrameShadow.vue +61 -0
  29. package/DemoForOperator/FullscreenIn/App.vue +1 -1
  30. package/DemoForOperator/FullscreenIn/FullscreenPoster.vue +18 -3
  31. package/DemoForOperator/Genie/geniePakcer/Genie.vue +60 -18
  32. package/DemoForOperator/GrayFilter/GrayFilter.vue +21 -0
  33. package/DemoForOperator/Jigsaw/JigsawFull.vue +46 -4
  34. package/DemoForOperator/Jigsaw/JigsawSingle.vue +34 -2
  35. package/DemoForOperator/LongChatBox/App.vue +36 -0
  36. package/DemoForOperator/LongChatBox/Bubble.vue +104 -0
  37. package/DemoForOperator/LongChatBox/LongChat.vue +173 -0
  38. package/DemoForOperator/LongChatBox/TextManager.ts +147 -0
  39. package/DemoForOperator/LongChatBox/VirtualList.vue +298 -0
  40. package/DemoForOperator/LongChatBox/testData.js +51 -0
  41. package/DemoForOperator/LongChatBox/utile.js +331 -0
  42. package/DemoForOperator/Particle/Drop/DropParticle.vue +33 -1
  43. package/DemoForOperator/Particle/Explode/ExplodeParticle.vue +23 -2
  44. package/DemoForOperator/PosterAnim/PosterAnim.js +21 -0
  45. package/DemoForOperator/PosterOverflow/PosterOverflow.vue +16 -0
  46. package/DemoForOperator/Resize/App.vue +157 -0
  47. package/DemoForOperator/Resize/Resize/Item.vue +234 -0
  48. package/DemoForOperator/Resize/Resize/Resize.vue +96 -0
  49. package/DemoForOperator/Ripple/Ripple.vue +16 -1
  50. package/DemoForOperator/ScreenShootScale/App.vue +96 -0
  51. package/DemoForOperator/ScreenShootScale/Back.vue +86 -0
  52. package/DemoForOperator/ScreenShootScale/Front.vue +133 -0
  53. package/DemoForOperator/ScreenShootScale/Item.vue +62 -0
  54. package/DemoForOperator/ScreenShootScale/ScreenShootScale.vue +109 -0
  55. package/DemoForOperator/SmoothSwiper/App.vue +50 -0
  56. package/DemoForOperator/Sound/Bounce/App.vue +56 -0
  57. package/DemoForOperator/Sound/Bounce/Bounce.vue +87 -0
  58. package/DemoForOperator/Sound/Bounce/FreeMoveBuilder.js +146 -0
  59. package/DemoForOperator/Sound/Bounce/bgmusic.mp3 +0 -0
  60. package/DemoForOperator/Sound/Bounce/coin.mp3 +0 -0
  61. package/DemoForOperator/Sound/FocusMove/App.vue +134 -0
  62. package/DemoForOperator/Sound/FocusMove/Item.vue +43 -0
  63. package/DemoForOperator/Sound/FocusMove/move.mp3 +0 -0
  64. package/DemoForOperator/Sound/Rain/App.vue +11 -0
  65. package/DemoForOperator/Sound/Rain/Raining/Rain.vue +69 -0
  66. package/DemoForOperator/Sound/Rain/Raining/RainScene.vue +118 -0
  67. package/DemoForOperator/Sound/Sound/Sound.vue +24 -0
  68. package/DemoForOperator/Sound/Sound/index.js +4 -0
  69. package/DemoForOperator/Sound/Sound/useSound.js +112 -0
  70. package/DemoForOperator/Sprite/Sprite.vue +62 -5
  71. package/DemoForOperator/Stretch/Stretch/Stretch.vue +52 -2
  72. package/DemoForOperator/Swiper/App.vue +101 -0
  73. package/DemoForOperator/Swiper/Item.vue +56 -0
  74. package/DemoForOperator/Swiper/ParallaxSlide.vue +164 -0
  75. package/DemoForOperator/TabContent/TabContent/TabContent.vue +39 -1
  76. package/DemoForOperator/TabContentVertical/App.vue +104 -0
  77. package/DemoForOperator/TabContentVertical/ContentPage.vue +67 -0
  78. package/DemoForOperator/TabContentVertical/Item.vue +94 -0
  79. package/DemoForOperator/TabContentVertical/PageItem.vue +40 -0
  80. package/DemoForOperator/TabContentVertical/TabContent/CreepFocus.vue +160 -0
  81. package/DemoForOperator/TabContentVertical/TabContent/Item.vue +63 -0
  82. package/DemoForOperator/TabContentVertical/TabContent/TabContent.vue +184 -0
  83. package/DemoForOperator/TabContentVertical/TabContent/TabItem.vue +368 -0
  84. package/DemoForOperator/TabContentVertical/TabContent/TabWidget.vue +259 -0
  85. package/DemoForOperator/TabContentVertical/TabContent/Util.js +3 -0
  86. package/DemoForOperator/TabContentVertical/TabContent/ViewSwiper.vue +110 -0
  87. package/DemoForOperator/TabContentVertical/assets/children_science.png +0 -0
  88. package/DemoForOperator/TabContentVertical/assets/documentary.png +0 -0
  89. package/DemoForOperator/TabContentVertical/assets/free.png +0 -0
  90. package/DemoForOperator/TabContentVertical/assets/game.png +0 -0
  91. package/DemoForOperator/TabContentVertical/assets/home_selected.png +0 -0
  92. package/DemoForOperator/TabContentVertical/assets/movie_ticket.png +0 -0
  93. package/DemoForOperator/TabContentVertical/assets/my_account.png +0 -0
  94. package/DemoForOperator/TabContentVertical/assets/opera.png +0 -0
  95. package/DemoForOperator/TabContentVertical/assets/sports.png +0 -0
  96. package/DemoForOperator/TabContentVertical/assets/tv_drama.png +0 -0
  97. package/DemoForOperator/TabContentVertical/assets/variety_show.png +0 -0
  98. package/DemoForOperator/TabContentVertical/assets/vip.png +0 -0
  99. package/DemoForOperator/TabContentVertical/testData.js +76 -0
  100. package/DemoForOperator/Vortex/Vortex/Vortex.vue +26 -0
  101. package/DemoForOperator/routeList.js +118 -1
  102. package/DemoHomepage/components/Item.vue +11 -0
  103. package/DemoHomepage/router.js +75 -1
  104. package/GiftRain/components/SpriteTranslate.vue +68 -48
  105. package/HashHistory/App.vue +2 -2
  106. package/HashHistory/router.js +1 -1
  107. package/MetroWidgetDemos/TripleWidget/App.vue +7 -1
  108. package/MetroWidgetDemos/TripleWidget/Item.vue +16 -2
  109. package/MetroWidgetDemos/TripleWidget/SWidgetItem.vue +7 -1
  110. package/MetroWidgetDemos/TripleWidget/WidgetItem.vue +8 -2
  111. package/MetroWidgetDemos/routeList.js +17 -0
  112. package/PosterPacker/App.vue +2 -2
  113. package/ViewOpacity/App.vue +19 -0
  114. package/package.json +1 -1
  115. package/DashPath/DashPath.vue +0 -118
  116. package/DemoForOperator/ScalePoster/App.vue +0 -4
  117. package/DemoForOperator/ScalePoster/ScalePoster.vue +0 -0
@@ -0,0 +1,62 @@
1
+ <!--
2
+ * @Author: ChenChanghua
3
+ * @Date: 2023-03-08 14:52:17
4
+ * @Description: file content
5
+ -->
6
+ <script setup>
7
+ import { shallowRef, onMounted, inject } from "vue";
8
+
9
+ const props = defineProps({
10
+ data: Object,
11
+ onAction: Object,
12
+ });
13
+
14
+ const focused = shallowRef(false);
15
+ const setTarget = inject("setTarget");
16
+
17
+ // 注册回调
18
+ const onFocus = () => {
19
+ focused.value = true;
20
+ };
21
+ const onBlur = () => {
22
+ focused.value = false;
23
+ };
24
+ const onClick = () => {
25
+ console.log("item onclick ", props.data);
26
+ };
27
+ props.onAction.register("onFocus", onFocus);
28
+ props.onAction.register("onBlur", onBlur);
29
+ props.onAction.register("onClick", onClick);
30
+
31
+ const imgRef = shallowRef(null);
32
+ onMounted(() => {
33
+ imgRef.value?.jsvGetBoundingClientRect().then((rect) => {
34
+ setTarget(rect.left, rect.top, rect.width, rect.height);
35
+ });
36
+ });
37
+ </script>
38
+
39
+ <template>
40
+ <div
41
+ v-if="data.imgUrl"
42
+ ref="imgRef"
43
+ :style="{
44
+ width: data.width,
45
+ height: data.height,
46
+ backgroundImage: data.imgUrl,
47
+ borderRadius: 10,
48
+ }"
49
+ ></div>
50
+ <div
51
+ v-else
52
+ :style="{
53
+ width: data.width,
54
+ height: data.height,
55
+ fontSize: 30,
56
+ color: focused ? '#FF0000' : '#FFFFFF',
57
+ backgroundColor: data.color,
58
+ }"
59
+ >
60
+ {{ data.content }}
61
+ </div>
62
+ </template>
@@ -0,0 +1,109 @@
1
+ <template>
2
+ <div
3
+ :style="{
4
+ left: from.left,
5
+ top: from.top,
6
+ width: from.width,
7
+ height: from.height,
8
+ animation: scaleAnim,
9
+ }"
10
+ @animationend="onAnimEnd"
11
+ >
12
+ <div
13
+ v-show="backShow"
14
+ :style="{
15
+ left: from.left,
16
+ top: from.top,
17
+ width: from.width,
18
+ height: from.height,
19
+ backgroundImage: toSource,
20
+ borderRadius: 50,
21
+ }"
22
+ ></div>
23
+ <div
24
+ v-if="frontShow"
25
+ :style="{
26
+ left: from.left,
27
+ top: from.top,
28
+ width: from.width,
29
+ height: from.height,
30
+ backgroundImage: fromSource,
31
+ animation: frontAnim,
32
+ borderRadius: 50,
33
+ }"
34
+ ></div>
35
+ </div>
36
+ </template>
37
+
38
+ <script>
39
+ let token = 0;
40
+ </script>
41
+ <script setup>
42
+ import { ref, onMounted, onBeforeUnmount } from "vue";
43
+ import { getKeyFramesGroup } from "jsview";
44
+
45
+ const props = defineProps({
46
+ from: Object,
47
+ to: Object,
48
+ duration: Number,
49
+ easing: String,
50
+ fromSource: String,
51
+ toSource: String,
52
+ });
53
+
54
+ const emit = defineEmits(["animationend"]);
55
+
56
+ const frontShow = ref(true);
57
+ const backShow = ref(true);
58
+ const frontAnim = ref(null);
59
+ const backAnim = ref(null);
60
+
61
+ const scaleAnimName = "screen_shoot_scale_anim_" + token++;
62
+ const scaleAnimBody = `@keyframes ${scaleAnimName} {
63
+ from { transform: translate3d(0,0,0) scale3d(1,1,1); transform-origin: 0 0; }
64
+ to { transform: translate3d(${props.to.left - props.from.left}, ${
65
+ props.to.top - props.from.top
66
+ }, 0) scale3d(${props.to.width / props.from.width}, ${
67
+ props.to.height / props.from.height
68
+ }, 1); transform-origin: 0 0; } }`;
69
+ const styleSheets = getKeyFramesGroup();
70
+ styleSheets.insertRule(scaleAnimBody);
71
+ const scaleAnim = ref(null);
72
+
73
+ const onAnimEnd = () => {
74
+ frontShow.value = false;
75
+ emit("animationend");
76
+ };
77
+
78
+ onMounted(() => {
79
+ frontAnim.value = `fadeOut ${props.duration / 1000}s ${props.easing}`;
80
+ backAnim.value = `fadeIn ${props.duration / 1000}s ${props.easing}`;
81
+ scaleAnim.value = `${scaleAnimName} ${props.duration / 1000}s ${
82
+ props.easing
83
+ }`;
84
+ });
85
+
86
+ onBeforeUnmount(() => {
87
+ styleSheets.removeRule(scaleAnimName);
88
+ });
89
+ </script>
90
+
91
+ <style scopped>
92
+ @keyframes fadeIn {
93
+ 0% {
94
+ opacity: 0;
95
+ }
96
+ 100% {
97
+ opacity: 1;
98
+ }
99
+ }
100
+
101
+ @keyframes fadeOut {
102
+ 0% {
103
+ opacity: 1;
104
+ }
105
+ 100% {
106
+ opacity: 0;
107
+ }
108
+ }
109
+ </style>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <div
3
+ :style="{
4
+ top: 100,
5
+ left: 0,
6
+ }"
7
+ >
8
+ <jsv-smooth-swiper
9
+ :name="'smooth-swiper'"
10
+ :total-frame="20"
11
+ :first-frame="1"
12
+ :layout-info="{ width: 1280, height: 300 }"
13
+ :item-size="{ width: 800, height: 200 }"
14
+ :item-gap="30"
15
+ :on-edge="onEdge"
16
+ :padding="{ top: 50, bottom: 50}"
17
+ >
18
+ <template #itemView="{ currentIndex, dataIndex, focused }">
19
+ <div
20
+ :style="{
21
+ width: 800,
22
+ height: 200,
23
+ backgroundColor: currentIndex == dataIndex ? '#007788' : '#778800',
24
+ transform: currentIndex == dataIndex ? 'scale3d(1.05, 1.05, 1)' : 'scale3d(1, 1, 1)',
25
+ transition: 'transform 0.3s',
26
+ fontSize: 40,
27
+ textAlign: 'center',
28
+ color: '#fff',
29
+ }"
30
+ >
31
+ {{ dataIndex }}
32
+ </div>
33
+ </template>
34
+ </jsv-smooth-swiper>
35
+ </div>
36
+ </template>
37
+ <script setup>
38
+ import { JsvSmoothSwiper, useFocusHub } from "jsview";
39
+ import { onMounted } from "vue";
40
+
41
+ const focusHub = useFocusHub();
42
+
43
+ const onEdge = (event) => {
44
+ console.log("onEdge", event);
45
+ };
46
+
47
+ onMounted(() => {
48
+ focusHub.setFocus("smooth-swiper");
49
+ });
50
+ </script>
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <div :style="{ width: 1280, height: 720, backgroundColor: '#F5F5DC' }"></div>
3
+ <jsv-focus-block autoFocus :onAction="{ onKeyDown }"></jsv-focus-block>
4
+ <div
5
+ :style="{
6
+ width: 1280,
7
+ height: 100,
8
+ lineHeight: 100,
9
+ textAlign: 'center',
10
+ fontSize: 40,
11
+ color: '#000000',
12
+ }"
13
+ >
14
+ 按OK键触发动画
15
+ </div>
16
+ <bounce
17
+ ref="bounceRef"
18
+ :src="iLeftSnake"
19
+ :layout="{
20
+ width: 320,
21
+ height: 320,
22
+ top: 400,
23
+ left: 400,
24
+ }"
25
+ />
26
+ <Sound :bgInfos="bgInfos" />
27
+ </template>
28
+
29
+ <script setup>
30
+ import Bounce from "./Bounce.vue";
31
+ import { shallowRef, provide } from "vue";
32
+ import { useSound, Sound } from "../Sound";
33
+ import bgUrl from "./bgmusic.mp3";
34
+ import coinUrl from "./coin.mp3";
35
+ const bgMap = {
36
+ bg: { url: bgUrl },
37
+ };
38
+ const sfxMap = {
39
+ bounce: coinUrl,
40
+ };
41
+ const { playSfx, playBg, pauseBg, bgInfos } = useSound(bgMap, sfxMap);
42
+ provide("playSfx", playSfx);
43
+
44
+ const bounceRef = shallowRef(null);
45
+ let iLeftSnake =
46
+ "https://cdn.release.qcast.cn/JsViewFrameworkTester/JsViewVueSampleResources/DemoForOperator/Bounce/App/snake_left.png?md5=e0310d4ba1c74899899ca365a8b16385";
47
+
48
+ function onKeyDown(ev) {
49
+ if (ev.keyCode == 13) {
50
+ bounceRef.value.start(-400, -400, 3);
51
+ playBg("bg");
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+ </script>
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <JsvFreeMoveActor
3
+ :top="layout.top"
4
+ :left="layout.left"
5
+ :width="layout.width"
6
+ :height="layout.height"
7
+ ref="actorRef"
8
+ >
9
+ <img
10
+ :src="src"
11
+ :style="{
12
+ width: layout.width,
13
+ height: layout.height,
14
+ }"
15
+ />
16
+ </JsvFreeMoveActor>
17
+ </template>
18
+
19
+ <script setup>
20
+ import { JsvFreeMoveActor } from "jsview";
21
+ import { shallowRef, inject } from "vue";
22
+ import { buildBounce } from "./FreeMoveBuilder";
23
+
24
+ const props = defineProps({
25
+ /**
26
+ * 图片资源路径
27
+ * @type {String}
28
+ * @required
29
+ * @example
30
+ * // 正确用法
31
+ * src: "/images/ball.png"
32
+ */
33
+ src: {
34
+ type: String,
35
+ required: true,
36
+ },
37
+
38
+ /**
39
+ * 布局配置对象
40
+ * @type {Object}
41
+ * @required
42
+ * @typedef {Object} LayoutConfig
43
+ * @property {number} top - 组件顶部位置(单位:px)
44
+ * @property {number} left - 组件左侧位置(单位:px)
45
+ * @property {number} width - 组件宽度(单位:px)
46
+ * @property {number} height - 组件高度(单位:px)
47
+ * @example
48
+ * // 正确配置示例
49
+ * { top: 100, left: 200, width: 50, height: 50 }
50
+ */
51
+ layout: {
52
+ type: Object,
53
+ required: true,
54
+ },
55
+ });
56
+
57
+ let actorRef = shallowRef(null);
58
+ let vLeftSnakeControl = null;
59
+ const playSfx = inject("playSfx");
60
+
61
+ /**
62
+ * 启动弹跳动画
63
+ * @param {number} left - 目标位置X坐标(单位:px)
64
+ * @param {number} top - 目标位置Y坐标(单位:px)
65
+ * @param {number} bounceTimes - 弹跳次数(建议1-5次)
66
+ * @description 调用此方法后组件会从当前位置向目标位置执行弹跳动画
67
+ * @example
68
+ * // 在(200,300)位置弹跳3次
69
+ * start(200, 300, 3)
70
+ */
71
+ function startSnakeAnim(left, top, bounceTimes) {
72
+ vLeftSnakeControl = actorRef.value.control;
73
+ vLeftSnakeControl.run((cmds) => [
74
+ ...buildBounce(cmds, 1, left, top, bounceTimes, 2.0, (state) => {
75
+ console.log("state", state);
76
+ }, () => {
77
+ console.log("onBounce");
78
+ playSfx("bounce");
79
+ }),
80
+ ]);
81
+ }
82
+
83
+ // 暴露给父组件的方法
84
+ defineExpose({
85
+ start: startSnakeAnim,
86
+ });
87
+ </script>
@@ -0,0 +1,146 @@
1
+ const SQRT2VAL = Math.sqrt(2)
2
+
3
+
4
+ // 获取原地起跳抛物的处理
5
+ function getParabola(
6
+ cmds,
7
+ condGroupId, // 后续改为specName
8
+ xSpeed,
9
+ ySpeed,
10
+ gravity,
11
+ times,
12
+ onLandCmds,
13
+ onBounceCbk,
14
+ ) {
15
+ let actCmds;
16
+ if (times > 0) {
17
+ actCmds = getParabola(
18
+ cmds,
19
+ condGroupId,
20
+ xSpeed,
21
+ ySpeed / SQRT2VAL,
22
+ gravity,
23
+ times - 1,
24
+ onLandCmds,
25
+ onBounceCbk,
26
+ );
27
+ } else {
28
+ actCmds = onLandCmds;
29
+ }
30
+ console.log("actCmds", actCmds);
31
+
32
+ return [
33
+ cmds.state().removeConditionByName(sFloorConditionName),
34
+ // (state: any) => {
35
+ // console.log(`State on t=${Date.now()} land y=${ySpeed} setStartOffsetPos times=${times}`,
36
+ // JSON.stringify(state))
37
+ // },
38
+ cmds.state().setStartPos(undefined, -1), // 离开接触点
39
+ cmds.action().setSpdAndAccel(xSpeed, ySpeed, 0, gravity),
40
+
41
+ // 下一帧再重启condition,避免当前帧的判断循环中仍然激活condition
42
+ cmds
43
+ .condition(condGroupId)
44
+ .onNextTick()
45
+ .then([
46
+ cmds
47
+ .condition(condGroupId, false, sFloorConditionName)
48
+ .reachPosition(undefined, 0)
49
+ .then([
50
+ ...actCmds,
51
+ onBounceCbk,
52
+ ]),
53
+ ]),
54
+ ];
55
+ }
56
+
57
+ const sFloorConditionName = "floorCond";
58
+ const sWallConditionName = "wallCond";
59
+
60
+ /*
61
+ 弹跳处理
62
+ */
63
+ export function buildBounce(
64
+ cmds,// FreeMove的cmds句柄
65
+ condGroupId,
66
+ startX, // 起始位置和目标位置的偏差, 单位px
67
+ startY, // 起始位置和目标位置的偏差, 单位px
68
+ times, // 整数,落点数(弹起次数-1)
69
+ gravity, // y轴的加速度, 建议设置成0.8
70
+ onEnd,
71
+ onBounceCbk, //每次落地的回调
72
+ ) {
73
+ //FIX onEnd回调在弹跳次数>=4时不会调用
74
+ let xDistance = startX - 0;
75
+ let yDistance = startY - 0;
76
+
77
+ if (times < 1) {
78
+ times = 1;
79
+ console.log("at least 1 times");
80
+ }
81
+
82
+ // 每个碰撞点之间的x的距离为
83
+ // sx * (1 + 1/sqrt(2) + 1/sqrt(2)^2 + ...) (=次数的数列)
84
+ // sx 为第一次下落过程x轴走过的距离
85
+ let sqrt2 = 1 / SQRT2VAL;
86
+ let sxSubBase = 2;
87
+ let sxSub = sxSubBase / 2;
88
+ for (let i = 0; i < times - 1; i++) {
89
+ sxSubBase = sxSubBase * sqrt2;
90
+ sxSub += sxSubBase;
91
+ }
92
+ let sx = -(xDistance / sxSub);
93
+
94
+ // 求首次下落使用的时间, 按照 s = 1/2*a*t^2的公式求解
95
+ let t1st = Math.sqrt(Math.abs(yDistance) * 2 / gravity);
96
+
97
+ // 求x的速度
98
+ let vx = sx / t1st;
99
+
100
+ // 求第一次落点的y速度
101
+ let vy1st = gravity * t1st;
102
+
103
+ let onLandCmds = [
104
+ cmds.action().teleportTo(0, 0),
105
+ // cmds.action().stopMoving(true),
106
+ cmds.state().removeConditionByGroup(condGroupId),
107
+ (...args) => {
108
+ onEnd?.(...args);
109
+ },
110
+ ];
111
+
112
+ let parabolaCmds;
113
+ if (times > 1) {
114
+ // 递归创建所有运动处理
115
+ parabolaCmds = getParabola(cmds, condGroupId, vx, -vy1st / SQRT2VAL, gravity, times - 2, onLandCmds, onBounceCbk);
116
+ } else {
117
+ parabolaCmds = onLandCmds;
118
+ }
119
+
120
+ let wallname = xDistance > 0 ? "left" : "right";
121
+
122
+ let cmdsArray = [
123
+ // 清理掉所有condition,除了group的外,还有wallposition
124
+ // 但后续specName的bug修正后,可以用specName来控制动画,只清理group即可
125
+ cmds.state().removeConditionByGroup(condGroupId),
126
+
127
+ // wallPosition用于规避运动路程计算超出(times越大超出越多)时,解决动画结尾的回弹问题
128
+ cmds.condition(condGroupId, true, sWallConditionName).wallPosition(wallname, 0, undefined).then([
129
+ cmds.action().teleportTo(0, undefined),
130
+ cmds.action().setSpdAndAccel(0, undefined, undefined, undefined),
131
+ ]),
132
+
133
+ // 启动从起始点的抛物下落动画
134
+ cmds.state().setStartPos(startX, startY),
135
+ cmds.action().setSpdAndAccel(vx, 0, 0, gravity),
136
+ cmds
137
+ .condition(condGroupId, false, sFloorConditionName)
138
+ .reachPosition(undefined, 0)
139
+ .then([
140
+ ...parabolaCmds,
141
+ onBounceCbk,
142
+ ])
143
+ ];
144
+
145
+ return cmdsArray;
146
+ }
@@ -0,0 +1,134 @@
1
+ <!--
2
+ * @Author: ChenChanghua
3
+ * @Date: 2023-03-08 14:52:08
4
+ * @Description: file content
5
+ -->
6
+ <script setup>
7
+ import { MetroWidget, VERTICAL, useFocusHub, SeamlessSlide } from "jsview";
8
+ import Item from "./Item.vue";
9
+ import { onMounted, shallowRef } from "vue";
10
+ import { useSound, Sound } from "../Sound";
11
+ import moveSound from "./move.mp3";
12
+
13
+ const TAG = "MetroWidgetDemo";
14
+
15
+ const focusHub = useFocusHub();
16
+
17
+ const randomColor = () => {
18
+ let randomColor = Math.round(Math.random() * 2 ** 24).toString(16);
19
+ return (
20
+ "#" + new Array(6 - randomColor.length).fill("0").join("") + randomColor
21
+ );
22
+ };
23
+
24
+ const provideData = () => {
25
+ const data = [];
26
+
27
+ for (let i = 0; i < 200; i++) {
28
+ data.push({
29
+ width: 180,
30
+ height: 270,
31
+ marginRight: 10,
32
+ marginBottom: 10,
33
+ color: randomColor(),
34
+ content: i,
35
+ });
36
+ }
37
+ return data;
38
+ };
39
+
40
+ const measures = (data) => {
41
+ return {
42
+ width: data.width,
43
+ height: data.height,
44
+ marginRight: data.marginRight,
45
+ marginBottom: data.marginBottom,
46
+ };
47
+ };
48
+
49
+ // callbacks
50
+ const onEdge = (edgeInfo) => {
51
+ console.log(TAG, "onEdge", edgeInfo);
52
+ };
53
+
54
+ const onFocus = () => {
55
+ console.log(TAG, "onFocus");
56
+ };
57
+
58
+ const onBlur = () => {
59
+ console.log(TAG, "onBlur");
60
+ };
61
+
62
+ const onScroll = (start, range, totalSize) => {
63
+ console.log(TAG, "onScroll", start, range, totalSize);
64
+ };
65
+
66
+ const widgetLayout = {
67
+ left: 50,
68
+ top: 50,
69
+ width: 1000,
70
+ height: 600,
71
+ };
72
+
73
+ onMounted(() => {
74
+ //组件mount后设置焦点
75
+ focusHub.setFocus("mainMw");
76
+ });
77
+
78
+ const { playSfx } = useSound(
79
+ null,
80
+ {
81
+ move: moveSound,
82
+ },
83
+ true
84
+ );
85
+
86
+ const onDispatchKeyDown = (ev) => {
87
+ if (
88
+ ev.keyCode == 37 ||
89
+ ev.keyCode == 39 ||
90
+ ev.keyCode == 38 ||
91
+ ev.keyCode == 40
92
+ ) {
93
+ playSfx("move");
94
+ }
95
+ return false;
96
+ };
97
+
98
+ const slideSetting = new SeamlessSlide({
99
+ // easing: "cubic-bezier(.42,.11,.43,.91)",
100
+ easing: "jsv-ease(0.2, 0.6, 1.5)",
101
+ speed: 0.85,
102
+ });
103
+ </script>
104
+
105
+ <template>
106
+ <div
107
+ :style="{
108
+ width: 1920,
109
+ height: 1080,
110
+ backgroundColor: '#007788',
111
+ }"
112
+ />
113
+ <jsv-focus-block :onAction="{ onDispatchKeyDown }">
114
+ <metro-widget
115
+ name="mainMw"
116
+ :left="widgetLayout.left"
117
+ :top="widgetLayout.top"
118
+ :width="widgetLayout.width"
119
+ :height="widgetLayout.height"
120
+ :provideData="provideData"
121
+ :direction="VERTICAL"
122
+ :measures="measures"
123
+ :onEdge="onEdge"
124
+ :onFocus="onFocus"
125
+ :onBlur="onBlur"
126
+ :onScroll="onScroll"
127
+ :slideSetting="slideSetting"
128
+ >
129
+ <template #renderItem="{ data, onAction }">
130
+ <item :data="data" :onAction="onAction" />
131
+ </template>
132
+ </metro-widget>
133
+ </jsv-focus-block>
134
+ </template>
@@ -0,0 +1,43 @@
1
+ <!--
2
+ * @Author: ChenChanghua
3
+ * @Date: 2023-03-08 14:52:17
4
+ * @Description: file content
5
+ -->
6
+ <script setup>
7
+ import { ref } from "vue";
8
+
9
+ const props = defineProps({
10
+ data: Object,
11
+ onAction: Object,
12
+ });
13
+
14
+ const focused = ref(false);
15
+
16
+ // 注册回调
17
+ const onFocus = () => {
18
+ focused.value = true;
19
+ };
20
+ const onBlur = () => {
21
+ focused.value = false;
22
+ };
23
+ const onClick = () => {
24
+ console.log("item onclick ", props.data);
25
+ };
26
+ props.onAction.register("onFocus", onFocus);
27
+ props.onAction.register("onBlur", onBlur);
28
+ props.onAction.register("onClick", onClick);
29
+ </script>
30
+
31
+ <template>
32
+ <div
33
+ :style="{
34
+ width: data.width,
35
+ height: data.height,
36
+ fontSize: 30,
37
+ color: focused ? '#FF0000' : '#FFFFFF',
38
+ backgroundColor: data.color,
39
+ }"
40
+ >
41
+ {{ data.content }}
42
+ </div>
43
+ </template>
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <RainScene></RainScene>
3
+ </template>
4
+
5
+ <script setup>
6
+ import RainScene from "./Raining/RainScene.vue"
7
+ </script>
8
+
9
+ <style scoped>
10
+
11
+ </style>