Closed stefanobergrussberger closed 11 years ago
Hi Stefano,
please provide a demo so I can have a look at it. :) (Although I suspect it might have something to do with the playoutAnimations option).
regards, J
Hi Jan,
thanks for the quick reply. Actually I tried playoutAnimations:false already but it didn't change anything. Here is my code so far:
// some animations
var tl= new TimelineLite();
for (var i = 3; i >= 0; i--) {
var tween = new TweenMax.to($('#veg'+(i+1)), i == 0 ? 0.3 : 0.4, {
css: {
marginLeft: 200
}
});
tl.add(tween, '-=0.3');
}
// append 2 divs moving in
var tweenIn1 = TweenMax.fromTo($('#textleft'), .3, {
css: {
top: '22%'
},
ease: Back.easeOut
});
tl.add(tweenIn1, '-=0.2');
var tweenIn2 = TweenMax.to($('#textright'), .3, {
css: {
left: 600
},
ease: Back.easeOut
});
tl.add(tweenIn2 , '-=0.1');
controller.addTween(500, tl);
// move divs back out
var tweenOut1 = new TweenMax.to($('#textleft'), 0.3, {
css: {
top: -200
}
});
controller.addTween(700, tweenOut1 );
var tweenOut2= new TweenMax.to($('#textright'), 0.3, {
css: {
left: $(window).width()
}
});
controller.addTween(700, tweenOut2);
...and sorry unfortunately I cannot provide a running demo. But maybe you can see already something in my code. I just noticed there was a fromTo-tween with only one object but that didn't cause it.
Ah, I guess, I know whats happening. When you scroll too fast the first tween is still running when the second is supposed to start. So what you'll need to do is tell TweenMax to overwrite other tweens if there are still running some. This can be achieved using the overwrite option of TweenMax. The Tweenmax Documentation says:
"auto" (2) - when the tween renders for the first time, it will analyze tweens of the same target that are currently active/running and only overwrite individual tweening properties that overlap/conflict. Tweens that haven't begun yet are ignored. For example, if another active tween is found that is tweening 3 properties, only 1 of which it shares in common with the new tween, the other 2 properties will be left alone. Only the conflicting property gets overwritten/killed. This is the default mode and typically the most intuitive for developers.
So what I think you should do is define your Tweens like this:
var tweenIn1 = TweenMax.fromTo($('#textleft'), .3, {
css: {
top: '22%'
},
overwrite: "auto",
ease: Back.easeOut
});
as an extra bonus tip note, that with the current version of TweenMax you dont have to use css options as an object anymore...
var tweenIn1 = TweenMax.fromTo($('#textleft'), .3, {
top: '22%',
overwrite: "auto",
ease: Back.easeOut
});
Thanks very much but unfortunately it still doesn't work. The doc says "auto" is default. But I tried it and the other values too but either the first tween gets killed completely or it stays with the wrong behaviour. I think I will just use different divs for the tweens for now.
...hm no it's not possible either. Even when I have only one div I still need to tween the same property in and out and there is the overwriting problem again... :(
I have had this issue happen a number of times with me as well, I took a 3 step approach to this, wrap all animations in a timeline, it is really easy to wrap a timeline inside of a timeline to make sure everything happens in a sequence, manually clean up bad animation with simple jquery function, ensure everything happens in the tweens by not having triggering elements also have animation happen to them.
I used timelineLite to wrap all tweens to make sure they finish and are handled. This seemed to help with my issues, even if I only have one animation for the tween I still put it in there. This also gives me onStart, onUpdate and onComplete ability to trigger functions to clean up some mess on animation. When I scrolled fast for example I would have multiple animations stuck in an active state. Most of my animations are progressively triggering display:block on display:none elements so I made a quick script to hide the siblings of the element. See code below, on every update the function runs to make sure no stuck frames in the animation. You could run this on just onComplete if you wanted, onUpdateScope lets me pass the jquery object I want to make sure $(this) is referencing so the function is really simple.
var timeLine1 = new TimelineLite({align: "sequence"})
.append([TweenMax.to($('#display-platform-list .frame-1'), 2, {css:{display:'block'},onUpdate:removeSiblings,onUpdateScope:$('#display-platform-list .frame-1')})])
.append([TweenMax.to($('#display-platform-list .frame-2'), 2, {css:{display:'block'},onUpdate:removeSiblings,onUpdateScope:$('#display-platform-list .frame-2')})])
.append([TweenMax.to($('#display-platform-list .frame-3'), 2, {css:{display:'block'},onUpdate:removeSiblings,onUpdateScope:$('#display-platform-list .frame-3')})])
.append([TweenMax.to($('#display-platform-list .frame-4'), 2, {css:{display:'block'},onUpdate:removeSiblings,onUpdateScope:$('#display-platform-list .frame-4')})])
.append([TweenMax.to($('#display-platform-list .frame-5'), 2, {css:{display:'block'},onUpdate:removeSiblings,onUpdateScope:$('#display-platform-list .frame-5')})])
.append([TweenMax.fromTo( $('#platform .callout'), 1, {css:{opacity: 1}}, {css:{opacity: 0}})]);
function removeSiblings(){
$(this).siblings().hide();
}
I am not sure how much this specific example applies to your situation but hope it gives you some ideas. I would also advise you not to mess with top and left when doing animations because this will confuse placements, try to use margins where possible.
Thanks a lot for the detailed advice. But now I don't move out the div anymore, I just fade it out and it's fine. Maybe I can use that later again...
I try it now in another place where I need to tween one property many times. One thing I just noticed: When I scroll slowly through the whole site once after page load and whatch tween after tween I can scroll very fast afterwards. No anmation gets stuck anymore. That doesn't really help me now but maybe you get a better idea what's happening...
I agree with jan here the issue seems to be TweenMax not superscrollorama. I was able to get this reset fine by using staggerFromTo and putting all the tweens in an array. I did notice your issue I just think your issue is more in how you are implementing your tweens stefan. My best suggestion at this point is to make sure you are on version 12 of the greensock code and review the documentation again http://api.greensock.com/js/
Hi Stefano,
I agree with James. Please follow his advice and if it still doesn't work, you'll have to provide some form of demo for us to be able to help you. If you cant show your production page just make a quick dummy where you show the phenomenon. Isolating the issue may even help you figuring out what the problem is yourself...
regards, J
Hi Jan, hi James,
thank you very much. Here is a little simple demo of what I'm trying to do. It's a container with position fixed and a div with position relative inside. The little div moves when I scroll. I tween marginLeft and marginTop. But as you can see when you scroll very fast it looks like the controller "forgets" some tweens.
Here the link: http://osmm.de/scrolldemo/
Thanks for looking at it!
and here a zip with the files: http://osmm.de/scrolldemo/scrolldemo.zip
Hi Stefano,
thank you for setting up the demo. This helps a lot.
I think I might understand now. To my mind superscrollorama does exactly what is supposed to, namely positioning the box exactly where it's supposed to be at the respective point in time. So if you go fast you won't see it going from left to right, but go to bottom instead (as that's the position it's supposed to be at at that point). Since you have playoutAnimations set to true sometimes this may cause it to animate differently than expected. (as the start position is not the end of the previous animation, but the position before that.) But even with playoutAnimations false the position can sometimes be wrong for the exact same reason.
What TweenMax.to does is always animate from the previous state.
To give you an example: ani 1 animates margin left to 750. previously it was 0 so it will animate to 750. ani 2 animates back to 0. ani 3 animates top to 750.
So obviously you expect the box to be at left 0, top 750 when finishing ani 3. But if you scroll fast enough to skip ani 2 completly the position will in fact be left 750, top 750. So try this code instead:
$(function ($) {
controller = $.superscrollorama();
controller.addTween(100, TweenMax.to($('#moving'), .3, {
marginLeft: 750,
marginTop: 0
}), 300);
controller.addTween(500, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 0
}), 300);
controller.addTween(900, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 750
}), 300);
controller.addTween(1300, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 0
}), 300);
controller.addTween(2000, TweenMax.to($('#moving'), .3, {
marginLeft: 750,
marginTop: 0
}), 300);
controller.addTween(2500, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 0
}), 300);
controller.addTween(2900, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 750
}), 300);
controller.addTween(3300, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 0
}), 300);
});
function log(msg) {
if (console != "undefined") console.log(msg);
else alert(msg);
}
Best regards, J
Hi Jan,
thanks for the code. Unfortunately it still behaves wrong (I tried that also in my project already). I updated the code in my example. When you try it you will see it still gets stuck somewhere in the middle when you scroll very fast the first time. When I scroll slowly once then it's fine, also when I scroll fast afterwards. It kind of looks like the tweens don't get registered when I scroll fast in the beginning.
Any other ideas?
Thank you!
Hi Stefano,
Hmm.. it IS kind of weird! I was almost going to say it works as it's supposed to but sometimes I get it to move diagonally... I am guessing it might have something to do with the fact that superscrollorama doesn't really care about past animations. But to be honest I am not really kean on investing a lot of time bugfixing superscrollorama, when I have the follower (ScrollMagic) already lined up. I will definitely use your demo to see how ScollMagic behaves with it, so please leave it online. As for fixing your issue I would recommend trying to leave nothing to coincidence. Try this bulky but quite surely working code:
$(function ($) {
controller = $.superscrollorama();
controller.addTween(100, TweenMax.fromTo($('#moving'), .3, {
marginLeft: 0,
marginTop: 0
},
{
marginLeft: 750,
marginTop: 0
}), 300);
controller.addTween(500, TweenMax.to($('#moving'), .3, {
marginLeft: 750,
marginTop: 0
},
{
marginLeft: 0,
marginTop: 0
}), 300);
controller.addTween(900, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 0
},
{
marginLeft: 0,
marginTop: 750
}), 300);
controller.addTween(1300, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 750
},
{
marginLeft: 0,
marginTop: 0
}), 300);
controller.addTween(2000, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 0,
},
{
marginLeft: 750,
marginTop: 0
}), 300);
controller.addTween(2500, TweenMax.to($('#moving'), .3, {
marginLeft: 750,
marginTop: 0,
},
{
marginLeft: 0,
marginTop: 0
}), 300);
controller.addTween(2900, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 0
},
{
marginLeft: 0,
marginTop: 750
}), 300);
controller.addTween(3300, TweenMax.to($('#moving'), .3, {
marginLeft: 0,
marginTop: 750,
},
{
marginLeft: 0,
marginTop: 0
}), 300);
});
function log(msg) {
if (console != "undefined") console.log(msg);
else alert(msg);
}
Hey Stefano!
Did this sort things out for ya?
regards, J
Hi Jan,
yes thanks, it's okay for now.
Thank you!
Hi Jan,
I added a timeline with some animations for a div at scrollposition 500. At 700 there is another tween on the same div, moving it back. When I scroll slowly, everything works fine. When I scroll fast past 700 it looks like the timeline is still finishing it's tweens and so the div doesn't move back. I tried already listening for onStart at the second tween and stop the timeline there but that didn't work very well.
Is there another solution for that?
Thank you!