janpaepke / ScrollMagic

The javascript library for magical scroll interactions.
http://ScrollMagic.io
Other
14.9k stars 2.17k forks source link

Parallax Sections - Jitter on OS X (Chrome, Safari, FF) and iPad #256

Closed maximilianschmidt closed 9 years ago

maximilianschmidt commented 9 years ago

noticed that a jitter occurs on you parallax sections example parallax sections example while scrolling (either with mouse, trackpad or using the scrollbars) on Mac OS X Chrome 41.0.2272.74, Safari 8.0.3 and iPad iOS 8 Safari. checked on my co-workers windows computer, same jitter occurs. any ideas on how to fix that?

thanks!

krnlde commented 9 years ago

Possible duplicate of #255 #247 #218 #186 #167

aevanson commented 9 years ago

I don't think this is a duplicate of #218, #186 or #167. They have been marked as resolved, yet the newest code and example from the docs still have the jitter. I'm seeing this on a Mac with Chrome, FF and Safari.

janpaepke commented 9 years ago

Sorry for the delayed answer, I was on holidays...

I can confirm that I can reproduce this on Safari. I'll check it out.

whatnickcodes commented 9 years ago

There's probably a deeper / better explanation to why this is suddenly happening related to recent browser updates. For example, CSSOM-View scroll behavior for smooth scrolling was just implemented in FF 36 - whatever that is. I really have no idea what is causing this. Old behavior that used to be ultra smooth has suddenly become jittery (ScrollMagic 1.3 and 2.0).

I find this mainly happening on pixel doubled screens and when a background image is present. The obvious signs are performance related from this. For now, you can fix the issue by:

It at least worked for me in some cases, but is still not perfect. Here's some examples (non-mobile) of Parallax with ScrollMagic 2.0 that operates without jitter: https://scotch.io/demos/animated-article-headers-blur

I'll keep everyone updated if I come across anything new related to this.

janpaepke commented 9 years ago

Okay so I tried to close in on this.

First I tried to remove ScrollMagic alltogether. This pen uses neither ScrollMagic, nor TweenMax: http://codepen.io/janpaepke/pen/raQdEr It seems smooth in Chrome and Firefox. But it's still jittery (although not as much) in Safari. I have no idea why but my guess is this (in an amplified version due to code complexity) is what's happening when using ScrollMagic as well.

I'll keep investigating this and keep you posted. Any input is welcome.

janpaepke commented 9 years ago

On FF and IE possibly resolved in https://github.com/janpaepke/ScrollMagic/issues/255#issuecomment-82322149. Issue remains in Safari.

Confirmations?

dpfranklin commented 9 years ago

Issue remains in Chrome with v2.0.1. Resolved in FF.

janpaepke commented 9 years ago

Ok so here's something really weird I observed. If I open http://janpaepke.github.io/ScrollMagic/examples/advanced/parallax_sections.html in Chrome 41.0.2272.89 and scroll down it works without jitter. If I scroll down even a little bit and then hit reload there is a very noticeable jitter when scrolling with mousewheel or trackpad. If I scroll back to the top and reload it works fine again.

This is weird! Can anyone confirm this?

On Chrome canary 43.0.2337.0 the jitter occurs regardless...

I will try to get to the bottom of this...

shivaalroy commented 9 years ago

I can confirm the behavior you are seeing on Chrome Version 41.0.2272.89 (64-bit).

jaydickinson commented 9 years ago

Can confirm this also in chrome 41.0.2272.101 (64-bit)

I've smoothed the native scroll with a script I found in the mean time and then the parallax runs a lot smoother, although this is a nasty hack as I'd rather keep native scrolling.

http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/ScrollToPlugin.min.js

 $(function(){   
        var $window = $(window);
        var scrollTime = 1.2;
        var scrollDistance = 185;

        $window.on("mousewheel DOMMouseScroll", function(event){
            event.preventDefault(); 
            var delta = event.originalEvent.wheelDelta/120 || -event.originalEvent.detail/3;
            var scrollTop = $window.scrollTop();
            var finalScroll = scrollTop - parseInt(delta*scrollDistance);
            TweenMax.to($window, scrollTime, {
                scrollTo : { y: finalScroll, autoKill:true },
                    ease: Power1.easeOut,
                    overwrite: 5                          
                });
        });
    });
janpaepke commented 9 years ago

Parallax Jitter bug should be removed in Chrome and Firefox. Safari and IE have some performance issues (IE especially), which we continue to try to resolve.

supermoos commented 9 years ago

