Scrollable Panel snap to elements on Scroll
Is there a way inside a scrollable div to snap to elements as the user scrolls.
For example if we have CSS such as
.container {
height: 300px;
width: 200px;
overflow: auto
}
li {
height: 40px;
width: 100 % ;
}
and HTML as
<div class="container">
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
<li>
test
开发者_JAVA技巧 </li>
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
</div>
So from that the container should have a vertical scroll bar. When the user scrolls I would like it so that when they stop scrolling the final scroll position snaps the container scroll position to the nearest div at shown. This might be difficult as browsers like safari offer momentum as well, so it would have to be an event on scroll end.
Any ideas if this is possible, and how.
Marvellous
You can use setTimeout. This should work
var snap_timer;
var scroll_from_mouse = true;
function snapList(){
var snapped = false;
var i = 0;
while(!snapped && i < $('.container li').size()){
var itop = $('.container li').eq(i).position().top;
var iheight = $('.container li').eq(i).outerHeight();
if(itop < iheight && itop > 0){
scroll_from_mouse = false;
snapped = true;
var new_scroll_top = 0;
if(iheight - itop > iheight / 2)
new_scroll_top = $('.container').scrollTop() + itop;
else if(i > 1)
new_scroll_top = $('.container').scrollTop() - ($('.container li').eq(i-1).outerHeight() - itop);
else
new_scroll_top = 0;
$('.container').scrollTop(new_scroll_top);
}
i++;
}
};
$(function(){
$('.container').scroll(function(){
clearTimeout(snap_timer);
if(scroll_from_mouse) snap_timer = setTimeout(snapList, 200);
scroll_from_mouse = true;
});
});
You can use CSS Scroll Snap.
However, the feature is now deprecated, so if you want to consider a cross-browser vanilla javascript re-implementation of the native CSS Scroll Snap spec, as already answered here: How to emulate CSS Scroll Snap Points in Chrome?, you can use this library I wrote.
The main reason to use this instead of the native css solution is that it works in all modern browsers and has a customizable configuration to allow custom timing in transitions and scrolling detection.
The library re-implements the css snapping feature using vanilla javascript easing functions, and works using the values of the container element's scrollTop
/scrollLeft
properties and the scroll Event Listener
Here is an example that shows how to use it:
import createScrollSnap from 'scroll-snap'
const element = document.getElementById('container')
const { bind, unbind } = createScrollSnap(element, {
snapDestinationX: '0%',
snapDestinationY: '90%',
timeout: 100,
duration: 300,
threshold: 0.2,
snapStop: false,
easing: easeInOutQuad,
}, () => console.log('snapped'))
// remove the listener
// unbind();
// re-instantiate the listener
// bind();
You can see a working demo here
精彩评论