前言
在项目中特别是数据大屏,会有把某一部分数据进行滚动的需求,之前也在网上找过很多的方法、插件、组件等,实现功能肯定是可以实现,不过呢,想着无限滚动的场景还是挺多的,于是想自己动手写一个出来,毕竟只有自己写过一遍才会收获更多知识点,废话不多说,先看效果
下面直接贴出html文件
如果是vue组件还可以使用
npm包直接下载哦,支持垂直+水平方向滚动请直接滚动到文章底部
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>无限滚动</title>
</head>
<style>
body,
html {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
list-style: none;
box-sizing: border-box;
overflow: hidden;
}
.scroll-box {
width: 500px;
height: 400px;
overflow: hidden;
scrollbar-width: none;
margin: 100px auto;
border: 1px solid #000;
padding: 10px;
box-sizing: border-box;
scrollbar-width: none;
/* firefox */
-ms-overflow-style: none;
/* IE 10+ */
}
/* 谷歌和safari */
.scroll-box::-webkit-scrollbar {
display: none;
}
.scroll-content {
width: 100%;
height: max-content;
}
ul {
padding: 0;
margin: 0;
list-style: none;
cursor: pointer;
}
ul>li {
color: #333;
min-height: 2rem;
display: flex;
align-items: center;
flex-wrap: wrap;
}
</style>
<body>
<div class="scroll-box">
<div class="scroll-content">
<!-- 这里建议把需要做滚动的内容用一个容器包起来 -->
<ul>
<li>Lorem ipsum dolor sit amet consectetur.</li>
<li>Saepe obcaecati ab excepturi qui voluptate.</li>
<li>Optio dicta consequatur vero vel quis.</li>
<li>Tenetur eum labore libero excepturi ab.</li>
<li>Totam ea quaerat id consequatur animi!</li>
<li>Esse praesentium fuga officiis vero iste.</li>
<li>Necessitatibus quia quidem itaque commodi consectetur?</li>
<li>A dicta odit cumque saepe aliquid.</li>
<li>Ad, aspernatur quod! Reprehenderit, corporis labore!</li>
<li>Commodi voluptatum reprehenderit ipsa eligendi! Aspernatur.</li>
<li>Iure tenetur sapiente labore esse distinctio.</li>
<li>Illo ducimus error explicabo quibusdam ratione?</li>
<li>Lorem ipsum dolor sit amet consectetur adipisicing.</li>
<li>Ab beatae tenetur autem? Aspernatur, dolorem natus?</li>
<li>Sapiente repellendus quisquam nostrum architecto aliquam velit.</li>
<li>Eveniet possimus quas molestias velit culpa dolorem!</li>
<li>Eligendi quidem, expedita ea debitis rem libero.</li>
<li>Provident, sunt. Dolores eum amet voluptatibus consequuntur!</li>
<li>Vel enim odit magnam consectetur voluptas ratione.</li>
<li>Error, excepturi iste illo eligendi quae possimus?</li>
<li>Aperiam dolore labore voluptatibus, a fugiat cupiditate!</li>
<li>Repellendus autem, veritatis exercitationem accusantium doloribus tempore!</li>
<li>Exercitationem, ullam voluptatem recusandae asperiores perspiciatis aliquam.</li>
<li>Error delectus voluptatum aut eligendi explicabo repudiandae?</li>
</ul>
</div>
</div>
</body>
<script>
let scrollBox = null;
let content = null;
let isScroll = false; // 是否开启滚动
let scrollTop = 0; // 滚动的高度
let fatherBoxHeight = 0; // 父元素的高度
let scrollBoxHeight = 0; // 滚动元素的高度
let isCopy = false; // 是否复制
window.onload = function () {
scrollBox = document.querySelector('.scroll-box');
content = document.querySelector('.scroll-content');
judgeScroll();
// 监听父容器的鼠标移入事件
scrollBox.addEventListener('mouseover', () => {
stopScroll(false);
});
// 监听父容器的鼠标移出事件
scrollBox.addEventListener('mouseout', () => {
isScroll = true;
startScroll();
})
}
// 判断内容是否满足滚动条件,如果满足条件则开启滚动
const judgeScroll = () => {
fatherBoxHeight = scrollBox.clientHeight;
scrollBoxHeight = content.clientHeight;
if (scrollBoxHeight > fatherBoxHeight) {
isScroll = true;
} else {
isScroll = false;
}
scroll();
};
// 滚动函数
const scroll = () => {
if (isScroll) {
startScroll();
} else {
stopScroll();
}
};
// 开启滚动
const startScroll = () => {
requestAnimationFrame(srcollCallback);
return;
};
// 滚动的回调函数
const srcollCallback = () => {
if (!isScroll) return;
scrollTop += 0.5;
if (scrollTop >= scrollBoxHeight - fatherBoxHeight) {
if (!isCopy) {
content.appendChild(content.firstElementChild.cloneNode(true));
isCopy = true;
} else {
// 滚动距离大于等于了滚动区域最大的高度时
if (scrollTop >= scrollBoxHeight) {
scrollTop = 0;
isCopy = false;
content.removeChild(content.lastElementChild);
}
}
}
scrollToRun();
// 再一次调用
requestAnimationFrame(srcollCallback);
}
// 让滚动区域进行滚动
const scrollToRun = () => {
if (!isScroll) return;
content.style.transform = `translateY(-${scrollTop}px)`;
}
// 停止滚动
const stopScroll = (isReset = true) => {
isScroll = false;
if (isReset) {
scrollTop = 0;
}
};
</script>
</html>
其中主要思想就是按照匀速把需要滚动的区域做移动,使用的是css transfrom: translateY() 属性,然后在滚动到DOM的底部时,在父元素中把现有的子元素复制一份并添加到父元素中(滚动元素建议使用一个容积(div标签)包起来,方便复制),然后滚动距离大于等于滚动元素自身的高度时,说明第一轮的滚动已经结束,那么把刚刚复制出来的元素从父元素中移除。这样就不会出现滚动时有空白区域的情况,类似于自动轮播图吧。
不想看代码的没关系,直接复制就可以用
如果是在vue项目中使用,唉(手动狗头),不要慌我也很懒,于是又针对vue写了一个组件,直接
npm install w-scroll -S
开箱即用
详细操作请移步:
注意
目前只有Vue3+TypeScript版本,其他的大差不差了,有兴趣的朋友可以直接看看源码,勿喷