Jump to content
GreenSock

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

Animating and controlling image sequence

Recommended Posts

Hi

 

Thanks in advance for any responses.

 

I am trying to figure out what is the best way to load a large image sequence (300 images representing a 3d movie) and control it using TimelineMax or simply staggerTo.

 

I used to do these things super easy with Loadermax (loading the image list from XML) and tweening it.

 

I have no idea how to do generate this array of images using javascript.

 

Please help.

 

Fernando.

Link to post
Share on other sites

Hi,

 

There currently aren't any loading tools built into the GreenSock Animation Platform JS version.

 

I know there is preloadJS from the createJS folks:

http://createjs.com/#!/PreloadJS

 

Don't know if they have an XMLLoader equivalent but you might want to start there. I imagine there has to be a library or even jQuery plugin that can load and track the progress of a bunch of images. You may need to break the task up into a few processes like:

 

1: load an xml file

2: build an array of image urls from the xml data

3: pass the image array into a tool like preloadJS

 

Really makes me appreciate the convenience of LoaderMax and Flash;)

 

 

 

S

Link to post
Share on other sites

Hi,

Thanks for the reply. Ok I got the whole thing working (not with a loader).

 

I am fading opacity to 1 for each div to simulate the image sequence. Problem is that fading in those in top of one another kills my memory. I am trying to figure out a way to fade back to 0 the previous frame.

 

Here is a snippet of the code and the files are attached,

 

function createATimeline () {
var j = 0;
var children = document.getElementById('chartHolder').childNodes;
for (var j = 0; j < children.length; j++) {
chartTimeline.append( TweenMax.to(children[j], 1, {css:{autoAlpha: 1}}) );
}
}

 

 

What I'd like to do is fade the previous image... I hope it makes sense.

 

See the example online

 

http://clients.letsm...c/ri-chart.html

Link to post
Share on other sites

to fade the previous image you can just make each TweenMax repeat and yoyo.

 

alpha 0 to 1 and then 1 to 0

 

if you offset each append by -1 second the new image will fade in while the previous image is fading out.

 

chartTimeline.append( TweenMax.to(children[j], 1, {css:{autoAlpha: 1}, repeat:1, yoyo:true}), -1 );

 

 

you could also add a repeatDelay so that the fade out doesn't happen until after the new image comes in. lots of flexibility.

 

That said, I'd be curious to hear if setting the autoAlpha of previous images to 0 really helps performance. Your current animation had my cpu pegged and both chrome and safari struggled greatly.

 

In all seriousness have you considered an animated gif?

 

http://dailypicksand...icture-gallery/

http://creativebits....les/chart_0.gif

http://betabeat.com/...-via-anil-dash/

 

I bet you could get a much smoother effect, smaller file size and of course way less server requests.

 

If you were using TweenLite to animate the chart via canvas or something like raphael.js I would totally endorse that. Regardless of how well optimized TweenLite is, managing the display of 300 large images seems like a lot of work for the browser.

 

I wish you the best. Let us know if the performance gets better.

Link to post
Share on other sites

Hey man! Thanks again.

 

I am going to explore my options.

 

Right now I think is working like I want it. Still some performance issues.

 

I think on exploring gif. Can I control a gif with gsap?

 

Also I feel Raphael a viable option, do you mean importing assets and animating or recreate the illustrator vector graphics in canvas?

 

Is that better?

 

You are so helpful in a crunch time. Appreciated

Link to post
Share on other sites

Hi Kranke,

 

I don't think you can control a gif with javascript, although I haven't researched it.

 

As far as using raphael.js or canvas I was just throwing them out there as possibilities. I'm sure both of them are up to the task. Not so sure which one will work better for you or be easier to implement. I've been impressed with how well raphael.js works in a large range of browsers.

 

Here is an interesting article: http://www.sitepoint.com/canvas-vs-svg-how-to-choose/

Link to post
Share on other sites

Like we used to do with AS3, it works equally well in JavaScript. All you do is preload the images into an array of image objects (in sequential order) and then access those images in the array sequentially via a timer or update type of event handler. Even mouse move events can control the position of the array image that is shown thus allow for interesting control of the image sequence animations.

 

You could also use jQuery and/or Greensock JS or regular old school JS to swap images out (or cycle through the images in any number of ways with CSS and HTML/JS) to essentially play the array of images in a simulated 'movieclip' or 'sequence'.

 

