思路
首先,高度一直增加,才有无限滚动的可能
那高度如何一直增加呢,联想到拼接,一块拼着一块,这样高度才能一直延续下去
css里面有实现这个的方式吗?有的,相对定位(记得去年面试的时候解答的是使用transform,通过两个块平移拼接的方式,模拟无限滚动的效果,当时字节面试官点了点头说思路可以,你再回去试试,但我这一回去,隔了一年都没有去试... 直到最近又去字节面试,被问到position有几种定位方式,才想起这件事情来)
relative
相对定位在MDN中的定义如下:
"该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative 对 table-*-group, table-row, table-column, table-cell, table-caption 元素无效。"
例子演示
相对定位的元素是在文档中的正常位置偏移给定的值,但是不影响其他元素的偏移。下面的例子中,注意未应用定位的其它元素是按照 "Two" 在正常位置的情况下进行布局的。
最终效果,就是相对定位的元素并未脱离文档流,原来的空间还是占着的,但是又能基于原来的位置进行偏移,并且不影响其他元素,好家伙这就是我们想要的效果
实现
有了思路和实现的手段之后,我们就可以先来实现着试一试
1. 先写不带js的,通过手动在浏览器里修改样式,模拟下实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.ul-ct {
list-style: none;
width: 60px;
padding: 0;
text-align: center;
margin: 0;
height: 216px;
overflow: scroll;
-ms-overflow-style: none;
scrollbar-width: none;
}
.ul-ct::-webkit-scrollbar {
display: none;
}
.lis1-ct,
.lis2-ct {
position: relative;
}
.lis1-ct {
background-color: green;
}
.lis2-ct {
background-color: red;
}
</style>
</head>
<body>
<ul class="ul-ct">
<div class="lis1-ct" style="top: 0;">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
</div>
<div class="lis2-ct" style="top: 0;">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
</div>
</ul>
</body>
</html>
在浏览器手动修改样式
一共两个块拼接,当第二个都滚动底时(没有可滚动的剩余高度了),那么这时候将第一个块的top偏移两个块的高度的和,然后第一个又滚动底时(没有可滚动的剩余高度了),那么这时候将第二个块的top偏移两个块的高度的和,以此往复,便形成了循环...
效果如下
2. 找到规律后,再把js代码添加进去,顺便修改下样式,最终代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.ul-ct {
list-style: none;
width: 60px;
padding: 0;
text-align: center;
margin: 0;
height: 90px;
overflow: scroll;
-ms-overflow-style: none;
scrollbar-width: none;
cursor: pointer;
}
.ul-ct::-webkit-scrollbar {
display: none;
}
.lis1-ct,
.lis2-ct {
position: relative;
}
</style>
</head>
<body>
<ul class="ul-ct">
<div class="lis1-ct" style="top: 0;">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
</div>
<div class="lis2-ct" style="top: 0;">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
</div>
</ul>
<script>
window.onload = function () {
const el = document.querySelector('.ul-ct');
const lis1 = document.querySelector('.lis1-ct');
const lis2 = document.querySelector('.lis2-ct');
el.addEventListener('scroll', () => {
const scrollTop = el.scrollTop;
const clientHeight = el.clientHeight;
const scrollHeight = el.scrollHeight;
const blockHeight = lis1.clientHeight;
if (scrollHeight > clientHeight && scrollTop + clientHeight === scrollHeight) {
const lis1Top = parseInt(lis1.style.top), lis2Top = parseInt(lis2.style.top);
if (lis1Top === lis2Top) {
lis1.style.top = (lis1Top + blockHeight * 2) + 'px';
} else {
lis2.style.top = (lis2Top + blockHeight * 2) + 'px';
}
}
});
};
</script>
</body>
</html>
最终效果如下
项目地址
rencoo/infinite-scrolling-timepicker