Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Dcoo

TimelineMax Image sequence flickers on Safari

Recommended Posts

Hi @Dcoo,

 

The reason is that the image src for each frame is being downloaded on demand (when the tween calls for it). You can try creating new image instances in your for loop to get the image into the browser's cache, like this.

 

See the Pen OJJYKmZ?editors=0110 by sgorneau (@sgorneau) on CodePen

 

Edit: in some tests here ... it's working, in other test, it's not. So, maybe a better option would be to actually add all the images to the DOM and tween then on/off. (CodePen to follow)

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

2 hours ago, Shaun Gorneau said:

Edit: in some tests here ... it's working, in other test, it's not. So, maybe a better option would be to actually add all the images to the DOM and tween then on/off. (CodePen to follow)

 

You weren't using a correct source for your image. This is better.

 

imgPreload.src= `https://fastsvgs.s3.amazonaws.com/imgseq/big/${imgIndex}.png`;

 

And those images were taking over a second each to load, so it's a bad demo to begin with as it could take several minutes to fully load.

 

But I do think using real images is much better than use a background src.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

18 hours ago, Shaun Gorneau said:

Hi @Dcoo,

The reason is that the image src for each frame is being downloaded on demand (when the tween calls for it). You can try creating new image instances in your for loop to get the image into the browser's cache, like this.

The reason is that the image src for each frame is being downloaded on demand (when the tween calls for it). You can try creating new image instances in your for loop to get the image into the browser's cache, like this.Thank you  so much for the help, I had been looking for an example of how to do this sequence for some time now, and this we the only one i could  find. If anyone knows of a better way I would  love to try it out :) ( i did try one with canvas but I could not get it to work well in Safari at all. )  

 

Edit: in some tests here ... it's working, in other test, it's not. So, maybe a better option would be to actually add all the images to the DOM and tween then on/off. (CodePen to follow)

Link to comment
Share on other sites

14 hours ago, OSUblake said:

 

You weren't using a correct source for your image. This is better.

 


imgPreload.src= `https://fastsvgs.s3.amazonaws.com/imgseq/big/${imgIndex}.png`;

 

And those images were taking over a second each to load, so it's a bad demo to begin with as it could take several minutes to fully load.

 

But I do think using real images is much better than use a background src.

Thanks for the reply, I do appreciate it!  Maybe i'm not putting that code in properly, but this seems to make the fliker worse in Safari and now it also does it in Chrome. also I'm not sure how to change it to real images? do you know of any examples I could  look at ?  and again!

Link to comment
Share on other sites

Here's a canvas animation. You just need to rework it a little. In the resizeCanvas function, get rid of the animation.play(), and add your scrolling code there.

 

function resizeCanvas(textures) {
   
  var texture = textures[0];  
  sprite.textures = textures;
  
  canvas.width = texture.naturalWidth || texture.width;
  canvas.height = texture.naturalHeight || texture.height;
  canvas.classList.add("is-loaded");
  
  var aspectRatio = canvas.height / canvas.width;
  
  // Make it responsive 
  TweenLite.set("#container", {
    paddingBottom: "calc(100% * " + aspectRatio + ")"
  });

  // We're ready to go!
  // animation.play(); 
  
  // add your scrolling code to change the animation timeline progress
}

 

See the Pen vpEQzY by osublake (@osublake) on CodePen

 

 

  • Like 2
Link to comment
Share on other sites

It might take a bit to load the first time. After that, the images will be cached, so it will load very fast.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

3 hours ago, OSUblake said:

It might take a bit to load the first time. After that, the images will be cached, so it will load very fast.

Thank You So  Much!!  This is fantastic!  It works amazingly well!! ( No flicker)

PS: how come your canvas works on Apple OSX and IOS, When so many people i've seen cant get ot to?( Very Impressive)

Link to comment
Share on other sites

3 hours ago, OSUblake said:

It might take a bit to load the first time. After that, the images will be cached, so it will load very fast.

Is there a pace to lean the ways to address controlling a timeline ?  I'm  just not sure how its controlled even in the original the timeline:

var tl = new TimelineMax({paused:true}); 

then the function calls   

tl.to( '#image-sequence' , dur , {css: {backgroundImage: imgUrl}} )