The interval between "showing" the images equates to your frames per second, like a 100ms timer would equate to roughly 10fps.

 

dynamic_image_sequence.zip

 

One way I like to do this is preload all of the images and contain the visible image inside a <div> tag and then swap them with an interval timeout that fires off showing the next image in the array while hiding the currently shown image, thus giving the illusion of a pseudo-sequence/movieclip. It's old school, but very reliable and rather simple as shown in my minimalist example ZIP above.

  • Like 2
Link to post
Share on other sites

Thanks Randall, I just took a peak at the source. Very clean and simple approach. I've evernote-d this for future reference.

  • Like 2
Link to post
Share on other sites

Wow! Do not know how long this narrower start posting in the comment: 'Wow!' But the truth is that GSAP is another world, is on another level. Congratulations! 
 
Well, playing around with image sequences. I also wondered how well an animation control. An example of how everylastdrop.co.uk transformation in scroll: 27700, car to spaceship. How to do an animation frame by frame, and control the timeline? 
 
I think the first thing would have loaded all the images of the sequence, before assigning any animation, and then using javascript magic (arrays, loops, and TweenMax n TweenlineMax) and some css to switch background-image prop

 

See it working: http://camal3on.globat.com/gs/

<div style0"width:80%;margin:100px auto;">
  <div id="basket">
    <div id="bskt-player">
      <div id="bskt-ball"></div>
    </div>
    <a href="#" class="play">play()</a>
    <p id="time-speed"></p>
  </div>
</div>
 

The css:

#basket{position:relative;border:1px solid red;width:80%;margin:50px auto;overflow:hidden;}
#basket #bskt-player{float:left;width:97px;height:124px;border:1px solid red;margin:20px autp;position:relative;background-image:url(img/bskt0001.png);background-position:0 0;background-repeat:no-repeat;background-color:transparent;}
#bskt_frames{position:right;padding:0 15px;margin-left:110px;background-color:#ededed;width:auto;margin-top:-95px;}
#bskt_frames span{display:inline-block;vertical-align:top;float:left;margin-right:10px;}
#bskt_frames span img{max-width:30px;}
#time-speed{position:absolute;top:0;right:0;border:1px solid green;margin:2px;}
#bskt-ball{background-color:#000;width:9px;height:9px;border-radius:50%;position:absolute;z-index:1;top:20px;left:60%;opacity:0;}
.play{float:left;display:block;width:70px;text-align:center;}

.cf:before,.cf:after {content:"";display:table;}
.cf:after {clear:both;}
/**
 * For IE 6/7 (trigger hasLayout)
 */
.cf {*zoom:1;}
 

JS:

$(document).ready(function($) {	
		
// Animate image secuence: 
  var _basket = $("#basket");
  var bskt_count = 0;
  var bskt_frames = [ // image and time_per_frame			    [1,1], [2,1], [3,1], [4,1], [5,1],
		[6,1], [5,1], [4,1], [3,1], [2,1], 
		[1,1], [2,1], [3,1], [4,1], [5,1],
		[6,1], [5,1], [4,1], [3,1], [2,1], 
		[1,1], [2,1], [3,1], [4,1], [5,1],
		[6,1], [7,1], [8,10], [9,4], [10,1], 
		[11,1], [12,10]
	]
  TweenMax.to(_basket.find('#bskt-player'),0.5,{
      backgroundImage:"url(img/bskt0001.png)", //default
      width:200, repeat:1, yoyo:true,
      onComplete:doneBskt,
      onCompleteParams:['{self}','complete']
  });
			  
  var tlBskt = new TimelineMax({paused:true,repeat:3,yoyo:true});
		
function doneBskt (evt,type){
	if(type == 'complete'){
	// add Tween to timeline
	for (var i=0;i<bskt_frames.length;i++){
	  var timeout = (bskt_frames[i][1]/10);
	  var _curr = (bskt_frames[i][0]<10)?'000':'00';
	  _curr += bskt_frames[i][0]+'.png';
	  var _img = "url(img/bskt"+_curr+")";
	  tlBskt.add( TweenMax.to($("#bskt_frames span:eq("+i+")"),0.01,{'backgroundColor':'yellow',overwrite:'all',delay:timeout}) );
	  tlBskt.add( TweenMax.to(_basket.find('#bskt-player'),0.01,{backgroundImage:_img},"+="+timeout ) )
			}
	// Final tween The Ball flying... I believe I can fly ;)'
	tlBskt.add( TweenMax.to('#bskt-ball',1,{top:-10,left:"-=50",autoAlpha:1,delay:-1}) );
	// then play...
	tlBskt.play();
	}}
		
	// Some jquery
	_basket.append('<div id="bskt_frames"></div> <div class="cf"></div>');
	$.each(bskt_frames,function(i){
	  var _curr = (bskt_frames[i][0]<10)?'000':'00';
	  _curr += bskt_frames[i][0]+'.png';
	  var _img = 'img/bskt'+_curr;
	  _curr += ', ('+bskt_frames[i][1]+')';
	  // console.log(i+' de '+bskt_frames.length+': '+_curr)
	  $("#bskt_frames").append("<span>"+_curr+" <img src='"+_img+"' alt=''> </span>  ");		
	});
	
	$("#bskt_frames").append('<div class="cf"></div>');
	
	var speed = 1;
	$('#time-speed').text('timeScale('+speed+')');
		
	$('a.play').on('click',function(e){
		  e.preventDefault();
		  speed = (speed<4) ? speed+1 : 1;
		  tlBskt.timeScale(speed);
		  tlBskt.restart();
		  if(speed==1)
		  TweenLite.to('#bskt-player',4,{rotation:-360});
		  else if(speed==2)
		  TweenLite.from('#bskt-player',2,{left:360,autoalpha:1,ease:Bounce.easeOut});
		  else if(speed==3)
		  TweenLite.from('#bskt-player',2,{scale:2,ease:Strong.easeIn,repeat:2,yoyo:true});
		  else
		  TweenLite.from('#bskt-player',2,{autoAlpha:0,delay:0.5,ease:Bounce.easeInOut});
		  
		  $('#time-speed').text('timeScale('+speed+')');
	});	
		
}); 
Link to post
Share on other sites

Hi guys,

 

Little bit late, but if it is help of anybody... Here is what I use when I want to preload sequence of images, or single image:

 

First, simple loadImage jQuery method:

$.loadImage = function(url) {
            var loadImage = function(deferred) {
                var image = new Image();
                image.onload = loaded;
                image.onerror = errored;
                image.onabort = errored;
                image.src = url;

                function loaded() {
                    unbindEvents();
                    deferred.resolve(image);
                }

                function errored() {
                    unbindEvents();
                    deferred.reject(image);
                }

                function unbindEvents() {
                    image.onload = null;
                    image.onerror = null;
                    image.onabort = null;
                }
            };
            return $.Deferred(loadImage).promise();
        };

This will return jQuery deferred, so we can do stuff like:

$.loadImage(someimageurl).done(function() {
            initAnimation();
        }).fail(function() {
            initAnimation();
        });

( for single image )

 

or 

$.when( $.loadImage("imagr1 url"), $.loadImage("image 2 url") ).done(function() { //some function });

( for two/multiple images ) 

 

I prefer this, because it will also listen for image errors

  • Like 1
Link to post
Share on other sites

I love it Chrysto!

 

I've been looking for a Promised-based asset loading example in the last few weeks, and that makes it really clear!

 

Is there some easier way to handle arrays of images? There was code at HTML5 Rocks that demos using Array.reduce to iterate over an array:

 

http://www.html5rocks.com/en/tutorials/es6/promises/#toc-creating-sequences

 

You got anything similar?

Link to post
Share on other sites

OK, I've been curious about this for ages, so here's my take on wrapping it up into a useful workflow:

 

https://gist.github.com/davestewart/39f626de39b57e6a132b

 

It adds a new method, $.loadImages, and allows you to add callbacks to both queue and image:

$.loadImages(urls, onDone, onFail, onLoad, onError);

Will have to look at PreloadJS too...

Link to post
Share on other sites

Hi Dave, this is nice. But if, for example, you have five images and the second is broken it will execute onFail() handler, without trying to preloading the rest of the images. If somebody is interested, we can make lightwave jQuery image preload utility... Will be in help for a lot of people here. 

Link to post
Share on other sites

Nope! It loads the rest of the images, and passes any failed images to onError.

 

Link to post
Share on other sites

Weird, it gave me different result when I was testing. Good work man, will investigate it later. 

Link to post
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.

×