Jump to content
Search Community

Resizing a container with multiple tweens inside of it

mattmoon test
Moderator Tag

Recommended Posts

I have a problem I am creating a slideshow that loads a group of images and places them into a TimeLineLite timeline before the slideshow is ran. I have the slideshow running appropriately but I need to be able to resize the container that is displaying the images. the structure looks something like this:

 

Slideshow - Class extends Sprite

- BG - Sprite

- container - Sprite

-- img 1 - Sprite

-- img 2 - Sprite

-- img 3 - Sprite

-- ect.

- masker - Sprite (masks the Slideshow sprite)

 

what i am trying to do is call a resize function on the Slideshow class the will resize the mask, bg, and the images inside the container appropriately and keep the slideshow moving the entire time. I can accomplish this when i do not play the timeline but when it is playing the images jitter.

 

the code that i am using for the resize is as follows:

 

From the outside class calling the resize function on the Slideshow

b = new Rectangle(0,0,480,270);
TweenLite.to(b,1,{delay:8,width:192,height:108,onUpdate:resizeImg});

private function resizeImg():void
{
    slideshow.resize(b.width,b.height);
}

here is the slideshow class that i am using to make the slideshow

package
{
import com.greensock.TimelineLite;
import com.greensock.TweenLite;
import com.greensock.easing.Linear;
import com.greensock.plugins.AutoAlphaPlugin;
import com.greensock.plugins.TweenPlugin;

import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.system.LoaderContext;

public class Slideshow extends Sprite
{
	/**
	 * Rotator Constants 
	 **/
	private const TRANSITION_TIME:Number = 1;
	private var DISPLAY_TIME:Number = 5;
	private var DURATION:Number = 42.748
	private const EASE_TYPE:Function = Linear.easeNone;
	/**
	 * Transition Types 
	 **/
	private const RANDOM:String = 'random';
	private const FADE:String = 'fade';
	private const CROSSFADE:String = 'crossfade';
	/** 
	 * Arrays
	 **/
	private var images:Array = new Array();
	private var imageLoaders:Array = new Array();
	private var imageSlides:Array = new Array();
	private var loadedSlides:Array = new Array();
	private var imageAttributes:Array = new Array();

	public var timeline:TimelineLite;
	public var container:Sprite;
	private var masker:Sprite;
	private var loadingImage:Number;
	private var curImage:Number;
	private var imageTotal:Number;
	private var lastDir:Number = 0;
	private var frameRate:Number = 24;
	private var bg:Sprite;
	private var imgCont:Sprite;
	public function Slideshow(tgt:Sprite)
	{
		TweenPlugin.activate([AutoAlphaPlugin]);
		timeline = new TimelineLite({useFrames:true});
		timeline.paused = true;
		container = new Sprite();
		masker = new Sprite();
		masker.graphics.beginFill(0x000000);
		masker.graphics.drawRect(0,0,480,270);
		masker.graphics.endFill();
		bg = new Sprite();
		bg.name = 'bg';
		var g:Graphics = bg.graphics;
		g.beginFill(0x000000);
		g.drawRect(0,0,480,270);
		g.endFill();
		this.addChild(bg);
		this.addChild(container);
		this.addChild(masker);
		this.mask = masker;
		init();
	}

	private function init():void
	{
		setImages();
		curImage = 0;
		loadingImage = 0;
		imageTotal = Math.ceil(DURATION/DISPLAY_TIME);
		loadImage();
	}

	private function setImages():void
	{
		images.push("http://videocache.pod0.sister.tv/PA/6/e/9/6e9cfe49-3f67-4644-a4b0-59eae7c7b921.jpg");
		images.push("http://videocache.pod0.sister.tv/PA/0/1/9/01932e7e-b2c6-423f-847d-37c1135ab76b.jpg");
		images.push("http://videocache.pod0.sister.tv/PA/0/d/7/0d740c4a-2bb3-4a31-a8f9-5311afc0d57f.jpg");
		images.push("http://videocache.pod0.sister.tv/PA/4/b/8/4b8100ce-1754-4cb5-9a22-06c24cf68ff2.jpg");			
	}

	private function loadImage():void
	{
		var ldr:Loader = new Loader();
		var ctx:LoaderContext = new LoaderContext(true);
		var img:String = images[loadingImage];
		imageLoaders.push({loader:ldr});
		ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,imageLoaded);
		ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,imageFailed);
		ldr.load(new URLRequest(img),ctx)
	}

	private function imageLoaded(e:Event):void
	{
		var loader:Loader = Loader(e.target.loader);
		var image:Bitmap = Bitmap(loader.content);
		var obj:Object = {image:image.bitmapData};
		imageSlides.push(obj);
		addItem();
		loadNextImage();
	}

	private function imageFailed(e:IOErrorEvent):void
	{
		loadNextImage();
	}

	private function loadNextImage():void
	{
		loadingImage++;
		var loadLength:Number = imageTotal < images.length ? imageTotal : images.length;
		if(loadingImage < loadLength)
		{
			loadImage();
		}else
		{
			if(curImage < imageTotal)
			{
				var left:Number = imageTotal - curImage;
				while(left > 0)
				{
					addItem();
					left--;
				}
			}
			timeline.timeScale = timeline.duration / convertSeconds(DURATION);
			dispatchEvent(new Event(Event.COMPLETE));
		}
	}

	private function addItem():void
	{
		/* Build Sprite */
		var isStatic:Boolean;
		var s:Sprite = new Sprite();
		var currentImage:Object;
		if(curImage == 0 || curImage == imageTotal - 1)
		{
			isStatic = true;
			currentImage = imageSlides[0];
		}else
		{
			isStatic = false;
			currentImage = imageSlides[curImage % imageSlides.length];
		}
		var b:Bitmap = new Bitmap(currentImage.image);
		b.smoothing = true;
		s.addChild(;
		s.alpha = 0;
		Stretcher.stretch(s,masker.width,masker.height,Stretcher.PANFILL);
		container.addChild(s);
		var imageObject:Object = new Object;
		imageObject.image = s;
		imageObject.direction = getDirection();
		imageObject.params = setSlideParams(imageObject,isStatic);
		imageAttributes.push(imageObject);
		/* Add Item to timeline */
		addToTimeline(imageObject,isStatic);				
		curImage++;
	}

	private function addToTimeline(img:Object,noMovement:Boolean=false):void
	{
		var trans:Array = [FADE,CROSSFADE];
		var itm:Number = curImage == 1 ? 1 : Math.floor((Math.random()*2)-1) + 1;
		var offset:Number;
		switch(trans[itm])
		{
			case FADE:
				offset = 0;
				break;
			case CROSSFADE:
				offset = -1;
				break;
		}
		var duration:Number = convertSeconds(DISPLAY_TIME - offset);
		var Delay:Number = duration - convertSeconds(1);
		if(noMovement)
		{
			timeline.appendMultiple([
				TweenLite.to(img.image,duration,{x:"0",y:"0",ease:Linear.easeNone}),
				TweenLite.to(img.image,convertSeconds(1),{alpha:1}),
				TweenLite.to(img.image,convertSeconds(1),{alpha:0,delay:Delay})
			],convertSeconds(offset));
		}else
		{
			timeline.appendMultiple([
				TweenLite.to(img.image,duration,{x:img.params.dX,y:img.params.dY,ease:Linear.easeNone}),
				TweenLite.to(img.image,convertSeconds(1),{alpha:1}),
				TweenLite.to(img.image,convertSeconds(1),{alpha:0,delay:Delay})
			],convertSeconds(offset));
		}
	}

	private function setSlideParams(obj:Object,isStatic:Boolean):Object
	{
		var o:Object = new Object();
		var direction:Number = obj.direction;
		var tgt:Sprite = obj.image;
		if(direction == 1) 
		{ 
			o.sX = Math.ceil((masker.width - tgt.width)/2);
			o.sY = 0;
			o.dX = String(0);
			o.dY = String(masker.height - tgt.height);
			//BOTTOM TO TOP
		} else if (direction == 2) 
		{
			o.sX = Math.ceil((masker.width - tgt.width)/2);
			o.sY = masker.height - tgt.height;
			o.dX = String(0);
			o.dY = String(-(masker.height - tgt.height));
			//LEFT TO RIGHT
		} else if (direction == 3) 
		{
			o.sX = masker.width - tgt.width;
			o.sY = Math.ceil((masker.height - tgt.height)/2);
			o.dX = String(-(masker.width - tgt.width));
			o.dY = String(0);
			//RIGHT TO LEFT
		} else if(direction == 4)
		{
			o.sX = 0;
			o.sY = Math.ceil((masker.height - tgt.height)/2);
			o.dX = String(masker.width - tgt.width);
			o.dY = String(0);
		}
		if(!isStatic)
		{
			tgt.x = o.sX;
			tgt.y = o.sY;
		}else
		{
			tgt.x = Math.round(masker.width/2 - tgt.width/2);
			tgt.y = Math.round(masker.height/2 - tgt.height/2);
		}

		return o;
	}

	private function getDirection():Number
	{
		var dir:Number = Math.floor((Math.random()*4)+1);
		if(dir != lastDir)
		{
			lastDir = dir;
			return dir;
		}
		return getDirection();

	}

	private function convertSeconds(n:Number):Number
	{
		return n * frameRate;
	}

	public function resize(w:Number,h:Number):void
	{
		trace("--BEFORE--");
		trace("CONTAINER",container.width,container.height,container.x,container.y);
		trace("MASKER",masker.width,masker.height,masker.x,masker.y);
		trace("BG",bg.width,bg.height,bg.x,bg.y);
		trace("----------");
		masker.width = bg.width = w;
		masker.height = bg.height = h;
		var curTime:Number = timeline.currentTime;
		timeline.kill()
		timeline = new TimelineLite({useFrames:true});
		curImage = 0;
		for(var i:Number = 0; i < imageAttributes.length; i++)
		{
			var isStatic:Boolean = false;
			if(curImage == 0 || curImage == imageTotal - 1)
			{
				isStatic = true;	
			}
			var img:DisplayObject = imageAttributes[i].image;
			Stretcher.stretch(img,masker.width,masker.height,Stretcher.PANFILL);
			imageAttributes[i].params = setSlideParams(imageAttributes[i],isStatic);

			/* Add Item to timeline */
			addToTimeline(imageAttributes[i],isStatic);
			curImage++;
		}
		timeline.timeScale = timeline.duration / convertSeconds(DURATION);
		//timeline.currentTime = curTime;
		timeline.play()
		trace("--AFTER--");
		trace("CONTAINER",container.width,container.height,container.x,container.y);
		trace("MASKER",masker.width,masker.height,masker.x,masker.y);
		trace("BG",bg.width,bg.height,bg.x,bg.y);
		trace("---------");
	}
}
}

 

