问题描述
我正在使用 CSS捕捉点 .对于我来说,只有仅CSS选项很重要,但是我可以通过 javascript (无框架)进行一些增强.>
我正在尝试添加上一个和下一个按钮,以编程方式滚动到下一个或上一个元素.如果禁用了javascript,则按钮将被隐藏,而轮播仍然起作用.
我的问题是关于如何触发滚动到下一个捕捉点?
所有项目的大小均不同,我发现的大多数解决方案要求像素值(例如示例中使用的 scrollBy
). scrollBy
40px
适用于第2页,但不适用于其他页面,因为它们太大(基于视口的大小).
function goPrecious(){document.getElementById('container').scrollBy({最高:-40,行为:平稳"});}函数goNext(){document.getElementById('container').scrollBy({最高:40行为:平稳"});}
#container {scroll-snap-type:y必选;溢出-y:滚动;边框:2px实心var(-gs0);border-radius:8px;高度:60vh;}#container div {scroll-snap-align:开始;显示:flex;证明内容:中心;align-items:居中;字体大小:4rem;}#container div:nth-child(1){背景:hotpink;白颜色;高度:50vh;}#container div:nth-child(2){背景:天蓝色;高度:40vh;}#container div:nth-child(3){背景:blanchedalmond;高度:60vh;}#container div:nth-child(4){背景:浅珊瑚色;白颜色;高度:40vh;}
< div id ="container">< div> 1</div>< div> 2</div>< div> 3</div>< div> 4</div></div>< button onClick ="goPrecious()">上一个</button>< button onClick ="goNext()"> next</button>
很好的问题!我将此视为挑战.
因此,我增加了 JavaScript
使其可以动态工作.遵循我的详细解决方案(最后是完整的代码):
首先,在 .container
中添加 position:relative
,因为它需要作为 scroll
和 height 的参考code>在
.container
中进行检查.
然后,我们创建3个全局辅助变量
:
1)一种将项目滚动位置
(顶部和底部)作为数组
放入 array
中.例如: [[[0,125],[125,280],[280,360]]
(在这种情况下为3个项目).
3)一种存储 .container高度
的一半(稍后会用到的).
2)另一个用于存储 scroll
位置
item index
var carouselPositions;var halfContainer;var currentItem;
现在,一个名为 getCarouselPositions
的函数
可以创建具有项目位置(存储在 carouselPositions
中)的 array
计算 .container
的一半(存储在 halfContainer
中):
function getCarouselPositions(){carouselPositions = [];document.querySelectorAll('#container div').forEach(function(div){carouselPositions.push([div.offsetTop,div.offsetTop + div.offsetHeight]);//将位置信息添加到数组中})halfContainer = document.querySelector('#container').offsetHeight/2;}getCarouselPositions();//调用一次
让我们替换按钮
上的功能
.现在,当您单击它们时,将调用相同的 function
,但带有"next"
或"previous"
参数:
< button onClick ="goCarousel('previous')">上一个</button>< button onClick ="goCarousel('next')"> next</button>
这里是关于 goCarousel
功能
本身的信息:
首先,它创建2个变量
,它们存储轮播的顶部滚动
位置和底部滚动
位置.
然后,有2个条件来查看当前轮播的位置是在大多数 top
还是大多数 bottom
上.
如果它位于 top
上,然后单击"next"按钮
,它将转到第二个位置.如果它位于底部
上,然后单击上一个"按钮
,它将在上一个项目之前移到上一个项目.
如果两个条件均失败,则表示当前项目不是第一个或最后一个.因此,它检查以查看当前位置
是什么,然后使用容器的一半与位置数组
一起循环计算,以查看项目代码>正在显示.然后,它结合
"previous"
或"next"
检查以设置 currentItem
变量的正确下一个位置.
最后,它使用 currentItem
新值通过 scrollTo
到达正确的位置.
下面是完整的代码:
var carouselPositions;var halfContainer;var currentItem;函数getCarouselPositions(){carouselPositions = [];document.querySelectorAll('#container div').forEach(function(div){carouselPositions.push([div.offsetTop,div.offsetTop + div.offsetHeight]);//将位置信息添加到数组中})halfContainer = document.querySelector('#container').offsetHeight/2;}getCarouselPositions();//调用一次函数goCarousel(direction){var currentScrollTop = document.querySelector('#container').scrollTop;var currentScrollBottom = currentScrollTop + document.querySelector('#container').offsetHeight;如果(currentScrollTop === 0&&方向==='下一个'){currentItem = 1;}否则,如果(currentScrollBottom === document.querySelector('#container').scrollHeight&& direction ==='previous'){console.log('这里')currentItem = carouselPositions.length-2;} 别的 {var currentMiddlePosition = currentScrollTop + halfContainer;对于(var i = 0; i< carouselPositions.length; i ++){如果(currentMiddlePosition> carouselPositions [i] [0]&& currentMiddlePosition< carouselPositions [i] [1]){currentItem = i;如果(方向==='下一个'){currentItem ++;} else if(direction ==='previous'){currentItem--}}}}document.getElementById('container').scrollTo({顶部:carouselPositions [currentItem] [0],行为:平稳"});}window.addEventListener('resize',getCarouselPositions);
#container {scroll-snap-type:y必选;溢出-y:滚动;边框:2px实心var(-gs0);border-radius:8px;高度:60vh;职位:相对}#container div {scroll-snap-align:开始;显示:flex;证明内容:中心;align-items:居中;字体大小:4rem;}#container div:nth-child(1){背景:hotpink;白颜色;高度:50vh;}#container div:nth-child(2){背景:天蓝色;高度:40vh;}#container div:nth-child(3){背景:blanchedalmond;高度:60vh;}#container div:nth-child(4){背景:浅珊瑚色;白颜色;高度:40vh;}
< div id ="container">< div> 1</div>< div> 2</div>< div> 3</div>< div> 4</div></div>< button onClick ="goCarousel('previous')">上一个</button>< button onClick ="goCarousel('next')"> next</button>
要添加的另一个很好的细节是,如果窗口调整大小,则再次调用 getCarouselPositions
函数:
window.addEventListener('resize',getCarouselPositions);
就是这样.
这样做很酷.我希望它可以有所帮助.
I am building a carousel, very minimalist, using CSS snap points. It is important for me to have CSS only options, but I'm fine with enhancing a bit with javascript (no framework).
I am trying to add previous and next buttons to scroll programmatically to the next or previous element. If javascript is disabled, buttons will be hidden and carousel still functionnal.
My issue is about how to trigger the scroll to the next snap point ?
All items have different size, and most solution I found require pixel value (like scrollBy
used in the exemple). A scrollBy
40px
works for page 2, but not for others since they are too big (size based on viewport).
function goPrecious() {
document.getElementById('container').scrollBy({
top: -40,
behavior: 'smooth'
});
}
function goNext() {
document.getElementById('container').scrollBy({
top: 40,
behavior: 'smooth'
});
}
#container {
scroll-snap-type: y mandatory;
overflow-y: scroll;
border: 2px solid var(--gs0);
border-radius: 8px;
height: 60vh;
}
#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="goPrecious()">previous</button>
<button onClick="goNext()">next</button>
Nice question! I took this as a challenge.
So, I increased JavaScript
for it to work dynamically. Follow my detailed solution (in the end the complete code):
First, add position: relative
to the .container
, because it need to be reference for scroll
and height
checkings inside .container
.
Then, let's create 3 global auxiliary variables
:
1) One to get items scroll positions
(top and bottom) as arrays
into an array
. Example: [[0, 125], [125, 280], [280, 360]]
(3 items in this case).
3) One that stores half of .container height
(it will be useful later).
2) Another one to store the item index
for scroll
position
var carouselPositions;
var halfContainer;
var currentItem;
Now, a function
called getCarouselPositions
that creates the array
with items positions (stored in carouselPositions
) and calculates the half of .container
(stored in 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
Let's replace the functions
on buttons
. Now, when you click on them, the same function
will be called, but with "next"
or "previous"
argument:
<button onClick="goCarousel('previous')">previous</button>
<button onClick="goCarousel('next')">next</button>
Here is about the goCarousel
function
itself:
First, it creates 2 variables
that store top scroll
position and bottom scroll
position of carousel.
Then, there are 2 conditionals to see if the current carousel position is on most top
or most bottom
.
If it's on top
and clicked "next" button
, it will go to the second item position. If it's on bottom
and clicked "previous" button
, it will go the previous one before the last item.
If both conditionals failed, it means the current item is not the first or the last one. So, it checks to see what is the current position
, calculating using the half of the container in a loop with the array of positions
to see what item
is showing. Then, it combines with "previous"
or "next"
checking to set the correct next position for currentItem
variable.
Finally, it goes to the correct position through scrollTo
using currentItem
new value.
Below, the complete code:
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>
Another good detail to add is to call getCarouselPositions
function again if the window resizes:
window.addEventListener('resize', getCarouselPositions);
That's it.
That was cool to do. I hope it can help somehow.
这篇关于CSS滚动捕捉点,带有导航(下一个,上一个)按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!