好问题!我将此视为挑战。
所以,我增加了JavaScript 让它动态工作。按照我的详细解决方案(最后是完整代码):
首先,将position: relative 添加到.container,因为它需要在.container 中作为scroll 和height 检查的引用。
那么,我们创建3个全局辅助variables:
1) 将项目scroll positions(顶部和底部)作为arrays 获取到array。示例:[[0, 125], [125, 280], [280, 360]](在本例中为 3 项)。
3) 存储 .container height 一半的一个(稍后会有用)。
2) 另一个存储item index 的scroll 位置
var carouselPositions;
var halfContainer;
var currentItem;
现在,一个名为getCarouselPositions 的function 创建了带有项目位置的array(存储在carouselPositions)并计算了.container 的一半(存储在halfContainer):
function getCarouselPositions() {
carouselPositions = [];
document.querySelectorAll('#container div').forEach(function(div) {
carouselPositions.push([div.offsetTop, div.offsetTop + div.offsetHeight]); // add to array the positions information
})
halfContainer = document.querySelector('#container').offsetHeight/2;
}
getCarouselPositions(); // call it once
让我们替换buttons 上的functions。现在,当您单击它们时,将调用相同的 function,但带有 "next" 或 "previous" 参数:
<button onClick="goCarousel('previous')">previous</button>
<button onClick="goCarousel('next')">next</button>
这里是关于goCarousel function 本身:
首先,它创建 2 个variables 存储top scroll 位置和bottom scroll 位置的轮播。
然后,有 2 个条件来查看当前轮播位置是在大多数 top 还是大多数 bottom。
如果它在top 上并单击"next" button,它将转到第二个项目位置。如果它在bottom 上并单击"previous" button,它将转到最后一项之前的上一项。
如果两个条件都失败,则表示当前项目不是第一个或最后一个。因此,它会检查current position 是什么,使用容器的一半与array of positions 循环计算以查看item 显示的内容。然后,它结合"previous" 或"next" 检查为currentItem 变量设置正确的下一个位置。
最后,它通过scrollTo使用currentItem新值到达正确的位置。
下面是完整的代码:
var carouselPositions;
var halfContainer;
var currentItem;
function getCarouselPositions() {
carouselPositions = [];
document.querySelectorAll('#container div').forEach(function(div) {
carouselPositions.push([div.offsetTop, div.offsetTop + div.offsetHeight]); // add to array the positions information
})
halfContainer = document.querySelector('#container').offsetHeight/2;
}
getCarouselPositions(); // call it once
function goCarousel(direction) {
var currentScrollTop = document.querySelector('#container').scrollTop;
var currentScrollBottom = currentScrollTop + document.querySelector('#container').offsetHeight;
if (currentScrollTop === 0 && direction === 'next') {
currentItem = 1;
} else if (currentScrollBottom === document.querySelector('#container').scrollHeight && direction === 'previous') {
console.log('here')
currentItem = carouselPositions.length - 2;
} else {
var currentMiddlePosition = currentScrollTop + halfContainer;
for (var i = 0; i < carouselPositions.length; i++) {
if (currentMiddlePosition > carouselPositions[i][0] && currentMiddlePosition < carouselPositions[i][1]) {
currentItem = i;
if (direction === 'next') {
currentItem++;
} else if (direction === 'previous') {
currentItem--
}
}
}
}
document.getElementById('container').scrollTo({
top: carouselPositions[currentItem][0],
behavior: 'smooth'
});
}
window.addEventListener('resize', getCarouselPositions);
#container {
scroll-snap-type: y mandatory;
overflow-y: scroll;
border: 2px solid var(--gs0);
border-radius: 8px;
height: 60vh;
position: relative;
}
#container div {
scroll-snap-align: start;
display: flex;
justify-content: center;
align-items: center;
font-size: 4rem;
}
#container div:nth-child(1) {
background: hotpink;
color: white;
height: 50vh;
}
#container div:nth-child(2) {
background: azure;
height: 40vh;
}
#container div:nth-child(3) {
background: blanchedalmond;
height: 60vh;
}
#container div:nth-child(4) {
background: lightcoral;
color: white;
height: 40vh;
}
<div id="container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</div>
<button onClick="goCarousel('previous')">previous</button>
<button onClick="goCarousel('next')">next</button>
另一个需要添加的好细节是,如果窗口调整大小,则再次调用getCarouselPositions 函数:
window.addEventListener('resize', getCarouselPositions);
就是这样。
这样做很酷。我希望它能以某种方式提供帮助。