Problems with .scroll function in mobile browsers - javascript

I am trying to get a div to go from 100% opacity to 0% opacity on scroll.
I made this Fiddle and it works great in a web browser, just as I'd hope. It works in mobile browsers too, but with one horrible downside.
var divs = $('.cover_image');
$(window).on('scroll', function() {
var st = $(this).scrollTop();
divs.css({
'opacity': (1 - st / 40)
});
});
(What is happening in the fiddle is the top div is going to opacity:0 as you scroll, revealing another div below it with the same background-image, but blurred. Creating the impression the same image is blurring the more you scroll)
In a web browser as you scroll the div drops in opacity progressively with a fade like affect which is great.
However in a mobile browser the change of opacity doesn't take effect until you release your finger from the the screen. So there is no progressive change of opacity. It only makes the changes visually as you release your finger from the screen, not as you scroll.
Is there a solution for this? I have tried adding in scrolling touch to my css, but it doesn't make a difference.
-webkit-overflow-scrolling: touch

Scrolling distance on mobile works very different from desktop. Even if you detect each step in the touch event, this is only half the truth. When the user releases, the site will continue to scroll for a bit while deaccelerating. This is called momentum scroll and will in most cases not be picked up by the touch event.
There are to my knowledge no perfect solution to this, since different devices handle scroll and touch very differently. There are however a few options you could look into.
Scrolling libraries
There are libraries to help you solve this problem. For instance one called scrollability that emulates scrolling to work more consistently.
Scrollability adds a good imitation of iOS native scrolling to your
mobile web apps.
Scrollability is a single script, it's small, and it has no external
dependencies. Drop it into your page, add a few CSS classes to
scrollable elements, and scroll away.
Ignore the scroll completely
Don't look at the touch or scroll events. Instead use setInterval or requestAnimationFrame with desired frequency that reports the pages current position (document.documentElement.scrollTop) at all time. Base your animation on this value instead of scroll or touch events. You might want to limit this to touch devices since it's not needed for desktop.
Write your own scroll functionality
Disable scrolling and make your own, without for instance momentum scroll, that is suited for your needs. Note that the scroll event is usually disabled on desktop if you disable scroll, but mousewheel works. I have been down this path and I would not recommend it. Instead you should probably go with the library approach at the top.

Related

jScrollPane on touch devices - drag button is in reverse

I've implemented jScrollPane and I'm having an issue on touch devices.
The example I'm using is http://jscrollpane.kelvinluck.com/drag_size.html where I have a vertical scroll using a circular button image for the scroll on the track. The class that's added to this is jspDrag.
On desktop, when you click and scroll the vertical button, it drags down and the content scrolls up, which is natural in my eyes.
The issue I'm facing is on touch devices (check the example URL above in Chrome using iPhone/iPad emulation in dev. tools) where you can't actually drag the button down - you actually have to scroll it up for the content to scroll?!
Users are definitely not going to know this as it's a button rather than a content block that you're using as a control.
I'd like to be able to touch and drag the button down on touch devices, rather than up, to make the content scroll.
Has any one come across this issue and managed to solve it? I've searched SO and Google Groups with no luck.
Thanks.
Unfortunately jScrollPane seems to just work like this, with an annoying caveat, which is unfortunate - I really liked the plugin.
I came across http://manos.malihu.gr/jquery-custom-content-scroller/ which functions the way it should and runs super smooth on touch devices.

Full page scrolling plugins (fullPage.js, scrollify.js, etc) prevents default mobile Safari UI behavior

On iOS devices, scrolling plugins like Scrollify.js, FullPage.js, and OnePage-Scroll.js seem to keep Safari's address and navigation bars in place, instead of the way they typically minimize when the user scrolls the page.
Is there any kind of workaround for this? I understand that when those UI bars minimize, the inner viewport height is changed, and so the plugin would need to recalculate the height. Also, the UI minimizes during the scroll event, and maybe that's problematic for the scrolling plugin? Is there a way to maybe hide the UI when the scroll event finishes?
When you change the orientation of the iPhone from portrait to landscape, the bars disappear, but if you bring them back by tapping the top or bottom, they stay put when you scroll.
I'd really like to have that extra height!
Is there any kind of workaround for this?
You can also use it without autoscrolling, but that might no be what you are looking for: autoScrolling:false.
If you are worried for the landscape mode, if you avoid using anchors and you load the page in portrait mode to then change to landscape, it won't show the top bar at all on iOS at least. Not the best solution, but it might help.
Personally I would recommend you to use the option responsiveWidth or responsiveHeight to change the behavior of the page on small screen devices and remove the auto scrolling and possibly have bigger sections.
In general, mobile browsers do not allow access to the top or bottom bars behaviors and there's no much developers can use to deal with them.

