mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-07 17:07:19 +08:00
feat: 添加两种数字动画组件
This commit is contained in:
parent
a64b236707
commit
0701692461
2
src/components/ReCountTo/README.md
Normal file
2
src/components/ReCountTo/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
normal 普通数字动画组件
|
||||||
|
rebound 回弹式数字动画组件
|
@ -1,10 +1,15 @@
|
|||||||
import { App } from "vue";
|
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) {
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
@ -10,7 +10,7 @@ import { countToProps } from "./props";
|
|||||||
import { isNumber } from "/@/utils/is";
|
import { isNumber } from "/@/utils/is";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "CountTo",
|
name: "Normal",
|
||||||
props: countToProps,
|
props: countToProps,
|
||||||
emits: ["mounted", "callback"],
|
emits: ["mounted", "callback"],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
73
src/components/ReCountTo/src/rebound/index.tsx
Normal file
73
src/components/ReCountTo/src/rebound/index.tsx
Normal 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>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
14
src/components/ReCountTo/src/rebound/props.ts
Normal file
14
src/components/ReCountTo/src/rebound/props.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
66
src/components/ReCountTo/src/rebound/rebound.css
Normal file
66
src/components/ReCountTo/src/rebound/rebound.css
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||||
<el-card shadow="always">
|
<el-card shadow="always">
|
||||||
<CountTo
|
<ReNormalCountTo
|
||||||
prefix="$"
|
prefix="$"
|
||||||
:duration="1000"
|
:duration="1000"
|
||||||
:color="'#409EFF'"
|
:color="'#409EFF'"
|
||||||
@ -15,14 +15,15 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||||
<el-card shadow="always">
|
<el-card shadow="always">
|
||||||
<CountTo
|
<ul class="flex">
|
||||||
prefix="$"
|
<ReboundCountTo
|
||||||
:duration="2000"
|
v-for="(num, inx) of [1, 6, 6, 6]"
|
||||||
:color="'green'"
|
:key="inx"
|
||||||
:fontSize="'2.3em'"
|
:i="num"
|
||||||
:startVal="1"
|
:blur="inx"
|
||||||
:endVal="2000"
|
:delay="inx + 1"
|
||||||
/>
|
/>
|
||||||
|
</ul>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -30,10 +31,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import CountTo from "/@/components/ReCountTo";
|
import { ReNormalCountTo, ReboundCountTo } from "/@/components/ReCountTo";
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
CountTo
|
ReNormalCountTo,
|
||||||
|
ReboundCountTo
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {};
|
||||||
@ -42,6 +44,9 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
:deep(.el-card) {
|
:deep(.el-card) {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user