Prechádzať zdrojové kódy

feat: 添加两种数字动画组件

xiaoxian521 3 rokov pred
rodič
commit
0701692461

+ 2 - 0
src/components/ReCountTo/README.md

@@ -0,0 +1,2 @@
+normal 普通数字动画组件  
+rebound 回弹式数字动画组件  

+ 9 - 4
src/components/ReCountTo/index.ts

@@ -1,10 +1,15 @@
 import { App } from "vue";
-import reCountTo from "./src";
+import reNormalCountTo from "./src/normal";
+import reboundCountTo from "./src/rebound";
 
-export const ReCountTo = Object.assign(reCountTo, {
+export const ReNormalCountTo = Object.assign(reNormalCountTo, {
   install(app: App) {
-    app.component(reCountTo.name, reCountTo);
+    app.component(reNormalCountTo.name, reNormalCountTo);
   }
 });
 
-export default ReCountTo;
+export const ReboundCountTo = Object.assign(reboundCountTo, {
+  install(app: App) {
+    app.component(reboundCountTo.name, reboundCountTo);
+  }
+});

+ 1 - 1
src/components/ReCountTo/src/index.tsx → src/components/ReCountTo/src/normal/index.tsx

@@ -10,7 +10,7 @@ import { countToProps } from "./props";
 import { isNumber } from "/@/utils/is";
 
 export default defineComponent({
-  name: "CountTo",
+  name: "Normal",
   props: countToProps,
   emits: ["mounted", "callback"],
   setup(props, { emit }) {

+ 0 - 0
src/components/ReCountTo/src/props.ts → src/components/ReCountTo/src/normal/props.ts


+ 73 - 0
src/components/ReCountTo/src/rebound/index.tsx

@@ -0,0 +1,73 @@
+import "./rebound.css";
+import {
+  defineComponent,
+  ref,
+  unref,
+  onBeforeMount,
+  onBeforeUnmount,
+  getCurrentInstance
+} from "vue";
+import { reboundProps } from "./props";
+
+export default defineComponent({
+  name: "Rebound",
+  props: reboundProps,
+  setup(props) {
+    const timer = ref(null);
+
+    onBeforeMount(() => {
+      const ua = navigator.userAgent.toLowerCase();
+      const testUA = regexp => regexp.test(ua);
+      const isSafari = testUA(/safari/g) && !testUA(/chrome/g);
+
+      // Safari浏览器的兼容代码
+      isSafari &&
+        (timer.value = setTimeout(() => {
+          // @ts-ignore
+          getCurrentInstance().refs["ul"].setAttribute(
+            "style",
+            `
+        animation: none;
+        transform: translateY(calc(var(--i) * -9.09%))
+      `
+          );
+        }, props.delay * 1000));
+    });
+
+    onBeforeUnmount(() => {
+      clearTimeout(unref(timer));
+    });
+
+    return () => (
+      <>
+        <div
+          class="scroll-num"
+          // @ts-ignore
+          style={{ "--i": props.i, "--delay": props.delay }}>
+          <ul ref="ul" style={{ fontSize: "32px" }}>
+            <li>0</li>
+            <li>1</li>
+            <li>2</li>
+            <li>3</li>
+            <li>4</li>
+            <li>5</li>
+            <li>6</li>
+            <li>7</li>
+            <li>8</li>
+            <li>9</li>
+            <li>0</li>
+          </ul>
+
+          <svg width="0" height="0">
+            <filter id="blur">
+              <feGaussianBlur
+                in="SourceGraphic"
+                stdDeviation={`0 ${props.blur}`}
+              />
+            </filter>
+          </svg>
+        </div>
+      </>
+    );
+  }
+});

+ 14 - 0
src/components/ReCountTo/src/rebound/props.ts

@@ -0,0 +1,14 @@
+import { PropType } from "vue";
+import { propTypes } from "/@/utils/propTypes";
+export const reboundProps = {
+  delay: propTypes.number.def(1),
+  blur: propTypes.number.def(2),
+  i: {
+    type: Number as PropType<number>,
+    required: false,
+    default: 0,
+    validator(value: number) {
+      return value < 10 && value >= 0 && Number.isInteger(value);
+    }
+  }
+};

+ 66 - 0
src/components/ReCountTo/src/rebound/rebound.css

@@ -0,0 +1,66 @@
+.scroll-num {
+  width: var(--width, 20px);
+  height: var(--height, calc(var(--width, 20px) * 1.8));
+  color: var(--color, #333);
+  font-size: var(--height, calc(var(--width, 20px) * 1.1));
+  line-height: var(--height, calc(var(--width, 20px) * 1.8));
+  text-align: center;
+  overflow: hidden;
+  animation: enhance-bounce-in-down 1s calc(var(--delay) * 1s) forwards;
+}
+
+ul {
+  animation: move 0.3s linear infinite,
+    bounce-in-down 1s calc(var(--delay) * 1s) forwards;
+}
+
+@keyframes move {
+  from {
+    transform: translateY(-90%);
+    filter: url(#blur);
+  }
+  to {
+    transform: translateY(1%);
+    filter: url(#blur);
+  }
+}
+
+@keyframes bounce-in-down {
+  from {
+    transform: translateY(calc(var(--i) * -9.09% - 7%));
+    filter: none;
+  }
+  25% {
+    transform: translateY(calc(var(--i) * -9.09% + 3%));
+  }
+  50% {
+    transform: translateY(calc(var(--i) * -9.09% - 1%));
+  }
+  70% {
+    transform: translateY(calc(var(--i) * -9.09% + 0.6%));
+  }
+  85% {
+    transform: translateY(calc(var(--i) * -9.09% - 0.3%));
+  }
+  to {
+    transform: translateY(calc(var(--i) * -9.09%));
+  }
+}
+
+@keyframes enhance-bounce-in-down {
+  25% {
+    transform: translateY(8%);
+  }
+  50% {
+    transform: translateY(-4%);
+  }
+  70% {
+    transform: translateY(2%);
+  }
+  85% {
+    transform: translateY(-1%);
+  }
+  to {
+    transform: translateY(0);
+  }
+}

+ 16 - 11
src/views/components/count-to/index.vue

@@ -3,7 +3,7 @@
     <el-row :gutter="24">
       <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
         <el-card shadow="always">
-          <CountTo
+          <ReNormalCountTo
             prefix="$"
             :duration="1000"
             :color="'#409EFF'"
@@ -15,14 +15,15 @@
       </el-col>
       <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
         <el-card shadow="always">
-          <CountTo
-            prefix="$"
-            :duration="2000"
-            :color="'green'"
-            :fontSize="'2.3em'"
-            :startVal="1"
-            :endVal="2000"
-          />
+          <ul class="flex">
+            <ReboundCountTo
+              v-for="(num, inx) of [1, 6, 6, 6]"
+              :key="inx"
+              :i="num"
+              :blur="inx"
+              :delay="inx + 1"
+            />
+          </ul>
         </el-card>
       </el-col>
     </el-row>
@@ -30,10 +31,11 @@
 </template>
 
 <script lang="ts">
-import CountTo from "/@/components/ReCountTo";
+import { ReNormalCountTo, ReboundCountTo } from "/@/components/ReCountTo";
 export default {
   components: {
-    CountTo
+    ReNormalCountTo,
+    ReboundCountTo
   },
   setup() {
     return {};
@@ -42,6 +44,9 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+.flex {
+  display: flex;
+}
 :deep(.el-card) {
   text-align: center;
   margin-bottom: 10px;