Vue3 實(shí)現(xiàn)一個無縫滾動組件(支持鼠標(biāo)手動滾動)
前言
在日常開發(fā)中,經(jīng)常遇到需要支持列表循環(huán)滾動展示,特別是在數(shù)據(jù)化大屏開發(fā)中,無縫滾動使用頻率更為頻繁,在jquery時代,我們常用的無縫滾動組件為liMarquee,在vue中已經(jīng)有vue-seamless-scroll組件(通過Vue2實(shí)現(xiàn),不支持鼠標(biāo)手動滾動),但是在使用過程中,發(fā)現(xiàn)滾動后會存在點(diǎn)擊事件失效的問題,并且產(chǎn)品提了個需求,需要支持鼠標(biāo)手動滾動,也要支持自動滾動,于是痛定思痛,決定通過Vue3來實(shí)現(xiàn)該功能,該組件已經(jīng)實(shí)現(xiàn)上傳npm,可以直接安裝使用,鏈接在文尾。
實(shí)現(xiàn)
html部分
首先寫一個基礎(chǔ)的list結(jié)構(gòu),通過插槽接收外部傳入的list數(shù)據(jù),因?yàn)樾枰獙?shí)現(xiàn)無縫滾動,需要復(fù)制出同一份的Dom,在最外層監(jiān)聽鼠標(biāo)hover和leave的狀態(tài),以實(shí)現(xiàn)鼠標(biāo)hover暫停滾動,綁定鼠標(biāo)滾動事件,在鼠標(biāo)滾動時記住滾動的位置,在恢復(fù)自動滾動時能從當(dāng)前滾動位置繼續(xù)滾動。
<div class="custom-list" ref="scrollBody" @mouseenter="mouseenterFunc" @mouseleave="mouseleaveFunc"
@mousewheel="mousewheelFunc">
<div class="list-body" :class="{
'list-body2': isHorizontal
}" ref="listBody" :style="{ transform: getScrollDistance() }">
<slot></slot>
</div>
<div class="list-body" :class="{
'list-body2': isHorizontal
}" ref="tBody" v-if="isCanScroll" :style="{ transform: getScrollDistance() }">
<slot></slot>
</div>
</div>
實(shí)現(xiàn)邏輯
開始
通過父級傳入的isHorizontal判斷是橫向滾動,還是垂直滾動
const start = () => {
//判斷是否可以滾動函數(shù)
let isScrollFunc = (bodySize:number, listSize:number) => {
if (bodySize > listSize) {
scrollDistance.value = 0;
isCanScroll.value = !1;
}
};
isStop.value = !1;
//判斷是否可以滾動
if (!isHorizontal.value) {
isScrollFunc(bodyHeight.value, listHeight.value);
} else {
isScrollFunc(bodyWidth.value, listWidth.value);
}
if (isCanScroll.value) {
run();
}
}
開始滾動
計(jì)算目前滾動的距離,并判斷需要滾動的方向,計(jì)算下一步滾動的距離。
const run = () => {
//清空動畫
clearAnimation();
animationFrame.value = window.requestAnimationFrame(() => {
//滾動主邏輯函數(shù)
let main = (listSize:number, bodySize:number) => {
let tempScrollDistance = Math.abs(scrollDistance.value);
if (scrollDistance.value < 0) {
let cc = 2 * listSize - bodySize;
if (tempScrollDistance > cc) {
scrollDistance.value = -(listSize - bodySize);
}
} else {
scrollDistance.value = -listSize;
}
};
//根據(jù)滾動方向判斷使用高度或?qū)挾瓤刂菩Ч? if (!isHorizontal.value) {
main(listHeight.value, bodyHeight.value);
} else {
main(listWidth.value, bodyWidth.value);
}
//判斷滾動值
if (!isStop.value) {
if (
props.scrollDirection === "top" ||
props.scrollDirection === "left"
) {
scrollDistance.value -= props.steep;
} else if (
props.scrollDirection === "bottom" ||
props.scrollDirection === "right"
) {
scrollDistance.value += props.steep;
}
run();
}
});
}
獲取滾動樣式
通過translate實(shí)現(xiàn)列表平移,已實(shí)現(xiàn)平滑滾動。
const getScrollDistance = () => {
let style;
if (!isHorizontal.value) {
style = "translate(0px, " + scrollDistance.value + "px)";
} else {
style = "translate(" + scrollDistance.value + "px,0px)";
}
return style;
}
const clearAnimation = () => {
if (animationFrame.value) {
cancelAnimationFrame(animationFrame.value);
animationFrame.value = null;
}
}
鼠標(biāo)滾動
鼠標(biāo)滾動時實(shí)時計(jì)算滾動的距離,可通過傳入的鼠標(biāo)滾動速率來計(jì)算每次滾動多少。
const mousewheelFunc = (e:any) => {
if (!isCanScroll.value || !props.isRoller) {
return false;
}
let dis = e.deltaY;
if (dis > 0) {
scrollDistance.value -= props.rollerScrollDistance;
} else {
scrollDistance.value += props.rollerScrollDistance;
}
run();
}
使用
該組件已上傳npm倉庫,歡迎satrt使用
npm install @fcli/vue-auto-scroll --save-dev 來安裝
在項(xiàng)目中使用
import VueAutoScroll from '@fcli/vue-auto-scroll';
const app=createApp(App)
app.use(VueAutoScroll);
使用示例:
<div class="content">
<vue-auto-scroll :data="list" :steep="0.5" scrollDirection="top" :isRoller="true" :rollerScrollDistance="50">
<div class="li" v-for="i in list" :key="i">
{{ i }}
</div>
</vue-auto-scroll>
</div>
屬性 | 屬性名稱 | 類型 | 可選值 |
---|---|---|---|
steep | 滾動的速率 | number | 為正數(shù)即可 |
scrollDirection | 滾動的方向 | string | top ,bottom,left,right |
isRoller | 是否可以使用滾輪滾動 | boolean | true,false |
rollerScrollDistance | 滾輪滾動的速率 | number | (isRoller 必須為 true)為正數(shù)即可 |
data | 接收異步數(shù)據(jù) | array | 同步任務(wù)可不傳 |
注: 當(dāng)scrollDirection 為top或bottom時,一定要為 vue-auto-scroll 組件設(shè)置高度。 當(dāng)scrollDirection 為left或right時,一定要為 vue-auto-scroll 組件設(shè)置寬度。并為嵌入vue-auto-scroll中的標(biāo)簽設(shè)置樣式為display:inline-block; 示例樣式名為list-item可以更改為其他類名。當(dāng)scrollDirection 為left或right時,是基于行內(nèi)元素的“white-space: nowrap;” 來控制強(qiáng)制不換行的。有可能會影響其內(nèi)部的文字排列??梢栽趌ist-item 層添加 white-space: normal; 來處理給問題。并為其添加固定寬度,以保證文字可以正常換行及插件的正確計(jì)算與顯示。如果沒有為其添加固定寬度,會造成插件獲取父容器層的寬度值錯誤,導(dǎo)致顯示混亂文章來源:http://www.zghlxwxcb.cn/news/detail-719865.html
git地址:https://gitee.com/fcli/vue-auto-scroll.git文章來源地址http://www.zghlxwxcb.cn/news/detail-719865.html
到了這里,關(guān)于Vue3 實(shí)現(xiàn)一個無縫滾動組件(支持鼠標(biāo)手動滾動)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!