Browse Source

数字滚动效果

huliu 1 year ago
parent
commit
4fff8cadf3

+ 1 - 1
src/assets/css/home.scss

@@ -31,7 +31,7 @@
31 31
     padding: 10px;
32 32
     padding-left: 20px;
33 33
     border-radius: 10px;
34
-    background: rgba(255, 255, 255, 0.80);
34
+    background: rgb(255, 255, 255);
35 35
     width: 206px;
36 36
     height: 165px;
37 37
     display: none;

+ 66 - 27
src/components/CircleProgress.vue

@@ -1,7 +1,10 @@
1 1
 <template>
2 2
     <div>
3 3
         <div class="number" v-if="textPosition == 'top'">
4
-            {{ showProgress }} <span> (个)</span>
4
+            <ul class="flex">
5
+                <ScrollNum v-for="(num, idx) of numArr" :key="idx" as="li" :i="num" :delay="idx + 1" />
6
+                <span> (人)</span>
7
+            </ul>
5 8
         </div>
6 9
     </div>
7 10
     <div class="progress" :style="{ width, height }">
@@ -15,14 +18,18 @@
15 18
             <slot></slot>
16 19
         </div>
17 20
     </div>
21
+
18 22
     <div class="bottomNumber" v-if="textPosition == 'bottom'">
19
-        {{ showProgress }} <span v-if="showProgress
20
-            > 1000">(人)</span>
21
-        <span v-else>(节)</span>
23
+        <ul class="flex">
24
+            <ScrollNum v-for="(num, idx) of numArr" :key="idx" as="li" :i="num" :delay="idx + 1" />
25
+            <span> (人)</span>
26
+        </ul>
27
+
22 28
     </div>
23 29
 </template>
24 30
 <script setup lang="ts">
25
-import { ref, toRefs, watch, onMounted } from 'vue';
31
+import { ref, computed, toRefs, watch, onMounted, nextTick } from 'vue';
32
+import ScrollNum from './roll.vue'
26 33
 
