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

This commit is contained in:
xiaoxian521 2021-08-19 11:46:47 +08:00
parent a64b236707
commit 0701692461
8 changed files with 181 additions and 16 deletions

View File

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

View File

@ -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);
}
});

View File

@ -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 }) {

View File

@ -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>
</>
);
}
});

View File

@ -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);
}
}
};

View File

@ -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);
}
}

View File

@ -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;