When scrolling with momentum in iScroll 5, is there a way to interrupt the scroll, stopping it in its tracks?
I have attempted toggling the momentum option, and forcing another scrollTo but haven't quite found the behaviour I need.
Here are my failed attempts: http://jsfiddle.net/chvtmwz5/4/
// only comes into effect once scroll is finished:
myScroll.options.momentum = false;
// halts scroll, but forces it back to the start unless we know the current scroll
myScroll.scrollTo(0,0);
// halts div scroll but allows scrollbar scroll animation to continue
var currentX = myScroll.x;
myScroll.scrollTo(currentX + 1, 0); // (scrolling to the current value of x has no effect)
Related
I have a one page application that will have sections which are nested.
main wayward section with nest
https://jsfiddle.net/zfLp7d6m/3/
So when the user hits slide 2 -- I want the vertical scrolling to pause and for the next slide to scroll horizontal to slide 3 --- then 4 -- then resume vertical scroll.
If the user goes back up -- then the pause occurs when it its hit slide 4, then 3, then 2 - then resume vertical scroll
var $nested = $('.nested');
var $win = $(window);
$nested.waypoint(function(direction) {
console.log("direction", direction);
if (direction == 'down') {
console.log("pause and slide right");
//scroll width -- pause vertical scroll and scroll right - end slide
//$dipper.addClass("js-dipper-animate");
} else {
console.log("pause and slide left");
//scroll width - pause vertical scroll and scroll left - start slide
//$dipper.removeClass("js-dipper-animate");
}
}, {
offset: '50%'
});
$(window).scroll(function () {
///any use for this function?
});
other example
https://jsfiddle.net/64Lzc1pg/1/
horizontal scroll
https://jsfiddle.net/5gf6envz/1/
You can use https://alvarotrigo.com/fullPage/
If you want to do it by yourself you need to capture the mouse wheel event, prevent the browser scrolling, and then use scrollBy and/or scrollTop to scroll the height of your slide (you can get the height this way: Math.max(document.documentElement.clientHeight, window.innerHeight || 0)). This way you will face a lot of corner cases and cross-platform problems so I recommend to use the other approach.
I've got a custom scrollbar solution (view on CodePen).
The obvious idea is dragging the custom scrollbar should scroll the page.
Try it and see what happens... it's bizarrely janky, and the scrollbar and page scrolling will suddenly snap between points.
The scrolling process is currently in a mousemove handler:
update the scrollbar position visually
window.scrollTo(...) the new position, calculated as viewport top relative to the new scrollbar position
If I comment out the window.scrollTo(...) line, the scrollbar itself then moves perfectly smoothly and sticks with the cursor.
Pertinent code
mousemove(e) {
if (!this.active) return;
this.update(this.getScrollDeltaPositional(e.pageY));
window.scrollTo({top: this.getWindowScrollTop()});
}
update(position, show=true, timer=true, time=0) {
let track = this.getTrackHeight();
this.trackPosition = Math.min(Math.max(position, 0), track);
this.track.style.transform = `translateY(${this.trackPosition}px)`;
}
getWindowScrollTop() {
let scroll = this.getDocumentScroll();
let position = (this.trackPosition / this.root.clientHeight);
return Math.round(scroll * position);
}
(Recommended you view the full source on CodePen)
I presume the scrolling each mousemove is blocking the mousemove events, resulting in the sudden snaps being observed.
How to achieve a smooth scrolling effect on window using a custom scrollbar?
I finally found the answer
After far too many hours of trying everything conceivable to remedy this, I stumbled upon this identical problem: https://css-tricks.com/forums/topic/scrolltop-inexplicably-going-haywire/.
As that user eventually discovered, MouseEvent.pageY (which is what I was using to get scroll position) is
relative to the top edge of the viewport, including scroll offsets.
Therefore, the scroll movement effectively amplifies the mousemove events, causing the scrolling to accelerate exponentially as seen in the demo.
So after half a day of hacking about with this, the fix is a simple Ctrl+H... use MouseEvent.clientY instead.
I have some trouble when trying to back to the top of a list.
I put -webkit-overflow-scrolling:touch on the list to get momentum scroll.
However when I'm using jQuery scrollTop(); while the momentum scroll is still going, it jumps to the top but it doesn't stop the momentum. So it keeps going down again until the momentum ends.
Is there an easy way to stop momentum scroll?
Set your list's -webkit-overflow-scrolling style to 'auto' and then back to 'touch' after a short timeout.
i.e.
let scrollContainer = document.getElementById('yourListId');
scrollContainer.style['-webkit-overflow-scrolling'] = 'auto'; // stop scroll
setTimeout(function() {
scrollContainer.scrollTop = 0; // or jQuery scrollTop()
scrollContainer.style['-webkit-overflow-scrolling'] = 'touch'; // re-enable
}, 2);
Reference: this SO answer. (modified their implementation to get rid of scrollbar redraw jerkiness on desktop browsers)
I have a div with webkit-overflow-scrolling set to touch. On iOS this then gives me an updated position during the touchmove event, but once the user lets go this event ends and a final call to touchend is made before events all stop, but the div continues to momentum scroll.
This is the behaviour I want, but I also want to update the page during this momentum scrolling.
I trigger a call to requestAnimationFrame when the touchend event happens, and I can loop this while the momentum scroll occurs. But when I get DOM information, it's frozen until after the mometnum scroll ends.
I've tried using both the scroll position of the scrolling element and elementFromPoint, but both just have the position the scrolled div was in at the time touchend was triggered, and don't update until the momentum scroll ends.
Does anyone know of any way to get real time DOM information on iOS (6+, not worried about 5)
Here's some code I'm using:
var glideStart;
var bird_scanner = document.getElementById('bird-scanner');
bird_scanner.addEventListener('touchend',function()
{
glideStart = null;
requestAnimationFrame(glide);
});
function glide(timestamp)
{
// if we need to reset the timestamp
if( glideStart === null )
{
glideStart = timestamp;
}
// determine if we've moved
var bird_scanner = document.getElementById('bird-scanner');
console.log( document.elementFromPoint(337,568) );
// calculate progress (keep running for a very long time so we see what happens when momentum ends)
var progress = timestamp - glideStart;
if( progress < 10000 )
{
requestAnimationFrame(App.Controller.bird.glide);
}
}
Update
After a lot of attempts at this, I think it really is impossible without using some library to try and mimic the momentum scroll instead of using the built in option (something I find never really gives as smooth results). Apple are clearly very worried about things interfering with their momentum scroll animation and preventing it rendering properly.
I ended up removing the momentum scroll and just detecting swipes and moving through a bunch of elements at once when that's triggered.
I did notice some particularly strange behaviour. When I had webkit-overflow-scrolling: touch set on an element that was scrolling the page up/down and added a setTimeout(some_func,0) to the touchend event, the function wasn't triggered until the momentum scroll ended. When I tried the same thing on a scroll going left/right it triggered the function straight away. No clue why this happens, decided it must just be some strange webkit quirk.
I have a very wide website, intentionally designed to have no vertical scrolling but a lot of horizontal.
Scrolling horizontally is usually a pain to users so was wondering if there was some way of using the middle mouse or other scrolling habits (eg. page up/down, up/down arrows, middle mouse click/drag) to scroll horizontally instead of vertically.
Edit: The main reason for requiring horizontal scrolling is because the layout/approach is a left to right graphical/interactive timeline. I've since found some examples;
This one with MooTools: http://www.tinkainteractive.com.au/ and a few other examples I found at http://naldzgraphics.net/inspirations/40-examples-of-horizontal-scrolling-websites/
You can add your own event listener
document.onmousewheel = myScrollFunction
Scrolling can be done by
window.scrollBy(x, y)
Where x is the horizontal scrolling offset and y the vertical scrolling offset.
So you might just call this function in your event listener. You may have to stop bubbling with event.stopPropagation and prevent browser default behaviour with event.preventDefault so that the original scrolling behaviour doesn't get applied anymore.
Edit: I was curious about this so I implemented something :-)
function onScroll(event) {
// delta is +120 when scrolling up, -120 when scrolling down
var delta = event.detail ? event.detail * (-120) : event.wheelDelta
// set own scrolling offset, take inverted sign from delta (scroll down should scroll right,
// not left and vice versa
var scrollOffset = 10 * (delta / -120);
// Scroll it
window.scrollBy(scrollOffset, 0);
// Not sure if the following two are necessary, you may have to evaluate this
event.preventDefault;
event.stopPropagation;
}
// The not so funny part... fin the right event for every browser
var mousewheelevt=(/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
if (document.attachEvent)
document.attachEvent("on"+mousewheelevt, onScroll);
else if (document.addEventListener)
document.addEventListener(mousewheelevt, onScroll, false);
This works in Firefox 3.5 and Opera 10, however not in IE8. But that would be your part now... ;-)
I wouldn't change this behaviour. It would be very unexpected to the user. Maybe it makes sense to cover the symptom and re-layout your website to switch to a more vertical centered approach?
Still you can do loads of event-handling stuff with java-script, but as said I would rethink the layout.