27 34
 const props = defineProps({
28 35
     targetValue: {
@@ -51,29 +58,49 @@ const props = defineProps({
51 58
 const { height, width, color, targetValue, textPosition } = toRefs(props);
52 59
 
53 60
 let showProgress = ref<number>(0);
54
-const addData = () => {
55
-    if (targetValue.value === 0) return;
56
-    let timer = setInterval(() => {
57
-        if (targetValue.value === showProgress.value) {
58
-            clearInterval(timer), timer == null;
59
-            return;
61
+const numArr = computed(() => {
62
+    const str = String(targetValue.value)
63
+    let arr = <any>[]
64
+    for (let i = 0; i < str.length; i++) {
65
+        arr.push(parseInt(str[i]))
66
+    }
67
+    return arr
68
+})
69
+
70
+const progressValue = ref<number>(0);
71
+let timer = ref<any>(null)
72
+const circleValue = () => {
73
+
74
+
75
+    if (textPosition.value == "top") {
76
+        if (progressValue.value = 360) {
77
+            timer.value = null
78
+            return
60 79
         }
61
-        // showProgress.value = showProgress.value + 200
62
-        // console.log(showProgress.value)
63
-        // console.log("targetValue.value", targetValue.value)
64
-        // showProgress.value = showProgress.value + 6
65
-        ++showProgress.value;
80
+        (timer as any) = setInterval(() => {
81
+            progressValue.value += 10
82
+        }, 2000)
83
+    } else {
84
+        if (progressValue.value = 120) {
85
+            timer.value = null
86
+            return
87
+        }
88
+        (timer as any) = setInterval(() => {
89
+            progressValue.value += 10
90
+        }, 2000)
91
+    }
92
+}
93
+
66 94
 
67 95
 
68
-    }, 10);
69
-};
70 96
 onMounted(() => {
71
-    addData();
72
-});
73
-// const progressValue = ref<number>((showProgress.value / 360) * 250);
74
-const progressValue = ref(0)
75
-watch(showProgress, (newValue: number) => {
76
-    progressValue.value = 360;
97
+    circleValue()
98
+})
99
+
100
+// const progressValue = ref(0)
101
+watch(textPosition, (newValue) => {
102
+    console.log("监听一下现在的位置", newValue)
103
+    // progressValue.value = 360;
77 104
 });
78 105
 </script>
79 106
 <style lang="scss" scoped>
@@ -113,12 +140,24 @@ watch(showProgress, (newValue: number) => {
113 140
     }
114 141
 }
115 142
 
116
-.bottomNumber {
117
-    font-size: 14px;
118
-    font-weight: bold;
143
+
144
+
145
+ul {
146
+    padding: 0;
147
+    margin: 0
148
+}
149
+
150
+.flex {
151
+    display: flex;
152
+    // border: 1px solid darkblue;
153
+    box-sizing: border-box;
154
+    // width: 100px;
155
+    align-items: center;
156
+    text-align: center;
119 157
 
120 158
     span {
121 159
         font-size: 12px;
160
+        margin-left: 4px;
122 161
     }
123 162
 }
124 163
 </style>

+ 2 - 2
src/components/home.vue

@@ -4,7 +4,7 @@
4 4
             <img :src="headImg" alt="" />
5 5
         </div>
6 6
         <el-container>
7
-            <left></left>
7
+            <Left></Left>
8 8
             <right></right>
9 9
             <div ref="linedomRef" style="width:1px;height:1px;position: absolute;z-index: 228;background:#ccc;">
10 10
             </div>
@@ -45,7 +45,7 @@ import { getClassDetail } from '../request/api.js'
45 45
 import {
46 46
     callUIInteraction,
47 47
 } from "../webrtcVideo";
48
-import axios from 'axios';
48
+
49 49
 
50 50
 export default ({
51 51
     name: 'Histogram',

+ 0 - 333
src/components/left copy.vue

@@ -1,333 +0,0 @@
1
-<template>
2
-    <div class="container">
3
-        <div class="header">
4
-            <img src="../assets/img/head.png" alt="" />
5
-        </div>
6
-        <el-container>
7
-            <!-- <left></left>
8
-            <right></right> -->
9
-            <div ref="linedomRef" style="width: 50px;height: 50px;background-color: #f00;position: absolute;z-index: 228;">
10
-            </div>
11
-
12
-        </el-container>
13
-
14
-
15
-        <el-popover placement="right" v-model:visible="visible" :width="260" :virtual-ref="triggerRef" trigger="click"
16
-            virtual-triggering>
17
-            <div class="model-detail" ref="popoverRef" id="popoverRef">
18
-                <span><span class="title">设备名称: </span>{{ clickData.value && clickData.value.status }}</span>
19
-                <span><span class="title">设备状态: </span>{{ clickData.value && clickData.value.classes }}</span>
20
-                <span><span class="title">位置: </span>{{ clickData.value && clickData.value.course }}</span>
21
-                <span><span class="title">型号: </span>{{ clickData.value && clickData.value.theory }}</span>
22
-                <span><span class="title">质保期: </span>{{ clickData.value && clickData.value.name }}</span>
23
-                <!-- <span><span class="title">实到人数: </span>{{ clickData.value && clickData.value.actual }}</span>
24
-                <span><span class="title">老师: </span>{{ clickData.value && clickData.value.teacher }}</span> -->
25
-            </div>
26
-        </el-popover>
27
-
28
-        <!-- 视频播放弹框 -->
29
-        <el-dialog class="videoDialog" v-model="videoDialog" title="互动教师1" width="60%" align="center" top="4%">
30
-            <videoPlay v-bind="videoData" @play="onPlay" />
31
-        </el-dialog>
32
-    </div>
33
-</template>
34
-
35
-<script>
36
-import { reactive, onMounted, ref, toRefs, onBeforeUnmount, getCurrentInstance, nextTick } from 'vue';
37
-import { ElScrollbar, ElPagination, ElDialog, ElCarousel, ElCarouselItem, ElMessage } from "element-plus";
38
-import "vue3-video-play/dist/style.css";
39
-import { addResponseEventListener } from "../webrtcVideo.js";
40
-import { videoPlay } from "vue3-video-play";
41
-import CircleProgress from './CircleProgress.vue';
42
-import Left from './left.vue'
43
-import Right from './right.vue'
44
-import LeaderLine from "../assets/js/leaderline.js"
45
-
46
-export default ({
47
-    name: 'Histogram',
48
-    components: { Left, Right, ElScrollbar, ElPagination, ElDialog, videoPlay, ElCarousel, ElCarouselItem, CircleProgress },
49
-    setup() {
50
-        // 视频数据
51
-        const videoData = reactive({
52
-            width: "100%", //播放器高度
53
-            height: "100%", //播放器高度
54
-            color: "red", //主题色
55
-            title: "互动教室", //视频名称
56
-            src: "https://cdn.jsdelivr.net/gh/xdlumia/files/video-play/IronMan.mp4", //视频源
57
-            muted: false, //静音
58
-            webFullScreen: false,
59
-            // speedRate: ["0.75", "1.0", "1.25", "1.5", "2.0"], //播放倍速
60
-            autoPlay: false, //自动播放
61
-            loop: false, //循环播放
62
-            mirror: false, //镜像画面
63
-            ligthOff: false, //关灯模式
64
-            volume: 0.3, //默认音量大小
65
-            control: true, //是否显示控制
66
-            currentTime: 0,//跳转到固定播放时间
67
-            controlBtns: [
68
-                "audioTrack",
69
-                "quality",
70
-                "speedRate",
71
-                "volume",
72
-                "setting",
73
-                "pip",
74
-                "pageFullScreen",
75
-                "fullScreen",
76
-            ], //显示所有按钮,
77
-        });
78
-        // 物联设备类型统计
79
-        const interDevice = ref(
80
-            [
81
-                // {
82
-                //     number: 98,
83
-                //     color: "#63ABFF",
84
-                //     icon: 'r1',
85
-                //     text: "显示系统"
86
-                // },
87
-                // {
88
-                //     number: 185,
89
-                //     color: "#63FFC7",
90
-                //     icon: 'r2',
91
-                //     text: "控制设备"
92
-                // },
93
-                // {
94
-                //     number: 58,
95
-                //     color: "#918EFF",
96
-                //     icon: 'r3',
97
-                //     text: "音频设备"
98
-                // },
99
-                // {
100
-                //     number: 68,
101
-                //     color: "#00C8E3",
102
-                //     icon: 'r4',
103
-                //     text: "录播设备"
104
-                // },
105
-                // {
106
-                //     number: 189,
107
-                //     color: "#FFBB54",
108
-                //     icon: 'r5',
109
-                //     text: "环境设备"
110
-                // },
111
-                // {
112
-                //     number: 98,
113
-                //     color: "#00CF78",
114
-                //     icon: 'r6',
115
-                //     text: "安全管理"
116
-                // },
117
-
118
-            ])
119
-        // 位置弹框
120
-        let centerDialogVisible = ref(false)
121
-        // 获取点击点数据
122
-        let clickData = reactive({})
123
-        const visible = ref(false)
124
-        const triggerRef = ref({
125
-            getBoundingClientRect() {
126
-                // console.log("positon----方法返回元素的大小及其相对于视口的位置", position.value)
127
-                return position.value
128
-            },
129
-        })
130
-        const position = ref({
131
-            top: 0,
132
-            left: 0,
133
-            bottom: 0,
134
-            right: 0,
135
-        })
136
-        // 点击某个模型跟随移动
137
-        const mousemoveHandler = (x, y) => {
138
-            position.value = DOMRect.fromRect({
139
-                width: 0,
140
-                height: 0,
141
-                x: x,
142
-                y: y,
143
-            })
144
-        }
145
-
146
-
147
-        //视频播放弹框
148
-        const videoDialog = ref(false)
149
-        // 播放视频
150
-        const lookVideo = function () {
151
-
152
-            videoDialog.value = true;
153
-            console.log("点击了播放视频", 12312312)
154
-        }
155
-        // 播放视频
156
-        const onPlay = function () {
157
-            console.log("播放视频")
158
-        }
159
-        //智慧教室实时监控---数据
160
-        const carouselData = ref([
161
-            // {
162
-            //     activeMonitor: {
163
-            //         title: "多屏互动教室",
164
-            //         array: [
165
-            //             {
166
-            //                 title: "互动教室22",
167
-            //                 poster: 'rb1',
168
-            //                 src: '',
169
-            //             },
170
-            //             {
171
-            //                 title: "互动教室22",
172
-            //                 poster: 'rb2',
173
-            //                 src: '',
174
-            //             }
175
-            //         ]
176
-            //     },
177
-            //     wisdomMonitor:
178
-            //     {
179
-            //         title: "多屏智慧教室",
180
-            //         array: [
181
-            //             {
182
-            //                 title: "智慧教室11",
183
-            //                 poster: 'rb1',
184
-            //                 src: '',
185
-            //             },
186
-            //             {
187
-            //                 title: "智慧教室11",
188
-            //                 poster: 'rb2',
189
-            //                 src: '',
190
-            //             }
191
-            //         ]
192
-            //     }
193
-            // },
194
-            // {
195
-            //     activeMonitor: {
196
-            //         title: "多屏互动教室",
197
-            //         array: [
198
-            //             {
199
-            //                 title: "互动教室33",
200
-            //                 poster: 'rb1',
201
-            //                 src: '',
202
-            //             },
203
-            //             {
204
-            //                 title: "互动教室33",
205
-            //                 poster: 'rb2',
206
-            //                 src: '',
207
-            //             }
208
-            //         ]
209
-            //     },
210
-
211
-            //     wisdomMonitor:
212
-            //     {
213
-            //         title: "多屏智慧教室",
214
-            //         array: [
215
-            //             {
216
-            //                 title: "智慧教室22",
217
-            //                 poster: 'rb1',
218
-            //                 src: '',
219
-            //             },
220
-            //             {
221
-            //                 title: "智慧教室22",
222
-            //                 poster: 'rb2',
223
-            //                 src: '',
224
-            //             }
225
-            //         ]
226
-            //     }
227
-            // }
228
-
229
-        ]
230
-        )
231
-        const linedomRef = ref(null)
232
-        let lineContainer = ref(null)
233
-        const popoverRef = ref(null)
234
-        const lineStyleOption = ref({
235
-            // color: '#2AC367', // 指引线颜色
236
-            // startPlug: 'disc',
237
-            // endPlug: 'disc', // 指引线结束点的样式 hand,disc
238
-            // size: 2, // 线条尺寸
239
-            // startSocket: 'bottom', //在指引线开始的地方从元素左侧开始
240
-            // endSocket: 'top', //在指引线开始的地方从元素右侧结束
241
-            // // hide: true, // 绘制时隐藏,默认为false,在初始化时可能会出现闪烁的线条
242
-            // // startPlugColor: '#2AC367', // 渐变色开始色
243
-            // // endPlugColor: '#fff386', // 渐变色结束色
244
-            // // gradient: false, // 使用渐变色
245
-            // outLineColor: 'blue',
246
-            // path: 'magnet', // straight,arc,fluid,magnet,grid
247
-            // dash: {
248
-            //     // 虚线样式
249
-            //     animation: true // 让线条滚动起来
250
-            // },
251
-            // hide: true
252
-            startPlug: 'disc',
253
-            endPlug: 'disc',
254
-            startPlugColor: 'rgb(248, 205, 30)',
255
-            startPlugOutlineColor: 'rgb(30, 130, 250)',
256
-            endPlugColor: '#ff0000', // translucent
257
-            endPlugOutlineColor: '#2AC367',
258
-            size: 2,
259
-            startPlugSize: 1.5,
260
-            startPlugOutlineSize: 1,
261
-            endPlugSize: 3,
262
-            endPlugOutlineSize: 3
263
-        })
264
-        onMounted(() => {
265
-
266
-
267
-            // 监听一下页面点击情况
268
-            addResponseEventListener("open", (data) => {
269
-                if (data) {
270
-                    let json = eval("(" + data + ")");//转对象
271
-                    clickData.value = json;
272
-                    // console.log("clickData---点击的数据", clickData.value)
273
-                    // console.log("看一下", linedomRef.value.style.top, json, "json")
274
-                    visible.value = true
275
-                    linedomRef.value.style.top = json.x + "px";
276
-                    linedomRef.value.style.left = json.y + "px";
277
-
278
-                    let popoverRef2 = document.getElementById("popoverRef")
279
-                    // setTimeout(() => {
280
-                    //     console.log("popoverRef", popoverRef, "popoverRef.value", popoverRef.value);
281
-                    // }, 2000);
282
-                    // setTimeout(() => {
283
-                    console.log("linedomRef.value", linedomRef.value, "popoverRef.value", popoverRef.value);
284
-                    lineContainer.value = new LeaderLine(linedomRef.value, popoverRef.value)
285
-                    lineContainer.value.show('draw', {
286
-                        duration: 1000, //持续时长
287
-                        timing: 'ease-in' // 动画函数
288
-                    })
289
-                    lineContainer.value.endPlugOutline = true;
290
-                    lineContainer.value.position()
291
-                    console.log("隔几秒在连接", 1312312)
292
-                    // }, 3000);
293
-
294
-                }
295
-            })
296
-
297
-            // addResponseEventListener("End", data => {
298
-            //     console.log("移动结束", 123123, data)
299
-            // })
300
-
301
-        })
302
-
303
-
304
-
305
-
306
-
307
-
308
-
309
-
310
-        return {
311
-            centerDialogVisible,
312
-            interDevice,
313
-            clickData,
314
-            visible,
315
-            triggerRef,
316
-            videoData,
317
-            onPlay,
318
-            videoDialog,
319
-            lookVideo,
320
-            ...toRefs(carouselData),
321
-            carouselData,
322
-            linedomRef,
323
-            popoverRef,
324
-            lineContainer
325
-        }
326
-    },
327
-})
328
-
329
-</script>
330
-
331
-<style scoped lang="scss">
332
-@import '../assets/css/home.scss';
333
-</style>

+ 4 - 2
src/components/left.vue

@@ -23,19 +23,21 @@
23 23
             <div class="title">
24 24
                 <div class="text">本周课程统计</div>
25 25
             </div>
26
+            <!-- <Number numm="1234" :numLen="4" /> -->
26 27
             <div class="content">
27 28
                 <div class="count" v-for="(item, index) in classCount" :key="index">
28 29
                     <CircleProgress :target-value="item.number" :color="item.color" text-position="bottom">
29 30
                         <img :src="leftimg + item.imgnumber + '.png'" alt="">
30
-
31 31
                         <!-- <img :src="'src/assets/img/' + item.imgnumber + '.png'" alt=""> -->
32 32
                     </CircleProgress>
33 33
                     <div class="text">{{ item.text }}</div>
34
+
35
+                    <!-- <Number :numm="item.text" :numLen="4" /> -->
34 36
                 </div>
35 37
             </div>
36 38
         </div>
37
-        <div class="left-bottom">
38 39
 
40
+        <div class="left-bottom">
39 41
             <div class="title">
40 42
                 <div class="text">智慧教室使用明细</div>
41 43
             </div>

+ 62 - 0
src/components/left1.vue

@@ -0,0 +1,62 @@
1
+<template>
2
+    <el-aside class="left">
3
+
4
+        <ul class="flex">
5
+            <ScrollNum v-for="(num, idx) of numArr" :key="idx" as="li" :i="num" :delay="idx + 1" class="num" />
6
+        </ul>
7
+
8
+    </el-aside>
9
+</template>
10
+
11
+<script setup>
12
+import { computed, ref } from 'vue'
13
+import ScrollNum from './roll.vue'
14
+
15
+const num = ref(888)
16
+const numArr = computed(() => {
17
+    const str = String(num.value)
18
+    let arr = []
19
+    for (let i = 0; i < str.length; i++) {
20
+        arr.push(parseInt(str[i]))
21
+    }
22
+    return arr
23
+})
24
+</script>
25
+
26
+<style scoped lang="scss">
27
+@import '../assets/css/left.scss';
28
+</style>
29
+<style>
30
+.classpopover {
31
+    .el-popper__arrow {
32
+        top: 196px !important;
33
+    }
34
+
35
+    .el-popper[data-popper-placement^=bottom],
36
+    .el-popper__arrow::before {
37
+        border-left-color: transparent !important;
38
+        border-top-color: transparent !important;
39
+    }
40
+}
41
+
42
+.flex {
43
+    display: flex;
44
+}
45
+
46
+.el-popper.is-light {
47
+    border-radius: 10px;
48
+}
49
+
50
+ul {
51
+    padding: 0;
52
+    margin: 0;
53
+    list-style: none;
54
+}
55
+
56
+.num {
57
+    /* --width: 26px;
58
+    margin-right: 6px;
59
+    border: 1px solid black;
60
+    border-radius: 8px */
61
+}
62
+</style>

+ 176 - 0
src/components/roll.vue

@@ -0,0 +1,176 @@
1
+<template>
2
+    <component :is="as" class="scroll-num" :style="{ '--i': i, '--delay': delay }" @animationend="showAnimate = false">
3
+        <ul ref="ul" :class="{ animate: showAnimate }">
4
+            <li>0</li>
5
+            <li>1</li>
6
+            <li>2</li>
7
+            <li>3</li>
8
+            <li>4</li>
9
+            <li>5</li>
10
+            <li>6</li>
11
+            <li>7</li>
12
+            <li>8</li>
13
+            <li>9</li>
14
+            <li>0</li>
15
+        </ul>
16
+
17
+        <svg width="0" height="0">
18
+            <filter id="blur">
19
+                <feGaussianBlur in="SourceGraphic" :stdDeviation="`0 ${blur}`" />
20
+            </filter>
21
+        </svg>
22
+    </component>
23
+</template>
24
+
25
+<script>
26
+export default {
27
+    name: 'ScrollNum',
28
+    props: {
29
+        as: {
30
+            type: String,
31
+            default: 'div'
32
+        },
33
+        i: {
34
+            type: Number,
35
+            default: 0,
36
+            validator: v => v < 10 && v >= 0 && Number.isInteger(v)
37
+        },
38
+        delay: {
39
+            type: Number,
40
+            default: 1
41
+        },
42
+        blur: {
43
+            type: Number,
44
+            default: 2
45
+        }
46
+    },
47
+    data: () => ({
48
+        timer: null,
49
+        showAnimate: true
50
+    }),
51
+    watch: { i() { this.showAnimate = true } },
52
+    mounted() {
53
+        const ua = navigator.userAgent.toLowerCase()
54
+        const testUA = regexp => regexp.test(ua)
55
+        const isSafari = testUA(/safari/g) && !testUA(/chrome/g)
56
+
57
+        // Safari浏览器的兼容代码
58
+        isSafari && (this.timer = setTimeout(() => {
59
+            this.$refs.ul.setAttribute('style', `
60
+        animation: none;
61
+        transform: translateY(calc(var(--i) * -9.09%))
62
+      `)
63
+        }, this.delay * 1000))
64
+    },
65
+    beforeDestroy() { clearTimeout(this.timer) }
66
+}
67
+</script>
68
+
69
+<style scoped>
70
+.scroll-num {
71
+    /* width: var(--width, 60px); */
72
+    /* height: var(--height, calc(var(--width, 20px) * 1.8)); */
73
+    /* color: var(--color, #333); */
74
+    /* font-size: var(--height, calc(var(--width, 20px) * 1.1)); */
75
+    /* line-height: var(--height, calc(var(--width, 20px) * 1.8)); */
76
+    text-align: center;
77
+    overflow: hidden;
78
+    font-size: 14px;
79
+    height: 13px;
80
+    line-height: 13px;
81
+    color: #fff;
82
+    font-weight: bold;
83
+    list-style: none;
84
+    /* width: 20px;
85
+    border: 5px soli darkcyan; */
86
+}
87
+
88
+.animate {
89
+    animation: move .3s linear infinite,
90
+        bounce-in-down 1s calc(var(--delay) * 1s) forwards;
91
+
92
+}
93
+
94
+ul {
95
+    margin: 0;
96
+    padding: 0;
97
+    /* border: 2px solid darkcyan; */
98
+}
99
+
100
+li {
101
+    list-style: none;
102
+}
103
+
104
+.border-animate {
105
+    /* animation: enhance-bounce-in-down 1s calc(var(--delay) * 1s) forwards */
106
+}
107
+
108
+ul {
109
+    /* // padding: 0;
110
+    // margin: 0;
111
+    // list-style: none; */
112
+    transform: translateY(calc(var(--i) * -9.09%));
113
+}
114
+
115
+@keyframes move {
116
+    from {
117
+        transform: translateY(-90%);
118
+        filter: url(#blur)
119
+    }
120
+
121
+    to {
122
+        transform: translateY(1%);
123
+        filter: url(#blur)
124
+    }
125
+}
126
+
127
+@keyframes bounce-in-down {
128
+    from {
129
+        transform: translateY(calc(var(--i) * -9.09% - 7%));
130
+        filter: none
131
+    }
132
+
133
+    25% {
134
+        transform: translateY(calc(var(--i) * -9.09% + 3%))
135
+    }
136
+
137
+    50% {
138
+        transform: translateY(calc(var(--i) * -9.09% - 1%))
139
+    }
140
+
141
+    70% {
142
+        transform: translateY(calc(var(--i) * -9.09% + .6%))
143
+    }
144
+
145
+    85% {
146
+        transform: translateY(calc(var(--i) * -9.09% - .3%))
147
+    }
148
+
149
+    to {
150
+        transform: translateY(calc(var(--i) * -9.09%))
151
+    }
152
+}
153
+
154
+@keyframes enhance-bounce-in-down {
155
+    25% {
156
+        transform: translateY(8%)
157
+    }
158
+
159
+    50% {
160
+        transform: translateY(-4%)
161
+    }
162
+
163
+    70% {
164
+        transform: translateY(2%)
165
+    }
166
+
167
+    85% {
168
+        transform: translateY(-1%)
169
+    }
170
+
171
+    to {
172
+        transform: translateY(0)
173
+    }
174
+}
175
+</style>
176
+