and then the scroll 

(window).scroll( function(){
    var scrollTop = $(window).scrollTop();
    var docHeight = $(document).height();
    var winHeight = $(window).height();
    if( scrollTop >= 0){
        tl.progress( scrollTop / ( docHeight - winHeight ) );
    }
  }
);

How does the scroll control the timeline? 

Link to comment
Share on other sites

1 minute ago, Dcoo said:

Is there a pace to lean the ways to address controlling a timeline ?

Our "Getting Started" video and article covers control methods of tweens and timelines. I recommend checking it out.

 

2 minutes ago, Dcoo said:

How does the scroll control the timeline?

In this example it does so in the tl.progress() call.

  • Thanks 1
Link to comment
Share on other sites

4 hours ago, OSUblake said:
Quote

In the resizeCanvas function, get rid of the animation.play(), and add your scrolling code there.

I'm not having much luck addinging the scrolling code.  I'm not sure how to call the timeline after taking out the  animation.play();  

function resizeCanvas(textures) {
   
  var texture = textures[0];  
  sprite.textures = textures;
  
  canvas.width = texture.naturalWidth || texture.width;
  canvas.height = texture.naturalHeight || texture.height;
  canvas.classList.add("is-loaded");
  
  var aspectRatio = canvas.height / canvas.width;
  
  // Make it responsive 
  TweenLite.set("#container", {
    paddingBottom: "calc(100% * " + aspectRatio + ")"
  });

  // We're ready to go!
  //animation.play(); 
}
$(window).scroll( function(){
    var scrollTop = $(window).scrollTop();
    var docHeight = $(document).height();
    var winHeight = $(window).height();
    if( scrollTop >= 0){
       animation.progress( scrollTop / ( docHeight - winHeight ) );
    }
  }

);

I am  probable way off

 

Link to comment
Share on other sites

15 minutes ago, Dcoo said:

I'm not having much luck addinging the scrolling code.

A demo would be helpful.

 

15 minutes ago, Dcoo said:

I'm not sure how to call the timeline after taking out the  animation.play();

Updating the .progress() updates the timeline so you don't have to play it. Think of it like a .set() call but affecting everything that the timeline affects at that point in time. It sets everything that the timeline affects to what it would be at that point in time.

  • Like 1
Link to comment
Share on other sites

13 minutes ago, ZachSaucier said:

A demo would be helpful.

 

Updating the .progress() updates the timeline so you don't have to play it. Think of it like a .set() call but affecting everything that the timeline affects at that point in time. It sets everything that the timeline affects to what it would be at that point in time.

I've tried to do that, but its not working for me.


See the Pen NWWZvYE by davicoo (@davicoo) on CodePen


 

Link to comment
Share on other sites

2 minutes ago, Dcoo said:

I've tried to do that, but its not working for me.

Look in your browser's console (F12 to get there): You will see errors. The first is Uncaught ReferenceError: $ is not defined because you didn't load jQuery but are attempting to use it.

 

Then you get errors on scrolling because the images haven't loaded yet. You can fix that by adding an if statement:

 

if(sprite.textures[sprite.frame]) {
  context.drawImage(sprite.textures[sprite.frame], 0, 0); 
  sprite.lastFrame = sprite.frame;
}

See the Pen dyyBmQP?editors=0010 by GreenSock (@GreenSock) on CodePen

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

1 minute ago, ZachSaucier said:

Then you get errors on scrolling because the images haven't loaded yet.

 

Yep. That's why I said to put the scroll listener inside the resizeCanvas function. @Dcoo was putting it outside.

 

This is how I did it.

 

function resizeCanvas(textures) {
   
  var texture = textures[0];  
  sprite.textures = textures;
  
  canvas.width = texture.naturalWidth || texture.width;
  canvas.height = texture.naturalHeight || texture.height;
  canvas.classList.add("is-loaded");
  
  var aspectRatio = canvas.height / canvas.width;
  
  // Make it responsive 
  TweenLite.set("#container", {
    paddingBottom: "calc(100% * " + aspectRatio + ")"
  });

  // We're ready to go!
  // animation.play(); 
  
  // Jump through progress to show first frame
  animation.progress(1).progress(0);
  
  // add scroll listener
  $(window).scroll(onScroll);
  
  // call onScroll in case page was scrolled during loading
  onScroll();
}