trigger scroll events on mobile momentum scroll

Not sure if I worded it correctly, but I am almost done with a workaround for creating sticky elements on mobile. So element is in doc flow then sticks to the top once it hits top of window. Waypoints.js does this but does not work very well on mobile.
So far I have been able to get it working normally on desktop (not a big deal), have been able to get it working on mobile touch scroll (kind of a big deal) but if the user lifts the finger off and the momentum scrolling takes over then the events don't fire until the momentum/scrolling stops.
Does anyone know how to make scroll events trigger during this momentum scroll?
This is what I did to make it work with touch scroll:
var stickyElementPosition = $('#thing-to-be-sticky').offset().top;
$(window).on("touchmove",function(){
var scrollPosition = $('body').scrollTop();
console.log(scrollPosition);
if(scrollPosition >= stickyElementPosition){
$('#thing-to-be-sticky').addClass('stuck');
}
else{
$('#thing-to-be-sticky').removeClass('stuck');
}
});
I made a JS fiddle but am not sure how to use it on a touch device. it just tries to scroll the entire page rather than the iframe/result.
link to fiddle

Synchronise multiple scroll div with inertia effect

I have multiple div which scroll at the same time. I had a css property to have the inertia effect on my all div (for safari on iPad) -webkit-overflow-scrolling: touch;. It works perfectly on the desktop web browser. But I have an effect that I want to change when i launch my webpage on my iPad.
The problem on ipad is : When i use the inertia effect, all div synchronize when the inertia effect is finished. I would like to have the same effect than the desktop web browser, that is, they are synchronized for the effect of inertia and not at the end.
You know, if there is a solution?
To complete my explanation, I created a : JSFiddle
As I know, CSS scrolling inertia on mobile devices cannot be handled with JavaScript. Element scroll event is fired when you scroll it by hand and when animation is finished. During animation no events are fired. So you have to emulate inertia with javascript to sync your divs (and this is not good idea).

Scroll event on Android Browser not firing. Need workaround

I've created a website with a parallax street scene. See here for an archived version.
It works just fine on all major desktop browsers, and Safari Mobile. It works fine in Mobile Firefox and Chrome for Android Beta also. However the default Android browser has issues with the scroll event. Let me be clear. Scrolling is not the issue. The div scrolls as required. The scroll event doesn't fire. This issue I experience on Honeycomb as well as ICS.
I'm not concerned about other mobile browsers because for mobile screen sizes one usually does not see the parallax scene; mediaqueries and conditional JavaScript loading take care of that. Responsive design and all that jazz.
Basically, I've written a parallise() jQuery plugin that positions each image based on its position and 'depth'. This function is bound to the scroll event.
On Android Browser, this event only fires at the start of the next touch, instead of continuously.
OK, so I thought that perhaps if I bound the function to touchstart, touchmove, and touchend events I would solve my issue. No cigar. Other touch events are also bugged. Applying the suggested workaround causes the events to fire, but as I have to e.preventDefault(), scrolling (the whole point of the exercise) is disabled.
What if I just poll the position of the stage div relative to the window div? Turns out that the position information is only updated at the start of the next touch.
I am at the end of my tether. Any help would be much appreciated.
Even if the touch events worked correctly on the bugged versions of Android, and you were then effectively able to track the native scroll position during a drag, this would be prone to error. For example, it wouldn't account for the momentum animation which happens after the touching has finished.
iOS and Android make sacrifices to improve the performance of scrolling. On both platforms, it's not possible to get the accurate scroll position until the scroll has completed. The scroll event (on the <body>) doesn't fire until the momentum animation is finished. So while your original question is about scroll events on an overflowing <div>, fixing this might not be totally helpful for you anyway.
If you want an animation to update in time with the scroll, then you need to perform the scroll programatically rather than using the browser's native scroll. The best library to do this is iScroll. You can achieve parallax effects very easily as seen in this demo.
If you need more complex effects (the walking character, in your example), you can opt for the "probe" version of iScroll which allows pixel-perfect polling of scroll position in return for reduced performance.
However, there are many downsides to using iScroll:
You may need to change your markup and styling
It is unnecessary overhead for desktop browsers, but due to markup changes may be difficult to use only as a fallback
The scrolling will not feel perfect - on iOS, with its usually excellent scrolling performance - the slight difference in momentum calculation can feel jarring. On Android, the scrolling can become more laggy than usual.
Swipe shim that doesn't need preventdefault on touchstart: https://github.com/TNT-RoX/android-swipe-shim

Categories