@shijiu/jsview-vue-samples 2.2.128 → 2.2.373
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.
- package/BakeViewDemo/App.vue +6 -1
- package/Basic/components/anim/AnimEasingCubicBezier.vue +56 -0
- package/Basic/components/anim/AnimGroup2.vue +33 -0
- package/Basic/components/panel/Panel2.vue +8 -3
- package/CoupletsTest/widget/Banger/Maroon.vue +4 -7
- package/CoupletsTest/widget/Fireworks/Fireworks.vue +52 -44
- package/CustomShader/App.vue +174 -0
- package/CustomShader/gaussianBlur.glsl +27 -0
- package/CustomShader/pageFlip.glsl +41 -0
- package/CustomShader/sdf.glsl +22 -0
- package/CustomShader/test.glsl +8 -0
- package/CustomShader/vortex.glsl +38 -0
- package/DemoHomepage/App.vue +50 -32
- package/DemoHomepage/components/Item.vue +23 -12
- package/DemoHomepage/index.d.ts +5 -2
- package/DemoHomepage/router.js +105 -72
- package/DispersedFocusControl/App.vue +67 -0
- package/DispersedFocusControl/Button.vue +76 -0
- package/DispersedFocusControl/data.js +44 -0
- package/DragBox/App.vue +148 -0
- package/DriftScopeTest/App.vue +128 -0
- package/FlexCellDemo/App.vue +47 -223
- package/FlexCellDemo/TestFrame1.vue +88 -0
- package/FlexCellDemo/TestFrame2.vue +100 -0
- package/FlexCellDemo/TestFrame3.vue +97 -0
- package/FlexCellDemo/TestFrame4.vue +60 -0
- package/FlexCellDemo/TestFrame5.vue +60 -0
- package/FlexCellDemo/images/6.jpg +0 -0
- package/FocusMoveStyle/App.vue +1 -0
- package/FocusMoveStyle/CreepFocus.vue +11 -1
- package/FocusMoveStyle/FoldableItem.vue +1 -1
- package/FreeMove/App.vue +62 -64
- package/FreeMoveLink/App.vue +2 -2
- package/FullScreenFlex/App.vue +42 -0
- package/FullScreenFlex/TestFrame2.vue +107 -0
- package/FullScreenFlex/images/1.png +0 -0
- package/HashHistory/App.vue +8 -4
- package/ImpactStop/App.vue +45 -45
- package/Input/App.vue +184 -97
- package/Input/InputPanel.vue +98 -82
- package/LatexFormula/App.vue +97 -10
- package/LongImage/App.vue +1 -2
- package/LongText/App.vue +2 -2
- package/LongText/LongTextScroll.vue +22 -22
- package/LongText/Scroll.vue +28 -9
- package/MetroWidgetDemos/RefreshDemo/App.vue +172 -56
- package/MetroWidgetDemos/RefreshDemo/ControlItem.vue +45 -0
- package/MetroWidgetDemos/RefreshDemo/Item.vue +20 -4
- package/MetroWidgetDemos/itemSizeUpdate/backward/Item.vue +1 -1
- package/MetroWidgetDemos/routeList.js +17 -17
- package/MindMap/App.vue +10 -1
- package/MindMap/data.js +34 -8
- package/Parkour/appConfig/jsview.config.mjs +0 -4
- package/PosterPacker/App.vue +207 -0
- package/PosterPacker/images/bg.jpg +0 -0
- package/PosterPacker/images/blue.png +0 -0
- package/PosterPacker/images/darkGreen.png +0 -0
- package/PosterPacker/images/left.png +0 -0
- package/PosterPacker/images/orange.png +0 -0
- package/PosterPacker/images/pink.png +0 -0
- package/PosterPacker/images/purple.png +0 -0
- package/PosterPacker/images/red.png +0 -0
- package/PosterPacker/images/right.png +0 -0
- package/PosterPacker/images/yellowGreen.png +0 -0
- package/PosterPacker/tools/geniePakcer/Genie.vue +686 -0
- package/PosterPacker/tools/geniePakcer/genieBottom.glsl +49 -0
- package/PosterPacker/tools/geniePakcer/genieLeft.glsl +50 -0
- package/PosterPacker/tools/geniePakcer/genieRight.glsl +57 -0
- package/PosterPacker/tools/geniePakcer/genieTop.glsl +50 -0
- package/PosterPacker/tools/particlePacker/Particle.vue +71 -0
- package/PosterPacker/tools/vortexPacker/Vortex.vue +135 -0
- package/PosterPacker/tools/vortexPacker/vortex.glsl +37 -0
- package/Preload/App.vue +1 -1
- package/SceneTransition/JsvSceneTransition.vue +30 -42
- package/ScrollBoxTest/App.vue +35 -86
- package/ScrollBoxTest/ClipBar.vue +154 -0
- package/ScrollBoxTest/DrawCircle.ts +25 -0
- package/ScrollBoxTest/NinePatchBar.vue +188 -0
- package/ScrollBoxTest/NoBackgroundBar.vue +125 -0
- package/ScrollBoxTest/SizeDivBar.vue +139 -0
- package/SprayMove/App.vue +75 -0
- package/SprayMove/SprayMove.vue +173 -0
- package/SprayView/App.vue +8 -9
- package/TestNativeSharedView/App.vue +6 -4
- package/TextShadowDemo/App.vue +3 -3
- package/TextureAnimation/App.vue +244 -148
- package/TextureAnimation/App2.vue +66 -14
- package/TextureAnimation/assets/blackWhiteTurntable.png +0 -0
- package/TextureAnimation/assets/circleHaloMask.png +0 -0
- package/TombSweepingDayTest/Raining/Rain.vue +8 -8
- package/TouchWidget/App.vue +79 -40
- package/TouchWidget/Item.vue +15 -3
- package/index.d.ts +1 -1
- package/package.json +1 -1
- package/MetroWidgetDemos/RefreshDemo/data.js +0 -16
- package/TextureAnimation/assets/mask.png +0 -0
- package/TextureAnimation/assets/php.jpg +0 -0
- package/TouchSample/App.vue +0 -136
- package/TouchSample/Item.vue +0 -102
- package/TouchSample/MetroWidgetHorizontal.vue +0 -144
- package/TouchSample/MetroWidgetVertical.vue +0 -144
- package/TouchSample/TouchContainerHorizontal.vue +0 -160
- package/TouchSample/TouchContainerVertical.vue +0 -160
- package/TouchSample/data.js +0 -81
- /package/TextureAnimation/assets/{php2.png → borderOpacity.png} +0 -0
package/BakeViewDemo/App.vue
CHANGED
|
@@ -37,7 +37,12 @@ onMounted(() => {
|
|
|
37
37
|
(textureName, autoRecycle, w, h) => {
|
|
38
38
|
vCapturedTexture.value = textureName;
|
|
39
39
|
console.log(`capture done id=${textureName} w=${w} h=${h}`);
|
|
40
|
-
|
|
40
|
+
|
|
41
|
+
if (autoRecycle) {
|
|
42
|
+
// 已经是设置了texture的自动回收,所以不再需要主动调用 JsvTextureStoreApi.deleteTexture 来释放内存
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
true // 自动回收, 不填也行,默认为true
|
|
41
46
|
);
|
|
42
47
|
}, 2200);
|
|
43
48
|
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { getKeyFramesGroup } from "jsview";
|
|
3
|
+
import { onBeforeUnmount } from "vue";
|
|
4
|
+
|
|
5
|
+
const itemStyle = {
|
|
6
|
+
top: 20,
|
|
7
|
+
left: 20,
|
|
8
|
+
width: 60,
|
|
9
|
+
height: 60,
|
|
10
|
+
fontSize: 15,
|
|
11
|
+
color: "rgba(255, 255, 0, 1)",
|
|
12
|
+
backgroundColor: "rgba(255, 0, 0, 1)",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// 单纯的放大动画使用贝塞尔的timingFunction成为心跳效果
|
|
16
|
+
const cP1 = [0.42, 3.96];
|
|
17
|
+
const cP2 = [0.62, 0];
|
|
18
|
+
const sScaleUpTs = `BasicAnim_PumpUp 0.8s cubic-bezier(${cP1[0]}, ${cP1[1]}, ${cP2[0]}, ${cP2[1]}) infinite`;
|
|
19
|
+
|
|
20
|
+
// 暂时不暴露fill-mode = forwards接口
|
|
21
|
+
// const sScaleUpOnce = `BasicAnim_PumpUp 0.8s cubic-bezier(${cP1[0]}, ${cP1[1]}, ${cP2[0]}, ${cP2[1]}) 3 forwards`;
|
|
22
|
+
|
|
23
|
+
// 拿取group句柄
|
|
24
|
+
const styleShell = getKeyFramesGroup();
|
|
25
|
+
|
|
26
|
+
// 动态注入规则, 注意 keyFrame 名称是全局的, 不要重名
|
|
27
|
+
styleShell.insertRule(
|
|
28
|
+
"@keyframes BasicAnim_PumpUp \
|
|
29
|
+
{from {transform: scale3d(1, 1, 1);} \
|
|
30
|
+
to {transform: scale3d(1.2, 1.2, 1);}}"
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// keyFrame 注意unmount时的销毁
|
|
34
|
+
onBeforeUnmount(() => {
|
|
35
|
+
styleShell.removeRule("BasicAnim_PumpUp");
|
|
36
|
+
});
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<div id="layout-root">
|
|
41
|
+
<div :style="{ ...itemStyle, animation: sScaleUpTs }">
|
|
42
|
+
{{ "心跳\n效果" }}
|
|
43
|
+
</div>
|
|
44
|
+
<!-- <div
|
|
45
|
+
:style="{
|
|
46
|
+
...itemStyle,
|
|
47
|
+
left: 100,
|
|
48
|
+
animation: sScaleUpOnce,
|
|
49
|
+
}"
|
|
50
|
+
>
|
|
51
|
+
{{ "心跳\n效果2" }}
|
|
52
|
+
</div> -->
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<style></style>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { reactive, onMounted, onBeforeUnmount } from "vue";
|
|
3
|
+
import ContentBlock from "../ContentBlock.vue";
|
|
4
|
+
import AnimEasingCubicBezier from "./AnimEasingCubicBezier.vue";
|
|
5
|
+
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
contentClass: String,
|
|
8
|
+
itemSides: Object,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const contentBlockProps = {
|
|
12
|
+
colIndex: 0,
|
|
13
|
+
itemSides: props.itemSides,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
onMounted(() => {});
|
|
17
|
+
|
|
18
|
+
onBeforeUnmount(() => {});
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<div id="item-root">
|
|
23
|
+
<ContentBlock
|
|
24
|
+
:class="contentClass"
|
|
25
|
+
:style="{ top: itemSides.height * 0 }"
|
|
26
|
+
:="contentBlockProps"
|
|
27
|
+
:index="1"
|
|
28
|
+
title="贝塞尔动画"
|
|
29
|
+
>
|
|
30
|
+
<AnimEasingCubicBezier />
|
|
31
|
+
</ContentBlock>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import TitleBar from "./TitleBar.vue";
|
|
3
3
|
import ImageGroup from "../img/ImageGroup.vue";
|
|
4
|
+
import AnimGroup2 from "../anim/AnimGroup2.vue";
|
|
4
5
|
|
|
5
6
|
const props = defineProps({
|
|
6
7
|
panelClass: String,
|
|
7
8
|
itemSides: Object,
|
|
8
9
|
});
|
|
9
10
|
|
|
10
|
-
const titleData = ["img标签"];
|
|
11
|
+
const titleData = ["img标签", "div动画2"];
|
|
11
12
|
</script>
|
|
12
13
|
|
|
13
14
|
<template>
|
|
@@ -23,9 +24,13 @@ const titleData = ["img标签"];
|
|
|
23
24
|
:contentClass="panelClass"
|
|
24
25
|
:itemSides="itemSides"
|
|
25
26
|
/>
|
|
27
|
+
<AnimGroup2
|
|
28
|
+
:style="{ left: itemSides.width * 1 }"
|
|
29
|
+
:contentClass="panelClass"
|
|
30
|
+
:itemSides="itemSides"
|
|
31
|
+
/>
|
|
26
32
|
</div>
|
|
27
33
|
</div>
|
|
28
34
|
</template>
|
|
29
35
|
|
|
30
|
-
<style>
|
|
31
|
-
</style>
|
|
36
|
+
<style></style>
|
|
@@ -81,14 +81,12 @@ let deg = shallowRef(props.deg);
|
|
|
81
81
|
//动画处理
|
|
82
82
|
const fire = () => {
|
|
83
83
|
props.myRef.value.start();
|
|
84
|
-
actorControl.run([
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
.setSpdAndAccel(undefined, 0, undefined, 0.15, null, null),
|
|
88
|
-
actorControl
|
|
84
|
+
actorControl.run((cmds) => [
|
|
85
|
+
cmds.action().setSpdAndAccel(undefined, 0, undefined, 0.15, null, null),
|
|
86
|
+
cmds
|
|
89
87
|
.condition()
|
|
90
88
|
.reachPosition(undefined, 280)
|
|
91
|
-
.then([
|
|
89
|
+
.then([cmds.action().stopMoving()]),
|
|
92
90
|
]);
|
|
93
91
|
};
|
|
94
92
|
|
|
@@ -112,7 +110,6 @@ const sprayOk = {
|
|
|
112
110
|
lifeMax: 2000,
|
|
113
111
|
accelerateX: 0,
|
|
114
112
|
accelerateY: 0,
|
|
115
|
-
addNumSpeed: 0.001,
|
|
116
113
|
enableFade: true,
|
|
117
114
|
enableShrink: true,
|
|
118
115
|
};
|
|
@@ -160,16 +160,26 @@ const props = defineProps({
|
|
|
160
160
|
});
|
|
161
161
|
|
|
162
162
|
//火花图片素材
|
|
163
|
-
const group1_1 =
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
163
|
+
const group1_1 =
|
|
164
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/1/group1_1.png";
|
|
165
|
+
const group1_2 =
|
|
166
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/1/group1_2.png";
|
|
167
|
+
const group2_1 =
|
|
168
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/2/group2_1.png";
|
|
169
|
+
const group2_2 =
|
|
170
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/2/group2_2.png";
|
|
171
|
+
const group3_1 =
|
|
172
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/3/group3_1.png";
|
|
173
|
+
const group3_2 =
|
|
174
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/3/group3_2.png";
|
|
175
|
+
const group4_1 =
|
|
176
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/4/group4_1.png";
|
|
177
|
+
const group4_2 =
|
|
178
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/4/group4_2.png";
|
|
179
|
+
const group5_1 =
|
|
180
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/5/group5_1.png";
|
|
181
|
+
const group5_2 =
|
|
182
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Fireworks/images/5/group5_2.png";
|
|
173
183
|
//弹药图片素材(请按需修改)
|
|
174
184
|
const ammo =
|
|
175
185
|
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/images/star2.png";
|
|
@@ -180,7 +190,7 @@ const fireworksJson =
|
|
|
180
190
|
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/SpringFestivalTest_2024/Sprite/fireworks.json";
|
|
181
191
|
|
|
182
192
|
//运动距离
|
|
183
|
-
let moveDistance = 260
|
|
193
|
+
let moveDistance = 260;
|
|
184
194
|
let sprite_info = shallowRef(null);
|
|
185
195
|
let view_size = shallowRef(null);
|
|
186
196
|
let isSpray = shallowRef(false);
|
|
@@ -195,7 +205,7 @@ let actorRef = shallowRef(null);
|
|
|
195
205
|
let myShow = shallowRef(false);
|
|
196
206
|
let actorControl;
|
|
197
207
|
//随机顺序绽放函数
|
|
198
|
-
const spray=()=> {
|
|
208
|
+
const spray = () => {
|
|
199
209
|
timer.id2 = setTimeout(() => {
|
|
200
210
|
let randomIndex = Math.floor(Math.random() * sprayArray.length);
|
|
201
211
|
sprayArray[randomIndex].value = true;
|
|
@@ -210,7 +220,7 @@ const spray=()=> {
|
|
|
210
220
|
}
|
|
211
221
|
}, 100);
|
|
212
222
|
}, 500);
|
|
213
|
-
}
|
|
223
|
+
};
|
|
214
224
|
|
|
215
225
|
//预加载
|
|
216
226
|
const preload_info = [
|
|
@@ -260,7 +270,6 @@ const sprayOk = {
|
|
|
260
270
|
lifeMax: 800,
|
|
261
271
|
accelerateX: 0,
|
|
262
272
|
accelerateY: 0,
|
|
263
|
-
addNumSpeed: 0.001,
|
|
264
273
|
enableFade: false,
|
|
265
274
|
enableShrink: true,
|
|
266
275
|
};
|
|
@@ -278,7 +287,6 @@ const sprayOk1 = {
|
|
|
278
287
|
lifeMax: 2000,
|
|
279
288
|
accelerateX: 0,
|
|
280
289
|
accelerateY: -40,
|
|
281
|
-
addNumSpeed: 0.001,
|
|
282
290
|
enableFade: false,
|
|
283
291
|
enableShrink: false,
|
|
284
292
|
};
|
|
@@ -295,50 +303,50 @@ let ImgData4;
|
|
|
295
303
|
let ImgData5;
|
|
296
304
|
const allGroup = [group1, group2, group3, group4, group5];
|
|
297
305
|
//随机烟花颜色设定
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
remainingGroups.splice(randomIndex, 1);
|
|
306
|
+
const remainingGroups = [...allGroup];
|
|
307
|
+
for (let i = 1; i <= 5; i++) {
|
|
308
|
+
const randomIndex = Math.floor(Math.random() * remainingGroups.length);
|
|
309
|
+
const selectedGroup = remainingGroups[randomIndex];
|
|
310
|
+
switch (i) {
|
|
311
|
+
case 1:
|
|
312
|
+
ImgData1 = selectedGroup;
|
|
313
|
+
break;
|
|
314
|
+
case 2:
|
|
315
|
+
ImgData2 = selectedGroup;
|
|
316
|
+
break;
|
|
317
|
+
case 3:
|
|
318
|
+
ImgData3 = selectedGroup;
|
|
319
|
+
break;
|
|
320
|
+
case 4:
|
|
321
|
+
ImgData4 = selectedGroup;
|
|
322
|
+
break;
|
|
323
|
+
case 5:
|
|
324
|
+
ImgData5 = selectedGroup;
|
|
325
|
+
break;
|
|
321
326
|
}
|
|
322
327
|
|
|
328
|
+
remainingGroups.splice(randomIndex, 1);
|
|
329
|
+
}
|
|
330
|
+
|
|
323
331
|
watch(readyNum, (n, o) => {
|
|
324
332
|
if (o != 2 && n == 2) {
|
|
325
333
|
myShow.value = true;
|
|
326
334
|
timer.id2 = setTimeout(() => {
|
|
327
335
|
myRef.value.start();
|
|
328
336
|
|
|
329
|
-
actorControl.run([
|
|
330
|
-
|
|
337
|
+
actorControl.run((cmds) => [
|
|
338
|
+
cmds
|
|
331
339
|
.condition()
|
|
332
340
|
.onNextTick(2)
|
|
333
341
|
.then([
|
|
334
|
-
|
|
335
|
-
|
|
342
|
+
cmds.action().setSpeed(undefined, -9),
|
|
343
|
+
cmds.action(3).setAccel(undefined, 0.13),
|
|
336
344
|
]),
|
|
337
|
-
|
|
345
|
+
cmds
|
|
338
346
|
.condition()
|
|
339
347
|
.reachPosition(undefined, -moveDistance)
|
|
340
348
|
.then([
|
|
341
|
-
|
|
349
|
+
cmds.action().stopMoving(),
|
|
342
350
|
() => {
|
|
343
351
|
isSpray.value = true;
|
|
344
352
|
isShow.value = false;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { onMounted, onUnmounted, ref, computed } from "vue";
|
|
3
|
+
import { JsvFragShaderView } from "jsview";
|
|
4
|
+
import vortexShader from "./vortex.glsl?raw";
|
|
5
|
+
import pageFlipShader from "./pageFlip.glsl?raw";
|
|
6
|
+
import sdfShader from "./sdf.glsl?raw";
|
|
7
|
+
import gaussianBlurShader from "./gaussianBlur.glsl?raw";
|
|
8
|
+
// import testShader from "./test.glsl?raw";
|
|
9
|
+
|
|
10
|
+
const ImageChinChilla =
|
|
11
|
+
"https://qcast-image.oss-cn-qingdao.aliyuncs.com/JsViewVideo/ImageTestSample/BackgroundLongmao.jpg";
|
|
12
|
+
const ImageLandscape = "https://oss.image.qcast.cn/ai-draw/landscape.jpeg";
|
|
13
|
+
const ImagePanda = "https://oss.image.qcast.cn/ai-draw/panda.jpeg";
|
|
14
|
+
const ImageOwl = "https://oss.image.qcast.cn/ai-draw/owl.jpeg";
|
|
15
|
+
|
|
16
|
+
const cShaderSettings = [
|
|
17
|
+
{
|
|
18
|
+
name: "vortex",
|
|
19
|
+
shader: vortexShader,
|
|
20
|
+
uniforms: [],
|
|
21
|
+
textures: [
|
|
22
|
+
{
|
|
23
|
+
name: "iChannel0",
|
|
24
|
+
resource: ImageOwl,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
duration: 100000,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "pageFlip",
|
|
31
|
+
shader: pageFlipShader,
|
|
32
|
+
uniforms: [],
|
|
33
|
+
textures: [
|
|
34
|
+
{
|
|
35
|
+
name: "iChannel0",
|
|
36
|
+
resource: ImageOwl,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
duration: 500,
|
|
40
|
+
onEnd: (id, status) => {
|
|
41
|
+
if (status) {
|
|
42
|
+
// 动画正常结束,而非cancel打断
|
|
43
|
+
console.log("flip anim end");
|
|
44
|
+
rShowShaderView.value = false;
|
|
45
|
+
} else {
|
|
46
|
+
console.log("flip anim cancel");
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "sdf",
|
|
52
|
+
shader: sdfShader,
|
|
53
|
+
uniforms: [],
|
|
54
|
+
textures: [
|
|
55
|
+
{
|
|
56
|
+
name: "iChannel0",
|
|
57
|
+
resource: ImageOwl,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
duration: 100000,
|
|
61
|
+
},
|
|
62
|
+
// 高斯模糊性能太差,先不做推广
|
|
63
|
+
{
|
|
64
|
+
name: "gaussianBlur",
|
|
65
|
+
shader: gaussianBlurShader,
|
|
66
|
+
uniforms: [],
|
|
67
|
+
textures: [
|
|
68
|
+
{
|
|
69
|
+
name: "iChannel0",
|
|
70
|
+
resource: ImageOwl,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
duration: 0,
|
|
74
|
+
},
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
const rShowShaderView = ref(true);
|
|
78
|
+
const rKeyCount = ref(0);
|
|
79
|
+
const rShaderInfo = computed(() => {
|
|
80
|
+
return cShaderSettings[rKeyCount.value];
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const rAutoplay = computed(() => {
|
|
84
|
+
return true;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const rWidgetRef = ref();
|
|
88
|
+
const onKeyDown = (ev) => {
|
|
89
|
+
switch (ev.keyCode) {
|
|
90
|
+
case 37: {
|
|
91
|
+
rShowShaderView.value = true;
|
|
92
|
+
rKeyCount.value =
|
|
93
|
+
rKeyCount.value > 0 ? rKeyCount.value - 1 : rKeyCount.value;
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
case 39: {
|
|
97
|
+
rShowShaderView.value = true;
|
|
98
|
+
rKeyCount.value =
|
|
99
|
+
rKeyCount.value < cShaderSettings.length - 1
|
|
100
|
+
? rKeyCount.value + 1
|
|
101
|
+
: rKeyCount.value;
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
case 13: {
|
|
105
|
+
rShowShaderView.value = true;
|
|
106
|
+
rWidgetRef.value?.startAnim();
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
default:
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
onMounted(() => {
|
|
115
|
+
window.JsView?.enableFpsDisplay(true);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
onUnmounted(() => {
|
|
119
|
+
window.JsView?.enableFpsDisplay(false);
|
|
120
|
+
});
|
|
121
|
+
</script>
|
|
122
|
+
|
|
123
|
+
<template>
|
|
124
|
+
<jsv-focus-block
|
|
125
|
+
autoFocus
|
|
126
|
+
:onAction="{
|
|
127
|
+
onKeyDown,
|
|
128
|
+
}"
|
|
129
|
+
:style="{
|
|
130
|
+
width: 1280,
|
|
131
|
+
height: 720,
|
|
132
|
+
backgroundImage: `url(${ImageChinChilla})`,
|
|
133
|
+
}"
|
|
134
|
+
></jsv-focus-block>
|
|
135
|
+
|
|
136
|
+
<jsv-frag-shader-view
|
|
137
|
+
v-if="rShowShaderView"
|
|
138
|
+
:key="rKeyCount"
|
|
139
|
+
ref="rWidgetRef"
|
|
140
|
+
:style="{ left: 0, top: 0, width: 1280, height: 720 }"
|
|
141
|
+
:duration="rShaderInfo.duration"
|
|
142
|
+
:shaderStr="rShaderInfo.shader"
|
|
143
|
+
:autoplay="rAutoplay"
|
|
144
|
+
:textures="rShaderInfo.textures"
|
|
145
|
+
:onEnd="rShaderInfo.onEnd"
|
|
146
|
+
></jsv-frag-shader-view>
|
|
147
|
+
<div
|
|
148
|
+
:key="rKeyCount"
|
|
149
|
+
:style="{
|
|
150
|
+
top: 100,
|
|
151
|
+
left: 20,
|
|
152
|
+
width: 500,
|
|
153
|
+
height: 50,
|
|
154
|
+
fontSize: 30,
|
|
155
|
+
backgroundColor: '#00000055',
|
|
156
|
+
color: '#ffffff',
|
|
157
|
+
}"
|
|
158
|
+
>
|
|
159
|
+
{{ rShaderInfo.name }}
|
|
160
|
+
</div>
|
|
161
|
+
<div
|
|
162
|
+
:style="{
|
|
163
|
+
top: 150,
|
|
164
|
+
left: 20,
|
|
165
|
+
width: 500,
|
|
166
|
+
height: 50,
|
|
167
|
+
fontSize: 30,
|
|
168
|
+
backgroundColor: '#00000055',
|
|
169
|
+
color: '#ffffff',
|
|
170
|
+
}"
|
|
171
|
+
>
|
|
172
|
+
左右键切换效果, OK键重新播放
|
|
173
|
+
</div>
|
|
174
|
+
</template>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const int samples = 35, LOD = 2, // gaussian done on MIPmap at scale LOD
|
|
2
|
+
sLOD = 4; // tile size = 2^LOD
|
|
3
|
+
const float sigma = float(samples) * .25;
|
|
4
|
+
|
|
5
|
+
float gaussian(vec2 i) {
|
|
6
|
+
return exp(-.5 * dot(i /= sigma, i)) / (6.28 * sigma * sigma);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
int myMod(int a, int b) {
|
|
10
|
+
return a - b * int(floor(float(a) / float(b)));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
vec4 blur(sampler2D sp, vec2 U, vec2 scale) {
|
|
14
|
+
vec4 O = vec4(0);
|
|
15
|
+
int s = samples / sLOD;
|
|
16
|
+
|
|
17
|
+
for(int i = 0; i < s * s; i++) {
|
|
18
|
+
vec2 d = vec2(myMod(i, s), i / s) * float(sLOD) - float(samples) / 2.;
|
|
19
|
+
O += gaussian(d) * jsvTexture2D(sp, U + scale * d);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return O / O.a;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void mainImage(out vec4 O, vec2 U) {
|
|
26
|
+
O = blur(iChannel0, U / iResolution.xy, 1. / iResolution.xy);
|
|
27
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//https://andrewhungblog.wordpress.com/2018/04/29/page-curl-shader-breakdown/
|
|
2
|
+
#define pi 3.14159265359
|
|
3
|
+
#define radius .1
|
|
4
|
+
|
|
5
|
+
float fastAsin(float x) {
|
|
6
|
+
float x2 = x * x;
|
|
7
|
+
float x3 = x2 * x;
|
|
8
|
+
float x5 = x3 * x2;
|
|
9
|
+
float x7 = x5 * x2;
|
|
10
|
+
return x + (1.0 / 6.0) * x3 + (3.0 / 40.0) * x5 + (5.0 / 112.0) * x7;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
14
|
+
vec2 aspect = iResolution.xy / iResolution.y;
|
|
15
|
+
vec2 uv = fragCoord * aspect / iResolution.xy;
|
|
16
|
+
vec2 anchor = aspect;
|
|
17
|
+
vec2 mouse = anchor - abs(iTime / iDuration) * anchor;
|
|
18
|
+
vec2 mouseDir = normalize(anchor - mouse);
|
|
19
|
+
vec2 origin = mouse - mouseDir * mouse.x / abs(mouseDir.x);
|
|
20
|
+
float mouseDist = length(mouse - origin);
|
|
21
|
+
|
|
22
|
+
float proj = dot(uv - origin, mouseDir);
|
|
23
|
+
float dist = proj - mouseDist;
|
|
24
|
+
vec2 linePoint = uv - dist * mouseDir;
|
|
25
|
+
if(dist > radius) {
|
|
26
|
+
fragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
|
27
|
+
fragColor.rgb *= pow(clamp(dist - radius, 0., 1.) * 1.5, .2);
|
|
28
|
+
} else if(dist >= 0.) {
|
|
29
|
+
// map to cylinder point
|
|
30
|
+
float theta = fastAsin(dist / radius);
|
|
31
|
+
vec2 p2 = linePoint + mouseDir * (pi - theta) * radius;
|
|
32
|
+
vec2 p1 = linePoint + mouseDir * theta * radius;
|
|
33
|
+
uv = (p2.x <= aspect.x && p2.y <= aspect.y && p2.x > 0. && p2.y > 0.) ? p2 : p1;
|
|
34
|
+
fragColor = jsvTexture2D(iChannel0, uv / aspect);
|
|
35
|
+
fragColor.rgb *= pow(clamp((radius - dist) / radius, 0., 1.), .2);
|
|
36
|
+
} else {
|
|
37
|
+
vec2 p = linePoint + mouseDir * (abs(dist) + pi * radius);
|
|
38
|
+
uv = (p.x <= aspect.x && p.y <= aspect.y && p.x > 0. && p.y > 0.) ? p : uv;
|
|
39
|
+
fragColor = jsvTexture2D(iChannel0, uv / aspect);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
2
|
+
// Normalized pixel coordinates (from 0 to 1)
|
|
3
|
+
vec2 aspect = iResolution.xy / iResolution.y;
|
|
4
|
+
vec2 originUv = fragCoord / iResolution.xy;
|
|
5
|
+
vec2 uv = 2. * (originUv - 0.5) * aspect;
|
|
6
|
+
|
|
7
|
+
vec2 sum = vec2(0., 0.); // r, g
|
|
8
|
+
|
|
9
|
+
float modTime = iTime - (60. * floor(iTime / 60.));
|
|
10
|
+
float time = 50. * abs(fract(modTime / 30.) - .5);
|
|
11
|
+
|
|
12
|
+
for(int i = 10; i < 13; i++) {
|
|
13
|
+
vec2 pos = uv * 40. + vec2(sin(time / 3. * float(i) / 2.), cos(time / 3. * float(i) / 3.)) * 10. * (1.0 + float(i) / 10.);
|
|
14
|
+
float dist = 1. / length(pos) * 6.;
|
|
15
|
+
sum += dist;
|
|
16
|
+
}
|
|
17
|
+
sum *= 0.5;
|
|
18
|
+
// sum.x = clamp(sum.x, 0., 1.);
|
|
19
|
+
// sum.x = step(.5, sum.x);
|
|
20
|
+
// fragColor = vec4(.1, sum.x, sum.x, sum.x);
|
|
21
|
+
fragColor = sum.x > 0.5 ? jsvTexture2D(iChannel0, originUv) : vec4(0.);
|
|
22
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#define RANGE 6.
|
|
2
|
+
#define SPEED .5
|
|
3
|
+
#define STRENGTH 6.
|
|
4
|
+
|
|
5
|
+
mat2 rotate(float a) {
|
|
6
|
+
float s = sin(a);
|
|
7
|
+
float c = cos(a);
|
|
8
|
+
return mat2(c, -s, s, c);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
void mainImage(out vec4 fragColor, vec2 coord) {
|
|
12
|
+
/** mediump精度10bit, 直接使用0-1的uv, 小值的normalize()会有精度问题, 导致异常大的结果; 但乘1920x1080又会有大值的问题, 所以选取16x9 */
|
|
13
|
+
vec2 aspect = (iResolution.xy / iResolution.y) * 9.;
|
|
14
|
+
vec2 center = 0.5 * aspect;
|
|
15
|
+
|
|
16
|
+
vec2 uv = coord / iResolution.xy * aspect;
|
|
17
|
+
uv -= center;
|
|
18
|
+
|
|
19
|
+
float d = length(uv);
|
|
20
|
+
float progress = sin(iTime * SPEED);
|
|
21
|
+
|
|
22
|
+
//vortex
|
|
23
|
+
float cTime = STRENGTH * progress;
|
|
24
|
+
d = smoothstep(0., RANGE, RANGE - d) * cTime;
|
|
25
|
+
uv *= rotate(d);
|
|
26
|
+
|
|
27
|
+
//shrink
|
|
28
|
+
float edge = aspect.y * abs(progress);
|
|
29
|
+
uv = uv + normalize(uv) * edge;
|
|
30
|
+
|
|
31
|
+
uv += center;
|
|
32
|
+
uv /= aspect;
|
|
33
|
+
if(uv.x > 1. || uv.y > 1. || uv.x < 0. || uv.y < 0.) {
|
|
34
|
+
fragColor = vec4(0.0, 0.5, 0.6, 1.);
|
|
35
|
+
} else {
|
|
36
|
+
fragColor = jsvTexture2D(iChannel0, uv);
|
|
37
|
+
}
|
|
38
|
+
}
|