function onScroll() {
  var scrollTop = $(window).scrollTop();
  var docHeight = $(document).height();
  var winHeight = $(window).height();
  if( scrollTop >= 0){
     animation.progress( scrollTop / ( docHeight - winHeight ) );
  }
}

 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

10 minutes ago, OSUblake said:

Thank you, I get it  now!!  :)
 

Yep. That's why I said to put the scroll listener inside the resizeCanvas function. @Dcoo was putting it outside.

 

This is how I did it.

 


function resizeCanvas(textures) {
   
  var texture = textures[0];  
  sprite.textures = textures;
  
  canvas.width = texture.naturalWidth || texture.width;
  canvas.height = texture.naturalHeight || texture.height;
  canvas.classList.add("is-loaded");
  
  var aspectRatio = canvas.height / canvas.width;
  
  // Make it responsive 
  TweenLite.set("#container", {
    paddingBottom: "calc(100% * " + aspectRatio + ")"
  });

  // We're ready to go!
  // animation.play(); 
  
  // Jump through progress to show first frame
  animation.progress(1).progress(0);
  
  // add scroll listener
  $(window).scroll(onScroll);
  
  // call onScroll in case page was scrolled during loading
  onScroll();
}

function onScroll() {
  var scrollTop = $(window).scrollTop();
  var docHeight = $(document).height();
  var winHeight = $(window).height();
  if( scrollTop >= 0){
     animation.progress( scrollTop / ( docHeight - winHeight ) );
  }
}

 

 

  • Like 1
Link to comment
Share on other sites

Im wondering if there is a way to make the sequence have momentum as you scroll?  so it woud slow to a stop instead of stopping right away?    

Hey and Guys,  thanks again for all your help!

Link to comment
Share on other sites

2 minutes ago, Dcoo said:

Im wondering if there is a way to make the sequence have momentum as you scroll?  so it woud slow to a stop instead of stopping right away?

I'm guessing you're on Windows? Macs have that built into their native scrolling.

 

You can reference Blake's infamous smooth scrolling script 

 

Link to comment
Share on other sites

Oh sorry, no not momentum of the scroll bar itself, but the animation of the onscroll sequence, so it will play out some extra frames and slow to a stop.
the original canvas I was playing around with( link below: and this one doesn't work on a mac at all )  had something like this , I think its this bit here.

i'm wondering if TweenMax could do something similar ?  

// the throttled funtion
  function draw() {
    var e = evt;
    var delta = Math.max(-1, Math.min(1, e.deltaY));
    if (delta == -1) currentLocation += 1;
    if (delta == 1) currentLocation -= 1;
    if (currentLocation < 0) currentLocation = 0;
    if (currentLocation >= (totalImages - 1)) currentLocation = (totalImages - 1);
    setImage(currentLocation);
    evt = null; // so the throttler knows we can kick again
  }
}

See the Pen rNNRjge by davicoo (@davicoo) on CodePen

Link to comment
Share on other sites

Ah, I see. It's easy using the approach of the demo that I posted (and that Blake posted) above. Just change the ease of the animation tween to something not linear/none like "power2.out".

 

Using your approach, you'd have to calculate the ease yourself. A little out of scope for this forum since it's not a GSAP question. 

Link to comment
Share on other sites

I did try that, it didn't seem to do anything but make it less  smooth , unless i'm not putting it in correctly?

var animation = new TimelineMax({
  
    paused: true,
    onUpdate: drawSprite
  })
  .to(sprite, 1, { 
    frame: sprite.totalFrames - 1, 
    roundProps: "frame",
    ease: "power2.out"
  });

 i'll try a combo of that and smooth scrolling script smooth scrolling script 

 

Thank you!

Link to comment
Share on other sites

16 hours ago, Dcoo said:

I did try that, it didn't seem to do anything but make it less  smooth , unless i'm not putting it in correctly?

If you're using GSAP 2 then it'd be the object form of eases like Power2.easeOut. Sorry, I'm quite used to using the GSAP 3 form of eases at this point.

 

See the Pen WNbvZWK by GreenSock (@GreenSock) on CodePen

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×