数字翻牌器
element plus已经封装好了 element-plus.org/zh-CN/compo…
效果:
大佬封装的vue3版本,还没试过
<template>
<div v-if="to" :id="nodeId" class="count-to">
<span class="num count-color"></span>
<span class="num count-color">
<slot name="unit"></slot>
</span>
</div>
<!-- fix flip插件数字为0的时候不显示 -->
<span v-else-if="to == 0 || !to" class="num_0 count-color">{{ 0 }}</span>
</template>
<script setup name='count-to'>
import uniqueId from 'lodash/uniqueId'
import { nextTick, onMounted, onUnmounted, onUpdated, ref, watch } from 'vue'
import { Flip } from 'number-flip'
const props = defineProps({
// 翻动起始数值
from: {
type: [String, Number],
default: 0
},
// 最终展示数值
to: [String, Number],
// 数字翻动时间
duration: {
type: Number,
default: 2
},
color: {
type: String,
default: '#fff'
},
nodeId: {
type: String,
default: () => {
// 生成随机不重复id
return uniqueId(['countCard_'])
}
},
// flip插件的其他参数
params: {
type: Object,
default: () => ({})
}
})
let flip = null
const initFlip = () => {
const numNode = document.querySelector(`#${props.nodeId} .num`)
if (numNode && props.to) {
numNode.innerHTML = ''
flip = new Flip({
...props.params,
node: numNode,
from: props.from,
to: props.to,
duration: props.duration
})
}
}
onMounted(() => {
initFlip()
})
onUpdated(() => {
initFlip()
})
onUnmounted(() => {
flip = null
})
</script>
<style lang="less" scoped>
.count-to {
overflow: hidden;
height: 24px;
text-align: center;
width: 100%;
}
.num,
.num_0 {
font-size: 20px;
text-align: center;
}
.count-color {
color: v-bind(color);
}
</style>
屏幕自适应包autofit.js
异形屏幕不支持自适应,也可能是我不会用吧。。。 autofit.js 问答和食用指南
下载
npm i autofit.js
引入
import autofit from 'autofit.js'
快速开始
autofit.init()
onMounted使用
autofit.init({
dh: 1080,
dw: 1920,
el:"body",
resize: true
})
onBeforeUnmount停用
autofit.off()
3D旋转菜单
效果:
感觉还挺好的,不过没试过,代码如下:
<template>
<div class="menu">
<div
v-for="(item, index) in MENU_LIST"
:key="index"
class="menu-item"
@click="linkTo(xxx)"
>
<img :src="item.icon" alt="" class="menu-icon" />
</div>
</div>
</template>
<script setup>
const MENU_LIST = [
{
icon: '/imgs/icon1.png',
name: '菜单1',
},
{
icon: '/imgs/icon2.png',
name: '菜单2',
},
{
icon: '/imgs/icon3.png',
name: '菜单3',
]
</script>
<style lang="less">
.menu {
position: relative;
width: 80%;
height: 100%;
left: 50%;
transform: translateX(-50%);
.menu-item {
width: 376px;
height: 436px;
display: flex;
flex-direction: column;
align-items: center;
padding: 33px 0;
position: absolute;
cursor: pointer;
//3个卡片,x和y轴动画加起来是20s , 20s/3 约等于 6.667s
//每个球y轴动画延迟 从0递减2.857s,x轴与y相差动画时长的一半(10s/2)
&:nth-child(1) {
animation: animateX 10s cubic-bezier(0.36, 0, 0.64, 1) -5s infinite alternate,
animateY 10s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate,
scaleAnimate 20s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate;
}
&:nth-child(2) {
animation: animateX 10s cubic-bezier(0.36, 0, 0.64, 1) -11.667s infinite alternate,
animateY 10s cubic-bezier(0.36, 0, 0.64, 1) -6.667s infinite alternate,
scaleAnimate 20s cubic-bezier(0.36, 0, 0.64, 1) -6.667s infinite alternate;
}
&:nth-child(3) {
animation: animateX 10s cubic-bezier(0.36, 0, 0.64, 1) -18.334s infinite alternate,
animateY 10s cubic-bezier(0.36, 0, 0.64, 1) -13.334s infinite alternate,
scaleAnimate 20s cubic-bezier(0.36, 0, 0.64, 1) -13.334s infinite alternate;
}
}
}
@keyframes animateX {
0% {
left: -50px;
}
100% {
left: 75%;
}
}
@keyframes animateY {
0% {
top: -100px;
}
100% {
top: 400px;
}
}
@keyframes scaleAnimate {
0% {
transform: scale(0.6);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0.6);
}
}
</style>