Vue2实现数字滚动翻页效果的示例代码
前言
最近大屏项目中有数值需要数值变化时有一个炸裂的效果,对用户来说明显一点,经过几番查找,自己又重新修改总结,发出下面文,防止下次遇到。
实现这种效果有两种方法:
第一种方法
第一种方法虽然实现了效果,但是数值变化整体都重新滚动了,不太好。
效果
新建文件FlipItem.vue
<template> <div style=" display: inline-flex; justify-content: flex-start; align-items: center; " > <div v-for="(item, index) in numberList" :key="index" style=" display: inline-flex; justify-content: flex-start; align-items: center; padding-bottom: 0.3rem; box-sizing: border-box; " > <span v-if="isNaN(item)">{{ item }}</span> <div class="number" v-else :style="{ color: TextColor }"> <span class="number-item" ref="numberItem" :data-number="item" :data-index="index" >0123456789</span > </div> </div> </div> </template> <script> export default { name: "ScrollNumber", props: { value: { type: [String, Number], default: 0, }, TextColor: { type: String, default: "black", }, }, watch: { value: { handler(newValue, oldValue) { // console.log("🚀 ~ value ~ newVal:", newValue); if (newValue) { this.$nextTick(() => { this.setNumberTransform(); }); } }, deep: true, immediate: true, }, TextColor: { handler(newValue, oldValue) { console.log("🚀 ~ handler ~ newValue:", newValue); this.TextColor = newValue; }, deep: true, immediate: true, }, }, computed: { numberList() { return String(this.value).split(""); }, pageColor() { return { "--TextColor": this.TextColor, }; }, }, data() { return { hasShow: false, // 是否已展示过动画 // TextColor: "red", }; }, mounted() { window.addEventListener("scroll", this.scrollHandle, true); // 监听 监听元素是否进入/移出可视区域 }, methods: { scrollHandle() { const offset = this.$el.getBoundingClientRect(); const offsetTop = offset.top; const offsetBottom = offset.bottom; // 进入可视区域 if (offsetTop <= window.innerHeight && offsetBottom >= 0) { this.setNumberTransform(); this.hasShow = true; window.removeEventListener("scroll", this.scrollHandle, true); } else { // 移出可视区域 if (this.hasShow) { window.removeEventListener("scroll", this.scrollHandle, true); } } }, // 设置每一位数字的偏移 setNumberTransform() { let numberItems = this.$refs.numberItem; let obj = {}; Array.from(numberItems).forEach((c) => { let key = c.dataset.index; let value = c.dataset.number; let init = 0; obj[key] = setInterval(() => { if (init < value * 10) { init += 1; c.style.transform = `translateY(-${init}%)`; } else { clearInterval(obj[key]); obj[key] = null; } }, 8); }); }, }, }; </script> <style scoped lang="scss"> .number { width: 30px; height: 30px; font-size: 25px; font-weight: 800; color: var(--TextColor); text-align: center; overflow: hidden; span { text-align: center; writing-mode: vertical-rl; text-orientation: upright; transform: translateY(0%); } } </style>
父组件引用
<template> <div class="father"> <FlipItemVue :value="num.toString()" :TextColor="TextColor"></FlipItemVue> <button @click="NumChangeFn">点击变更数字</button> </div> </template> <script> import FlipItemVue from "./FlipItem.vue"; export default { components: { FlipItemVue, }, data() { return { num: 123456, TextColor: "red", }; }, methods: { NumChangeFn() { this.num = 9999999; }, }, }; </script> <style lang="scss" scoped> </style>
第二种方法
第二种方法效果更好一点,数字滚动更丝滑自然只有变化的数值滚动。这里我就没有封装也就copy了一个demo过来了,问题:1、我封装了首次接受数值时只有第一个数字滚动,2、页面首次渲染如果是三个数字,那么宽度就固定了。这时候传过来新值是四个字,可能就会出现内容超出。(可能我个人问题)
效果
新建文件Index.vue
<template> <div class="days-box"> <div class="operating-title">安全运行天数</div> <div class="box-item"> <li :class="{ 'number-item': !isNaN(item), 'mark-item': isNaN(item), }" v-for="(item, index) in runningDays" :key="index" > <span v-if="!isNaN(item)"> <i ref="numberItem">0123456789</i> </span> <span class="comma" v-else>{{ item }}</span> </li> </div> <button @click="toRunningNum(399)">点击</button> </div> </template> <script> export default { data() { return { runningDays: ["0", "0", "0", "0", "0", "0", "0", "0"], }; }, mounted() { // 获取当前日期 var today = new Date(); // 设置起始日期 var startDate = new Date("2023-04-24"); // 计算天数差 var timeDiff = Math.abs(today.getTime() - startDate.getTime()); var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24)); this.$nextTick(() => { this.toRunningNum(diffDays); // 这里输入数字即可调用 this.setNumberTransform(); }); }, methods: { // 设置文字滚动 setNumberTransform() { const numberItems = this.$refs.numberItem; // 拿到数字的ref,计算元素数量 console.log("🚀 ~ setNumberTransform ~ numberItems:", numberItems); const numberArr = this.runningDays.filter((item) => !isNaN(item)); // 结合CSS 对数字字符进行滚动,显示订单数量 for (let index = 0; index < numberItems.length; index++) { const elem = numberItems[index]; elem.style.transform = `translate(-50%, -${numberArr[index] * 10}%)`; } }, // 处理数字 toRunningNum(num) { num = num.toString(); this.runningDays = num.split(""); // 将其便变成数据,渲染至滚动数组 this.setNumberTransform(); }, }, }; </script> <style lang="scss" scoped> .days-box { display: flex; flex-direction: column; justify-content: center; align-items: center; } /*滚动数字设置*/ .operating-title { color: black; font-size: 16px; margin-bottom: 10px; } .box-item { position: relative; height: 80px; font-size: 54px; line-height: 41px; text-align: center; list-style: none; // color: #2d7cff; color: #fff; writing-mode: vertical-lr; text-orientation: upright; /*文字禁止编辑*/ -moz-user-select: none; /*火狐*/ -webkit-user-select: none; /*webkit浏览器*/ -ms-user-select: none; /*IE10*/ -khtml-user-select: none; /*早期浏览器*/ user-select: none; /* overflow: hidden; */ } /* 默认逗号设置 */ .mark-item { width: 10px; height: 100px; margin-right: 5px; line-height: 10px; font-size: 48px; position: relative; & > span { position: absolute; width: 100%; bottom: 0; writing-mode: vertical-rl; text-orientation: upright; } } /*滚动数字设置*/ .number-item { width: 41px; height: 75px; // background: #ccc; list-style: none; margin-right: 5px; // background: rgb(7, 50, 207); border-radius: 4px; // border: 1px solid rgba(7, 50, 207, 1); color: black; & > span { position: relative; display: inline-block; margin-right: 10px; width: 100%; height: 100%; writing-mode: vertical-rl; text-orientation: upright; overflow: hidden; & > i { font-style: normal; position: absolute; top: 11px; left: 50%; transform: translate(-50%, 0); transition: transform 1s ease-in-out; letter-spacing: 10px; } } } </style>
到此这篇关于Vue2实现数字滚动翻页效果的示例代码的文章就介绍到这了,更多相关Vue2数字滚动内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Vue使用路由钩子拦截器beforeEach和afterEach监听路由
这篇文章主要介绍了Vue使用路由钩子拦截器beforeEach和afterEach监听路由,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2020-11-11解读element el-upload上传的附件名称不显示 file-list赋值
这篇文章主要介绍了解读element el-upload上传的附件名称不显示 file-list赋值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-10-10
最新评论