Vue2實(shí)現(xiàn)數(shù)字滾動翻頁效果的示例代碼
前言
最近大屏項(xiàng)目中有數(shù)值需要數(shù)值變化時有一個炸裂的效果,對用戶來說明顯一點(diǎn),經(jīng)過幾番查找,自己又重新修改總結(jié),發(fā)出下面文,防止下次遇到。
實(shí)現(xiàn)這種效果有兩種方法:
第一種方法
參考文章:【vue2】實(shí)現(xiàn)數(shù)字縱向滾動效果(計(jì)時器效果)
第一種方法雖然實(shí)現(xiàn)了效果,但是數(shù)值變化整體都重新滾動了,不太好。
效果

新建文件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); // 監(jiān)聽 監(jiān)聽元素是否進(jìn)入/移出可視區(qū)域
},
methods: {
scrollHandle() {
const offset = this.$el.getBoundingClientRect();
const offsetTop = offset.top;
const offsetBottom = offset.bottom;
// 進(jìn)入可視區(qū)域
if (offsetTop <= window.innerHeight && offsetBottom >= 0) {
this.setNumberTransform();
this.hasShow = true;
window.removeEventListener("scroll", this.scrollHandle, true);
} else {
// 移出可視區(qū)域
if (this.hasShow) {
window.removeEventListener("scroll", this.scrollHandle, true);
}
}
},
// 設(shè)置每一位數(shù)字的偏移
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">點(diǎn)擊變更數(shù)字</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>
第二種方法
第二種方法效果更好一點(diǎn),數(shù)字滾動更絲滑自然只有變化的數(shù)值滾動。這里我就沒有封裝也就copy了一個demo過來了,問題:1、我封裝了首次接受數(shù)值時只有第一個數(shù)字滾動,2、頁面首次渲染如果是三個數(shù)字,那么寬度就固定了。這時候傳過來新值是四個字,可能就會出現(xiàn)內(nèi)容超出。(可能我個人問題)
效果

新建文件Index.vue
<template>
<div class="days-box">
<div class="operating-title">安全運(yùn)行天數(shù)</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)">點(diǎn)擊</button>
</div>
</template>
<script>
export default {
data() {
return {
runningDays: ["0", "0", "0", "0", "0", "0", "0", "0"],
};
},
mounted() {
// 獲取當(dāng)前日期
var today = new Date();
// 設(shè)置起始日期
var startDate = new Date("2023-04-24");
// 計(jì)算天數(shù)差
var timeDiff = Math.abs(today.getTime() - startDate.getTime());
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
this.$nextTick(() => {
this.toRunningNum(diffDays); // 這里輸入數(shù)字即可調(diào)用
this.setNumberTransform();
});
},
methods: {
// 設(shè)置文字滾動
setNumberTransform() {
const numberItems = this.$refs.numberItem; // 拿到數(shù)字的ref,計(jì)算元素?cái)?shù)量
console.log("?? ~ setNumberTransform ~ numberItems:", numberItems);
const numberArr = this.runningDays.filter((item) => !isNaN(item));
// 結(jié)合CSS 對數(shù)字字符進(jìn)行滾動,顯示訂單數(shù)量
for (let index = 0; index < numberItems.length; index++) {
const elem = numberItems[index];
elem.style.transform = `translate(-50%, -${numberArr[index] * 10}%)`;
}
},
// 處理數(shù)字
toRunningNum(num) {
num = num.toString();
this.runningDays = num.split(""); // 將其便變成數(shù)據(jù),渲染至滾動數(shù)組
this.setNumberTransform();
},
},
};
</script>
<style lang="scss" scoped>
.days-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/*滾動數(shù)字設(shè)置*/
.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; */
}
/* 默認(rèn)逗號設(shè)置 */
.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;
}
}
/*滾動數(shù)字設(shè)置*/
.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>
到此這篇關(guān)于Vue2實(shí)現(xiàn)數(shù)字滾動翻頁效果的示例代碼的文章就介紹到這了,更多相關(guān)Vue2數(shù)字滾動內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3+vite兼容低版本的白屏問題詳解(安卓7/ios11)
這篇文章主要給大家介紹了關(guān)于vue3+vite兼容低版本的白屏問題的相關(guān)資料,還給大家介紹了vue打包項(xiàng)目以后白屏和圖片加載不出來問題的解決方法,需要的朋友可以參考下2022-12-12
Vue3新屬性之css中使用v-bind的方法(v-bind?in?css)
這篇文章主要介紹了Vue3新屬性css中使用v-bind(v-bind?in?css)的方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01
Vue 報(bào)錯Error: No PostCSS Config foun
這篇文章主要介紹了Vue 報(bào)錯Error: No PostCSS Config found問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
vue實(shí)現(xiàn)點(diǎn)擊復(fù)制到粘貼板
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)點(diǎn)擊復(fù)制到粘貼板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08
Vue3中關(guān)于ref和reactive的區(qū)別分析
這篇文章主要介紹了vue3關(guān)于ref和reactive的區(qū)別分析,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-06-06
setup+ref+reactive實(shí)現(xiàn)vue3響應(yīng)式功能
這篇文章介紹了通過setup+ref+reactive實(shí)現(xiàn)vue3響應(yīng)式功能,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-11-11
vue下拉菜單組件(含搜索)的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue下拉菜單組件(含搜索)的實(shí)現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11

