@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,113 @@
1
+ <script setup>
2
+ import { shallowRef } from "vue";
3
+ import Blur, { captureBlurTexture } from "../Blur.vue";
4
+
5
+ const vToCapture = shallowRef(null);
6
+ const vTextureInfo = shallowRef(null);
7
+
8
+ function enableBlur() {
9
+ captureBlurTexture(vToCapture.value, 12).then((textureInfo) => {
10
+ vTextureInfo.value = textureInfo;
11
+ });
12
+ }
13
+
14
+ const _onKeyDown = (ev) => {
15
+ if (ev.keyCode == 13) {
16
+ enableBlur();
17
+ return true;
18
+ }
19
+ };
20
+
21
+ const popupViewLayout = {
22
+ left: (1280 - 400) / 2,
23
+ top: 100,
24
+ width: 400,
25
+ height: 400,
26
+ };
27
+ </script>
28
+
29
+ <template>
30
+ <jsv-focus-block
31
+ autoFocus
32
+ :onAction="{
33
+ onKeyDown: _onKeyDown,
34
+ }"
35
+ >
36
+ <div
37
+ ref="vToCapture"
38
+ :style="{
39
+ width: 1280, // 截屏区域的宽
40
+ height: 720, // 截屏区域的高
41
+ }"
42
+ >
43
+ <div
44
+ :style="{
45
+ width: 1280,
46
+ height: 720,
47
+ backgroundImage: `url(https://cdn.release.qcast.cn/JsViewFrameworkTester/JsViewVueSampleResources/DemoHomepage/App/BackgroundLongmao.jpg)`,
48
+ }"
49
+ />
50
+ <div
51
+ :style="{
52
+ top: 300,
53
+ width: 1280,
54
+ height: 100,
55
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
56
+ color: '#ffffff',
57
+ fontSize: 40,
58
+ textAlign: 'center',
59
+ }"
60
+ >
61
+ 按OK键弹出带模糊背景的框
62
+ </div>
63
+ </div>
64
+
65
+ <div
66
+ v-if="vTextureInfo"
67
+ :style="{
68
+ left: popupViewLayout.left,
69
+ top: popupViewLayout.top,
70
+ }"
71
+ >
72
+ <blur
73
+ :textureInfo="vTextureInfo"
74
+ :layout="{
75
+ left: 0,
76
+ top: 0,
77
+ width: popupViewLayout.width,
78
+ height: popupViewLayout.height,
79
+ }"
80
+ :showRectPos="{
81
+ left: popupViewLayout.left,
82
+ top: popupViewLayout.top,
83
+ }"
84
+ :borderRadius="30"
85
+ />
86
+ <div
87
+ :style="{
88
+ width: popupViewLayout.width,
89
+ height: popupViewLayout.height,
90
+ backgroundColor: 'rgba(0, 0, 0, 0.3)',
91
+ borderRadius: 30,
92
+ lineHeight: popupViewLayout.height,
93
+ textAlign: 'center',
94
+ color: '#ffffff',
95
+ fontSize: 40,
96
+ }"
97
+ >
98
+ 弹窗内容
99
+ </div>
100
+ </div>
101
+ </jsv-focus-block>
102
+ </template>
103
+
104
+ <style>
105
+ @keyframes rotate {
106
+ 0% {
107
+ transform: rotate3d(0, 0, 1, 0deg);
108
+ }
109
+ 100% {
110
+ transform: rotate3d(0, 0, 1, 360deg);
111
+ }
112
+ }
113
+ </style>
@@ -0,0 +1,115 @@
1
+ <template>
2
+ <div>
3
+ <FlippingBook
4
+ :page-count="totalPages"
5
+ :position="position"
6
+ :page-size="pageSize"
7
+ ref="bookFlipRef"
8
+ >
9
+ <template #default="{ pageIndex, triggerFlush }">
10
+ <BookPage
11
+ :width="pageSize.width"
12
+ :height="pageSize.height"
13
+ :index="pageIndex"
14
+ :flushTrigger="triggerFlush"
15
+ />
16
+ </template>
17
+ </FlippingBook>
18
+
19
+ <div :style="{ top: 650 }">
20
+ <JsvFocusBlock :autoFocus="true" :onKeyDown="handleKeyDown">
21
+ <div
22
+ class="page-info"
23
+ :style="{
24
+ top: -40,
25
+ left: 400,
26
+ height: 50,
27
+ width: 480,
28
+ lineHeight: 50,
29
+ textAlign: 'center',
30
+ color: '#FFFFFF',
31
+ }"
32
+ >
33
+ 左右键进行翻页
34
+ </div>
35
+ <div
36
+ class="page-info"
37
+ :style="{
38
+ left: 400,
39
+ height: 50,
40
+ width: 480,
41
+ lineHeight: 50,
42
+ textAlign: 'center',
43
+ color: '#FF0000',
44
+ }"
45
+ >
46
+ 当前页: {{ currentPage + 1 }} / {{ totalPages }}
47
+ </div>
48
+ </JsvFocusBlock>
49
+ </div>
50
+ </div>
51
+ </template>
52
+
53
+ <script setup>
54
+ import { ref } from "vue";
55
+ import FlippingBook from "./BookFlip/FlippingBook.vue";
56
+ import BookPage from "./BookPage.vue";
57
+ import { JsvFocusBlock } from "jsview";
58
+
59
+ // 配置参数
60
+ const totalPages = 8;
61
+ const pageSize = {
62
+ width: 980,
63
+ height: 500,
64
+ };
65
+ const position = {
66
+ x: 150,
67
+ y: 100,
68
+ };
69
+
70
+ // 组件引用和状态
71
+ const bookFlipRef = ref(null);
72
+ const currentPage = ref(0);
73
+
74
+ // 翻页方法
75
+ const nextPage = () => {
76
+ if (currentPage.value < totalPages - 1) {
77
+ currentPage.value++;
78
+ bookFlipRef.value.setCurrentPage(currentPage.value);
79
+ }
80
+ };
81
+
82
+ const prevPage = () => {
83
+ if (currentPage.value > 0) {
84
+ currentPage.value--;
85
+ bookFlipRef.value.setCurrentPage(currentPage.value);
86
+ }
87
+ };
88
+
89
+ // 按键处理
90
+ const handleKeyDown = (event) => {
91
+ switch (event.keyCode) {
92
+ case 37: // 左键的keyCode
93
+ prevPage();
94
+ return true;
95
+ case 39: // 右键的keyCode
96
+ nextPage();
97
+ return true;
98
+ default:
99
+ return false;
100
+ }
101
+ };
102
+ </script>
103
+
104
+ <style scoped>
105
+ .control-btn {
106
+ font-size: 30;
107
+ background-color: rgba(76, 175, 80, 1);
108
+ color: rgba(128, 255, 255, 1);
109
+ border-radius: 4;
110
+ }
111
+
112
+ .page-info {
113
+ font-size: 30;
114
+ }
115
+ </style>
@@ -0,0 +1,179 @@
1
+ <script setup>
2
+ import { ref, computed } from "vue";
3
+ import { JsvFragShaderView, JsvPreload, buildPreloadInfo } from "jsview";
4
+ import pageFlipShader from "./flip.glsl?raw";
5
+
6
+ // 定义组件的 props
7
+ const props = defineProps({
8
+ // 第一张图片资源
9
+ imageFrom: {
10
+ type: String,
11
+ required: true,
12
+ },
13
+ // 第二张图片资源
14
+ imageTo: {
15
+ type: String,
16
+ required: true,
17
+ },
18
+ // 初始页
19
+ initPage: {
20
+ type: String,
21
+ default: "from",
22
+ },
23
+ // 动画持续时间
24
+ duration: {
25
+ type: Number,
26
+ default: 3000,
27
+ },
28
+ // 宽度
29
+ width: {
30
+ type: Number,
31
+ default: 1280,
32
+ },
33
+ // 高度
34
+ height: {
35
+ type: Number,
36
+ default: 720,
37
+ },
38
+ // 书本范围, 单位为组件的百分比
39
+ bookRect: {
40
+ type: Object,
41
+ default: () => ({
42
+ left: 0.15,
43
+ top: 0.05,
44
+ right: 0.85,
45
+ bottom: 0.95,
46
+ }),
47
+ validator: (value) => {
48
+ return (
49
+ value.left >= 0 &&
50
+ value.top >= 0 &&
51
+ value.right <= 1 &&
52
+ value.bottom <= 1
53
+ );
54
+ },
55
+ },
56
+ });
57
+
58
+ // 定义事件
59
+ const emit = defineEmits(["animEnd"]);
60
+
61
+ const curPage = ref(props.initPage == "to" ? 1 : 0); // 0: from, 1: to
62
+ const rShowImg = ref(true);
63
+ let duringAnim = false;
64
+ const rImgUrl = computed(() => {
65
+ return curPage.value == 0 ? props.imageFrom : props.imageTo;
66
+ });
67
+
68
+ const rImgLayout = computed(() => {
69
+ const cBookRect = props.bookRect;
70
+ return {
71
+ left: cBookRect.left * props.width,
72
+ top: cBookRect.top * props.height,
73
+ width: (cBookRect.right - cBookRect.left) * props.width,
74
+ height: (cBookRect.bottom - cBookRect.top) * props.height,
75
+ };
76
+ });
77
+
78
+ // 修改着色器代码,替换书籍范围常量
79
+ const rModifiedShader = computed(() => {
80
+ // 替换着色器中的 BOOK_BOUND 定义
81
+ return pageFlipShader.replace(
82
+ "#define BOOK_BOUND vec4(0.15, 0.05, 0.85, 0.95)",
83
+ `#define BOOK_BOUND vec4(${props.bookRect.left.toFixed(6)}, ${
84
+ 1 - props.bookRect.bottom.toFixed(6)
85
+ }, ${props.bookRect.right.toFixed(6)}, ${
86
+ 1 - props.bookRect.top.toFixed(6)
87
+ })`
88
+ );
89
+ });
90
+
91
+ const rPageFlipSettings = computed(() => {
92
+ return {
93
+ name: "pageFlip",
94
+ shader: rModifiedShader.value,
95
+ uniforms: [],
96
+ textures: [
97
+ {
98
+ name: "iChannel0",
99
+ resource: props.imageFrom,
100
+ },
101
+ {
102
+ name: "iChannel1",
103
+ resource: props.imageTo,
104
+ },
105
+ ],
106
+ duration: props.duration,
107
+ onEnd: (id, cStatus) => {
108
+ emit("animEnd", cStatus);
109
+
110
+ curPage.value = curPage.value == 0 ? 1 : 0;
111
+ rShowImg.value = true;
112
+ duringAnim = false;
113
+ },
114
+ };
115
+ });
116
+
117
+ const rWidgetRef = ref();
118
+ const rIsPreloadDone = ref(false);
119
+ let vPendingAnim = false;
120
+
121
+ const rPreloadList = computed(() => {
122
+ return [buildPreloadInfo(props.imageFrom), buildPreloadInfo(props.imageTo)];
123
+ });
124
+
125
+ const handlePreloadDone = () => {
126
+ console.log("图片预加载完成");
127
+ rIsPreloadDone.value = true;
128
+ if (vPendingAnim) {
129
+ _startAnim();
130
+ vPendingAnim = false;
131
+ }
132
+ };
133
+
134
+ // 内部实际执行动画的方法
135
+ const _startAnim = (reverse = false) => {
136
+ console.log("开始翻页动画", reverse);
137
+ duringAnim = true;
138
+ rShowImg.value = false;
139
+ rWidgetRef.value?.startAnim(undefined, undefined, reverse);
140
+ };
141
+
142
+ // 暴露组件方法给父组件
143
+ defineExpose({
144
+ /**
145
+ * 翻页
146
+ */
147
+ flip: () => {
148
+ if (duringAnim) {
149
+ return;
150
+ }
151
+ if (rIsPreloadDone.value) {
152
+ _startAnim(curPage.value == 1);
153
+ } else {
154
+ vPendingAnim = true;
155
+ }
156
+ },
157
+ getCurPage: () => {
158
+ return curPage == 0 ? "from" : "to";
159
+ },
160
+ });
161
+ </script>
162
+
163
+ <template>
164
+ <jsv-preload
165
+ :preloadList="rPreloadList"
166
+ :onPreloadDone="handlePreloadDone"
167
+ ></jsv-preload>
168
+ <jsv-frag-shader-view
169
+ ref="rWidgetRef"
170
+ :style="{ left: 0, top: 0, width: width, height: height }"
171
+ :duration="rPageFlipSettings.duration"
172
+ :shaderStr="rPageFlipSettings.shader"
173
+ :autoplay="false"
174
+ :textures="rPageFlipSettings.textures"
175
+ :onEnd="rPageFlipSettings.onEnd"
176
+ :hideAfterEnd="false"
177
+ ></jsv-frag-shader-view>
178
+ <img v-if="rShowImg" :src="rImgUrl" :style="rImgLayout" />
179
+ </template>
@@ -0,0 +1,310 @@
1
+ <script>
2
+ import { JsvTextureStoreApi } from "jsview";
3
+
4
+ const FLIP_STATUS_IDLE = 0;
5
+ const FLIP_STATUS_WAIT_DIV_READY = 1;
6
+ const FLIP_STATUS_TAKING = 2;
7
+ const FLIP_STATUS_READY = 3;
8
+
9
+ function takeTexture(pageDivRef, pageIndex) {
10
+ // 抓取界面
11
+ let holder = {
12
+ promiseRef: null,
13
+ textureRef: null,
14
+ };
15
+
16
+ holder.promiseRef = new Promise((resolve, reject) => {
17
+ holder.textureRef = JsvTextureStoreApi.capture2Texture(
18
+ pageDivRef,
19
+ (textureAccessName) => {
20
+ if (textureAccessName != "") {
21
+ resolve(textureAccessName);
22
+ } else {
23
+ reject();
24
+ }
25
+ }
26
+ );
27
+ });
28
+ return holder;
29
+ }
30
+ </script>
31
+
32
+ <script setup>
33
+ import { computed, shallowRef, onUnmounted, onMounted, reactive } from "vue";
34
+ import pageFlipShader from "./flip.glsl?raw";
35
+ import { JsvFragShaderView } from "jsview";
36
+
37
+ // 定义组件的 props
38
+ const props = defineProps({
39
+ // 页面总数
40
+ pageCount: {
41
+ type: Number,
42
+ default: 2,
43
+ },
44
+
45
+ // 初始化时显示的页面索引
46
+ initPageIndex: {
47
+ type: Number,
48
+ default: 0,
49
+ },
50
+
51
+ // 组件的坐标 x,y
52
+ position: {
53
+ type: Object,
54
+ default: () => ({
55
+ x: 0,
56
+ y: 0,
57
+ }),
58
+ validator: (value) => {
59
+ return !isNaN(value.x) && !isNaN(value.y);
60
+ },
61
+ },
62
+
63
+ // page的width,height
64
+ pageSize: {
65
+ type: Object,
66
+ required: true,
67
+ validator: (value) => {
68
+ return !isNaN(value.width) && !isNaN(value.height);
69
+ },
70
+ },
71
+
72
+ // 动画持续时间
73
+ duration: {
74
+ type: Number,
75
+ default: 600,
76
+ },
77
+ });
78
+
79
+ const cFlipArea = {
80
+ width: Math.ceil(props.pageSize.width / 1.0),
81
+ height: Math.ceil(props.pageSize.height / 0.8),
82
+ x: 0,
83
+ y: 0,
84
+ };
85
+ // cFlipArea.x = Math.ceil((props.pageSize.width - cFlipArea.width) / 2); // 翻页区域对齐原div区域
86
+ // cFlipArea.y = Math.ceil((props.pageSize.height - cFlipArea.height) / 2); // 翻页区域对齐原div区域
87
+
88
+ // 创建rPageList数据,内容为shallowRef(null)
89
+ const rPageList = Array(props.pageCount)
90
+ .fill()
91
+ .map((_, idx) => ({
92
+ index: idx,
93
+ divRef: null,
94
+ pageReady: false,
95
+ }));
96
+
97
+ const rPageLives = reactive([props.initPageIndex, -1]);
98
+
99
+ const rCurrentPageIndex = shallowRef(props.initPageIndex);
100
+
101
+ const rPrevPageIndex = shallowRef(-1);
102
+
103
+ // fragShaderView的Texture管理
104
+ const rTextureStatus = shallowRef(FLIP_STATUS_IDLE);
105
+ const rTextureNames = [shallowRef(null), shallowRef(null)];
106
+ let vTextureHolder = {
107
+ holder0: null,
108
+ holder1: null,
109
+ token: 0,
110
+ };
111
+ let vTexturePromiseAll = null;
112
+
113
+ const rPageFlipSettings = computed(() => {
114
+ return {
115
+ name: "pageFlip",
116
+ shader: pageFlipShader,
117
+ uniforms: [],
118
+ textures: [
119
+ {
120
+ name: "iChannel0",
121
+ resource: "jsvtexturestore://" + rTextureNames[1].value,
122
+ },
123
+ {
124
+ name: "iChannel1",
125
+ resource: "jsvtexturestore://" + rTextureNames[0].value,
126
+ },
127
+ ],
128
+ duration: props.duration,
129
+ onEnd: (end_or_cancel) => {
130
+ // 结束动画, 以触发prev页面的销毁
131
+ if (rTextureStatus.value == FLIP_STATUS_READY) {
132
+ // 非开新界面时,结束动画后,恢复到空闲状态
133
+ rTextureStatus.value = FLIP_STATUS_IDLE;
134
+ }
135
+ },
136
+ };
137
+ });
138
+
139
+ // 新进界面触发flush处理,第一个flush传来后才启动动画
140
+ const fncTriggerFlush = (pageIndex) => {
141
+ rPageList[pageIndex].pageReady = true;
142
+
143
+ // prev和current的page都ready了就启动翻页动画
144
+ if (
145
+ rTextureStatus.value == FLIP_STATUS_WAIT_DIV_READY &&
146
+ rPageList[rPrevPageIndex.value].pageReady &&
147
+ rPageList[rCurrentPageIndex.value].pageReady
148
+ ) {
149
+ // 抓取界面
150
+
151
+ // 取消上一次的抓取
152
+ vTextureHolder.holder0?.textureRef.cancel();
153
+ vTextureHolder.holder1?.textureRef.cancel();
154
+
155
+ // 抓取当前界面
156
+ rTextureStatus.value = FLIP_STATUS_TAKING;
157
+
158
+ vTextureHolder = {
159
+ holder0: takeTexture(
160
+ rPageList[rPageLives[0]].divRef,
161
+ rPageList[rPageLives[0]].index
162
+ ),
163
+ holder1: takeTexture(
164
+ rPageList[rPageLives[1]].divRef,
165
+ rPageList[rPageLives[1]].index
166
+ ),
167
+ };
168
+
169
+ let holders = vTextureHolder;
170
+
171
+ // TODO: promise.all的引用和unmount时释放, 可能可以规避组件退出时内存泄露问题
172
+ vTexturePromiseAll = Promise.all([
173
+ holders.holder0.promiseRef,
174
+ holders.holder1.promiseRef,
175
+ ])
176
+ .then(([page_0_texture, page_1_texture]) => {
177
+ if (rCurrentPageIndex.value > rPrevPageIndex.value) {
178
+ rTextureNames[0].value = page_0_texture;
179
+ rTextureNames[1].value = page_1_texture;
180
+ } else {
181
+ rTextureNames[0].value = page_1_texture;
182
+ rTextureNames[1].value = page_0_texture;
183
+ }
184
+ rTextureStatus.value = FLIP_STATUS_READY;
185
+ })
186
+ .finally(() => {
187
+ // resolve或者reject时,释放holder引用
188
+ holders.holder0 = null;
189
+ holders.holder1 = null;
190
+ });
191
+ }
192
+ };
193
+
194
+ // 暴露组件方法给父组件
195
+ defineExpose({
196
+ /**
197
+ * 设置当前页码
198
+ * @param {number} pageIndex - 要设置的页码索引
199
+ */
200
+ setCurrentPage: (pageIndex) => {
201
+ if (pageIndex < 0 || pageIndex >= props.pageCount) {
202
+ console.error(`页码超出范围: ${pageIndex}, 总页数: ${props.pageCount}`);
203
+ return;
204
+ }
205
+
206
+ if (pageIndex == rCurrentPageIndex.value) {
207
+ // 如果当前页码和要设置的页码相同,则不进行操作
208
+ return;
209
+ }
210
+
211
+ // 更新页码索引
212
+ // 保存旧的当前页码
213
+ const oldCurrentIndex = rCurrentPageIndex.value;
214
+
215
+ if (
216
+ rTextureStatus.value != FLIP_STATUS_IDLE &&
217
+ pageIndex == rPrevPageIndex.value &&
218
+ rPageList[pageIndex].pageReady
219
+ ) {
220
+ // 在动画过程中,翻页反向,此时由于页面不重新mount,不会触发fncTriggerFlush
221
+ // 需要手动触发fncTriggerFlush
222
+ Promise.resolve().then(() => {
223
+ fncTriggerFlush(pageIndex);
224
+ });
225
+ }
226
+
227
+ // 设置当前页码
228
+ rCurrentPageIndex.value = pageIndex;
229
+ rPrevPageIndex.value = oldCurrentIndex;
230
+
231
+ // 界面进入动画状态
232
+ rTextureStatus.value = FLIP_STATUS_WAIT_DIV_READY;
233
+
234
+ // 设置新页面为未准备就绪
235
+ rPageList[pageIndex].pageReady = false;
236
+
237
+ rPageLives[0] = pageIndex;
238
+ rPageLives[1] = oldCurrentIndex; // 老页面遮挡在上面
239
+ },
240
+ });
241
+
242
+ onMounted(() => {});
243
+
244
+ onUnmounted(() => {
245
+ // 取消截屏处理,并释放promise引用
246
+ vTextureHolder.holder0?.textureRef.cancel();
247
+ vTextureHolder.holder1?.textureRef.cancel();
248
+ vTextureHolder.holder0 = null;
249
+ vTextureHolder.holder1 = null;
250
+
251
+ // 释放PromiseAll引用
252
+ vTexturePromiseAll = null;
253
+ });
254
+ </script>
255
+
256
+ <template>
257
+ <div
258
+ :style="{
259
+ left: props.position.x,
260
+ top: props.position.y,
261
+ }"
262
+ >
263
+ <!-- 通过key锁定, 当 currentPageIndex 变化时,已存在页面不会重新创建 -->
264
+ <div
265
+ v-show="rTextureStatus != FLIP_STATUS_READY"
266
+ v-for="pageIndex in rPageLives"
267
+ :key="pageIndex"
268
+ >
269
+ <div
270
+ v-if="
271
+ pageIndex == rCurrentPageIndex || rTextureStatus != FLIP_STATUS_IDLE
272
+ "
273
+ :ref="(el) => (rPageList[pageIndex].divRef = el)"
274
+ :style="{
275
+ width: props.pageSize.width,
276
+ height: props.pageSize.height,
277
+ }"
278
+ >
279
+ <slot :pageIndex="pageIndex" :triggerFlush="fncTriggerFlush"></slot>
280
+ </div>
281
+ <!-- <div
282
+ :style="{
283
+ width: 300,
284
+ height: 100,
285
+ fontSize: 20,
286
+ color: 'rgba(255,255,255,1)',
287
+ lineHeight: 100,
288
+ }"
289
+ >
290
+ 当前界面: {{ "" + pageIndex + " " + rCurrentPageIndex }}
291
+ </div> -->
292
+ </div>
293
+
294
+ <jsv-frag-shader-view
295
+ v-if="rTextureStatus == FLIP_STATUS_READY"
296
+ :style="{
297
+ left: cFlipArea.x,
298
+ top: cFlipArea.y,
299
+ width: cFlipArea.width,
300
+ height: cFlipArea.height,
301
+ }"
302
+ :duration="rPageFlipSettings.duration"
303
+ :shaderStr="rPageFlipSettings.shader"
304
+ :autoplay="true"
305
+ :reverseAnimate="rCurrentPageIndex < rPrevPageIndex"
306
+ :textures="rPageFlipSettings.textures"
307
+ :onEnd="rPageFlipSettings.onEnd"
308
+ ></jsv-frag-shader-view>
309
+ </div>
310
+ </template>