What i am doing on resize is actually killing the timeline and creating a new one since the properties of each images movement is predetermined before the timeline is created. I get a start X and Y position and then determine how far each image has to move then use those numbers to populate the tweens for the timeline. I get the current position of the old timeline and store that number to be used to reset the new timeline to the right position and repeat that every time the resize event is called. It is very jittery and am wondering if there is a better way of going about this. I just purchased a Shockingly Green membership to the Greensock club. And am wondering if the dymaincProps plugin could help. I could really use some assistance on this as this is an important piece to a very large product being built with a LOOMING DEADLINE!

 

Thanks in advance!

 

Matt Moon.

Link to comment
Share on other sites

Hey Matt. First of all, welcome to the club. Thanks so much for the support.

 

Your code is definitely requiring a lot of processing power the way you structured it (recreating all the animations on every frame during the resize with many function calls). That explains the stuttering. Plus masks are very expensive in terms of performance as well (you might want to look into using scrollRect instead). Typically this forum is for answering relatively straightforward questions about GreenSock stuff, but it looks to me like your code is in need of a fair amount of restructuring and strategic optimization. This is beyond the scope of what I typically provide for free in these forums. If you'd like some consulting help, please ping me via e-mail or PM and we'll talk scheduling.

 

Oh, and dynamicProps probably wouldn't be the best tool for this. I think there are other strategies that could significantly reduce the strain on the CPU, but it's not a simple "add this magic special property to your tweens" kind of thing. From what I can tell, tweening isn't the problem here. It's the structure of the code that's creating the tweens and adjusting the values. Again, I wish I had a simple do-it-yourself fix for you :(

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.
×
×
  • Create New...