This is a really nice library, but this performance problems is pretty much a roadblocker :-(

krnlde commented 9 years ago

Which perf probs in particular?

supermoos commented 9 years ago

The jitter on safari and mobile safari. Also pinning on mobile safari is unreliable and jumpy because an upwards scroll on the iPad triggers the adress bar to change height causing jumping behaviour of position: fixed; elements :-( But the interface and structure of this library is super easy, sadly it needs a little more on the performance side to be really perfect.

krnlde commented 9 years ago

These aren't perf issues at all. The performance issues jan mentioned are related to Safari and IE (due to their repaint to be exact), not ScrollMagic. The above problems are directly related to the new subpixel calculations the browser vendors began to implement recently (about 1 year ago, https://code.google.com/p/chromium/issues/detail?id=360889). We however try to tackle those browser unsimilarities.

dpfranklin commented 9 years ago

Its unlikely that Chrome, IE and Safari will address this relatively obscure edge case anytime soon. It may indeed be a "browser bug" - but the result is ScrollMagic is unusable in its current state.

supermoos commented 9 years ago

@dpfranklin basically my point, it's probably useable to someone, but if 60 fps is the target, then we fall very short of this right now, and notice should probably put in the readme for now until the problem can be solved, if ever...

krnlde commented 9 years ago

It is not an fps issue! The jitter is due to a delay between the browser's internal repaint an the execution of callback where ScrollMagic calculates the current offset. If these things do not happen at the same event loop you will see jitter, despite having it running at 60fps.

janpaepke commented 9 years ago

Hi Guys, I hope to settle this issue a little bit.

ScrollMagic is first and foremost a scroll-interaction library (as stated in its tagline). NOT a parallax library. Parallaxing is just one of the things you can do with it. There are other libraries solely focussing on parallax and - as far as I know - they are subject to the same browser limitations, unless you use something like the keith css approach.

In this light @dpfranklin is right to the point, that it MIGHT be unusable for parallax applications, but so would every other library out there. Which would make parallax unusable, not ScrollMagic.

Our research indicates that there are some pretty real browser limitations, particularly in IE and Safari. With IE this is due to excessive unnecessary repaints, as explained here and with Safari it seems to be a bug built into scrolling in Mavericks, particularly for retina displays (read more on this here). And as I said before those are issues that apply to other libraries as well. Check this page for example, build with adobe muse.

The important part to note here is the point @krnlde tried to make: It's not a performance issue with ScrollMagic, but the browsers not doing their job properly. I can assure you hours and hours went into making ScrollMagic as fast as possible.

If there are workarounds for these browser quirks, we of course try to implement them, like with the recent fix for chrome in 2.0.3. This one especially is an obvious browser bug, and we are in contact with the chrome developers to resolve it.

Bottom line is: We can't drive faster than the car's engine is built to run, unless we get a better car. If there's ways to tweak the driver we'd love to do it, but we'd have to know what tweaks really work. And there are limitations to that (for example if making one tweak would improve performance for one browser, but make it worse for others).

So if you find libraries, demos or pages that run these types of things reliably smooth on Safari or IE, please do share them. We will try to deconstruct them and see if we can incorporate the behavior into ScrollMagic. Better yet: Get into the issue, do some research, find the potential source of the problem in ScrollMagic's code and try to make this library better. It is open source after all. :)

supermoos commented 9 years ago

@janpaepke great response. I see your point, and I haven't looked at the inner workings of ScrollMagic enough to make suggestions to solving it, and I guess you have already given it a very thorough try. But for others looking to alternative solutions (until browser vendors hopefully get fixes out) I can highly recommend reading the different proposals here: http://www.html5rocks.com/en/tutorials/speed/parallax/

Right now I am going for a solution that combines the 3 suggestions in that post; combining a fixed positioned div with a body that has a fixed height corresponding to the content's total length, then using Greensocks TimelineMax and tweening the progress of the timeline to correspond to the scroll events fired when scrolling the body. This way it's like a timeline where you just scrub through it using scroll input, and this scrubbing can then be tweened and eased to give a smooth 60 fps experience. The one major drawback is that you have to do workaround's if you want to say; tween a 400x3000px div on an iOS device using transforms, because iOS has a texture limit that results in poor performance of large textures like a 400x3000 px div.

I hope the above quick & dirty explanation of an alternative approach might help someone who's out for the 60 fps solution. But hopefully this will be fixed at some point by browser vendors...

janpaepke commented 9 years ago

Well the technique you describe is essentially how ScrollMagic handles it. :) And what still didn't seem to have come across: It's not a code performance problem. It runs at 60fps. Even if something looks jittery at 60fps it's still jittering at 60fps.

I wish all the best of luck to you, but my suspicion is that you are going to run into troubles with safari as well pretty soon. But if not, even better!

In any case we'd love to see your results and findings.

supermoos commented 9 years ago

Well not at the moment, I'll post the finished project, then you can inspect it. Everything runs fine in both IE, Safari, iOS, Chrome and Firefox, though I'm only targeting latest browser versions.

supermoos commented 9 years ago

If you want to I can show it to you privately, just cannot publish a link to the project at this moment.

janpaepke commented 9 years ago

sure. just send me an email...

janpaepke commented 9 years ago

For the record: @lasseyls solution was to animate the parallax elements to the correct position, instead of hard-setting it. While this resulted in the loss of the direct link between scrollbar and image position, it did indeed remove the jitters in safari (for obvious reasons). The same can be done with ScrollMagic, for example by changing the code of the parallax_sections example to this:

// init controller
var controller = new ScrollMagic.Controller({globalSceneOptions: {triggerHook: "onEnter", duration: "200%"}});

function move (what, progress) {
    var to = progress * 80;
    TweenMax.to(what, 0.3, {y: to + "%", overwrite: 5, force3D: true});
}
// build scenes
new ScrollMagic.Scene({triggerElement: "#parallax1"})
                .on("progress", function (e) {
                    move ("#parallax1 > div", e.progress);
                })
                .addIndicators()
                .addTo(controller);

new ScrollMagic.Scene({triggerElement: "#parallax2"})
                .on("progress", function (e) {
                    move ("#parallax2 > div", e.progress);
                })
                .addIndicators()
                .addTo(controller);

new ScrollMagic.Scene({triggerElement: "#parallax3"})
                .on("progress", function (e) {
                    move ("#parallax3 > div", e.progress);
                })
                .addIndicators()
                .addTo(controller);

So while this might do the trick for some, this isn't really a solution to the real issue.

krnlde commented 9 years ago

Nice workaround though.