Jump to content
GreenSock

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

proportional browser scaling

Recommended Posts

I have a gallery thats loading large images from thumbs. I want the large images to scale with the browser. Can I use LiquidStage for this? I have a blank movieclip on the stage named imgContainer which is the container for my large images I tried adding area.attach() to my imgContainer or even event.target.content and I get "Error: The parent of the DisplayObject imgContainer added to AutoFitArea instance55 doesn't share the same parent". Can anyone explain which instance should I add the area.attach() function to?

Link to comment
Share on other sites

Sure, but you don't really need that imgContainer. You can just drop them right onto the root/stage if you want (not that you have to). It'd look something like this (assuming your stage is 550x400):

 

var ls:LiquidStage = new LiquidStage(this.stage, 550, 400);
var la:LiquidArea = new LiquidArea(this, 0, 0, 550, 400);

var loader:ImageLoader = new ImageLoader("assets/1.jpg", {container:this, onComplete:la.update});
loader.load();

la.attach(loader.content, {scaleMode:"proportionalOutside", crop:true});

Link to comment
Share on other sites

Yea I thought I had tried something like that to test at first and it gave me the same error. Had something like this:

 

private function loadImage( index: Number ):void
	{
		ls = new LiquidStage(this.stage, 550, 419, 550, 419);
		area = new LiquidArea(this.stage, 0, 0, 550, 419);

		var file:String = xImgList[index]. @ url;

		var image:ImageLoader = new ImageLoader("assets/images/" + file, new ImageLoaderVars()
		.container( imgContainer )
		.x(0)
		.y(0)
		.alpha( 0 )
		.width( IMAGE_WIDTH )
		.height( IMAGE_HEIGHT )
		.prop( "index", index )
		.prop( "url", xImgList[index].@url)
		.prop( "title", xImgList[index].@title)
		.prop( "desc", xImgList[index].@desc)
		.onComplete(completeHandler)
		 );


		area.attach(image.content, {scaleMode:"proportionalOutside", crop:true});
		image.load();
	}

Link to comment
Share on other sites

Right, the problem with your code (as the error text indicated) is that you created your LiquidArea on "this.stage" but then you nested the images that you're attaching inside imgContainer. You cannot attach() objects that are in a completely different container. In other words, it's like telling LiquidArea "okay, you live in this.stage and I want you to be mindful of that coordinate space" and then out put your images in a completely different coordinate space and LiquidArea is like "dude, those things you're attaching to me don't live here...they're in a foreign zip code that isn't within my purview...me no likie."

Link to comment
Share on other sites

Haha ok I think I understand that logic. Ok so that worked after added LiquidStage(imgContainer, 0, 0..) but now have another problems.

 

I have this function oldImage() shown in the code, which checks if there is an image already there before loading another image and fades out if there is. This seems to conflict with the liquidstage and give the error "RangeError: Error #2006: The supplied index is out of bounds." Not sure of a better way to check if image is there and keep liquidarea working.

 

private function thumbClick( e:MouseEvent ):void
	{

		// access prop with vars object
		var vars:Object = ImageLoader(e.currentTarget.loader).vars;
		trace( vars.url );

		checkOldImage( vars.index ); // good practice for tweening image if it is already on stage
	}

private function checkOldImage( index:Number ):void
	{

		//check if there is already an image loaded
		if ( imgContainer.numChildren > 0 ) 
		{
			var oldClip:Sprite = Sprite( imgContainer.getChildAt( 0 ) );
			TweenMax.to( oldClip, .5, { autoAlpha: 0, onComplete: function() {
						imgContainer.removeChildAt( 0 ); loadImage( index ) }
						} );
		} else
		{
			loadImage( index );
		}
	}

Link to comment
Share on other sites

It's tough to say what's going on because you probably have other code that is affecting the display list. Your code is assuming that nothing will change in the display list between the time the tween begins and ends, but I think that's a dangerous assumption to make. The error seems to indicate that something else is removing that object from the display list prematurely.

 

You could try something like:

 

var oldClip:DisplayObject = imgContainer.getChildAt( 0 );
nextIndex = index;
TweenMax.to( oldClip, .5, { autoAlpha: 0, onComplete: completeFadeHandler, onCompleteParams:[oldClip] } );

function completeFadeHandler(child:DisplayObject):void {
   if (child.parent) {
       child.parent.removeChild(child);
   }
   loadImage(nextIndex);
}

 

Keep in mind that the nextIndex might change while the tween is occuring too, so it's best to write your code to accommodate that scenario.

Link to comment
Share on other sites

Yea as I test and test some more. There are far more errors that are unexplained. Like the placement of the image and an unknown bar on the right side of the browser on scale. And that code you gave me didn't really fix the problem for that RangError, it just presented a new error. I thinks it's best I come up with a new gallery functionality that I can actually accomplish and accept that what I was going for is far passed my skill level instead of coming back here for help on a ton of new issues. Thanks again for the help. Sorry we weren't able to clear this up.

Link to comment
Share on other sites

Wow, I totally forgot to edit part of what I pasted in there as the code. My apologies. This is what I meant:

 

var oldClip:DisplayObject= imgContainer.getChildAt( 0 );
nextIndex = index;
TweenMax.to( oldClip, .5, { autoAlpha: 0, onComplete: completeFadeHandler, onCompleteParams:[oldClip] } );

function completeFadeHandler(child:DisplayObject):void {
   if (child.parent) {
       child.parent.removeChild(child);
   }
   loadImage(nextIndex);
}

Link to comment
Share on other sites

With that I still get the same error I was getting before which was very confusing "1118: Implicit coercion of a value with static type flash.display:DisplayObject to a possibly unrelated type flash.display:Sprite". The full code can be found on the scroll problem forum question if you need to see it but it's the same story with that problem. Plus the image is doing a weird crop so that's another problem.

Link to comment
Share on other sites

Oh, right - getChildAt() returns a DisplayObject, not a Sprite (although it certainly could be a Sprite). So simply change the data type for your variable:

var oldClip:DisplayObject = imgContainer.getChildAt( 0 );

Link to comment
Share on other sites

Haha yea same error 2006: out of bounds error. I think this error is somewhere else in the code that I can't find. Wasn't as simple a project as I thought. I might have to test full browser LoaderMax images at a later when my skills get better and settle for a gallery with the initial size that comes now.

Link to comment
Share on other sites

You did have that code inside the condition: if ( imgContainer.numChildren > 0 ) right? Oh well, if you're still getting errors, there must be something else going on in your project that's causing the trouble. Let us know if you need more help.

Link to comment
Share on other sites

Yea I added it inside if statement as well. The thing is in the old code I had below, if I take out the line "removeChildAt(0) then this whole thing works fine, except I dont get garbage collection and this application will get heavy loading. There has to be a way around this. After searching the error 2006, it seems that the issue is with remove/getChildAt functions. Ultimately, I just want to loading the right image from next or thumbnails and remove the last image.

 

package 
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.DisplayObject;

import com.greensock.TweenMax;
import com.greensock.layout.*;
import com.greensock.events.LoaderEvent;
import com.greensock.loading.XMLLoader;
import com.greensock.loading.LoaderMax;
import com.greensock.loading.ImageLoader;
import com.greensock.loading.data.ImageLoaderVars;
import com.greensock.loading.display.ContentDisplay;


public class Main extends MovieClip
{
	private static const THUMB_WIDTH:Number = 100;
	private static const THUMB_HEIGHT:Number = 64;
	private static const IMAGE_WIDTH:Number = 550;
	private static const IMAGE_HEIGHT:Number = 355;

	private var ls:LiquidStage;
	private var la:LiquidArea;

	private var xImgList:XMLList;
	public var arrowRight:MovieClip;
	public var arrowLeft:MovieClip;
	private var currentImage:String;
	private var image:ImageLoader;
	private var index:Number = 0;

	public function Main()
	{
		// load in xml
		var xPhotography:XMLLoader = new XMLLoader("assets/data.xml");
		xPhotography.addEventListener( LoaderEvent.COMPLETE, xmlLoaded );
		xPhotography.load();

		arrowRight.alpha = arrowLeft.alpha = 0;
		arrowRight.addEventListener(MouseEvent.ROLL_OVER, rollOverArrowHandler, false, 0, true);
		arrowRight.addEventListener(MouseEvent.ROLL_OUT, rollOutArrowHandler, false, 0, true);
		arrowRight.addEventListener( MouseEvent.CLICK, onArrowClick );
		arrowLeft.addEventListener(MouseEvent.ROLL_OVER, rollOverArrowHandler, false, 0, true);
		arrowLeft.addEventListener(MouseEvent.ROLL_OUT, rollOutArrowHandler, false, 0, true);
		arrowLeft.addEventListener( MouseEvent.CLICK, onArrowClick );
	}

	private function xmlLoaded( e:LoaderEvent ):void
	{
		var xData:XML = e.target.content;// get copy of xml
		xImgList = new XMLList(xData.image);// grabbing xml image nodes

		loadImage( 0 );
	}

	// load in the image
	private function loadImage( index: Number ):void
	{
		ls = new LiquidStage(this.stage,550,419);
		la = new LiquidArea(imgContainer, 0, 0, 550, 419);

		var file:String = xImgList[index].@url;

		var image:ImageLoader = new ImageLoader("assets/images/" + file, new ImageLoaderVars()
		.container( imgContainer )
		.x(0)
		.y(0)
		.alpha( 0 )
		.width( stage.stageWidth )
		.height( stage.stageHeight )
		.onComplete(completeHandler)
		.scaleMode( "proportionalOutside" )
		.autoDispose(true)
		 );

		image.load();
		la.attach(image.content, {scaleMode:"proportionalOutside", crop:true});
	}

	private function completeHandler(event:LoaderEvent):void
	{
		/*la = new LiquidArea(imgContainer, 0, 0, 550, 419);
		la.update();*/
		TweenMax.to(event.target.content, 1.5, {alpha:1});
	}

	private function rollOverArrowHandler(e:MouseEvent):void
	{
		TweenMax.to(e.currentTarget, 0.5, {alpha:1});
	}

	private function rollOutArrowHandler(e:MouseEvent):void
	{
		TweenMax.to(e.currentTarget, 0.5, {alpha:0});
	}

	private function onArrowClick( e:MouseEvent ):void
	{
		switch (e.target)
		{
			case arrowRight :
				index++;
				break;
			case arrowLeft :
				index--;
				break;
		}

		if (index == xImgList.length())
		{
			index = 0;
		} else if (index < 0)
		{
			index = xImgList.length() - 1;
		}

		checkOldImage( index );// needed to help loading times
	}

	private function checkOldImage( index:Number ):void
	{

		//check if there is already an image loaded
		if ( imgContainer.numChildren > 0 ) {
			var oldClip:Sprite = Sprite( imgContainer.getChildAt( 0 ) );
			TweenMax.to( oldClip, .5, { autoAlpha: 0, onComplete: function() 
						{
						imgContainer.removeChildAt( 0 );  // commenting out this line removes the error but does not help fix the app.
						loadImage( index ) }
						} );
		} else {
			loadImage( index );
		}
	}
}

}

Link to comment
Share on other sites

Yep, according to the error message, when you try to run imgContainer.removeChildAt( 0 ) there is no child there. That's why I suggested the different code that had conditional logic in place to avoid that situation. If you'd rather not implement my suggestion, that's cool. But I'm not sure what else you were hoping for with your latest post.

 

Also, you definitely shouldn't be creating new LiquidStage and LiquidArea instances every time you load a new image - that's very wasteful. Just reuse the same instances (one each). And if you're going to keep creating new ImageLoaders like that (which I wouldn't really recommend, but you're certainly allowed to do it), don't forget to detach them from the LiquidArea so that they can get disposed properly. Otherwise your app just keeps creating more and more instances that are holding references to things you don't need anymore.

 

I think it would be far more efficient to use one ImageLoader for each image and just reuse it whenever you need that image. That way you don't have to load it every time it is needed. Make sense?

 

By the way, have you seen the example source files at http://www.greensock.com/as/LoaderMax/slideshow.zip ?

Link to comment
Share on other sites

By the way, you are using the latest version of the GreenSock classes, right?

 

Can you post a sample FLA (and support files) that we can publish to see the error on our end? (don't forget to zip them first)

Link to comment
Share on other sites

If you'd rather not implement my suggestion, that's cool.

I had told you before in the previous post that I used your suggestion and it gave me the exactly same error. What I was hoping by showing you the function again was to see if we could now get to a better solution since I thought I knew where it was.

 

Also, you definitely shouldn't be creating new LiquidStage and LiquidArea instances every time you load a new image

This actually cleaned up the error. I dont get the error anymore once I added LiquidStage/Area to the constructor.

 

I think it would be far more efficient to use one ImageLoader for each image and just reuse it whenever you need that image. That way you don't have to load it every time it is needed. Make sense?

By the way, have you seen the example source files at http://www.greensock.com/as/LoaderMax/slideshow.zip ?

Thats where I get confused. After looking at the "Meet LoaderMax" videos and looking at the demos, I wasn't really sure how you can reference back to the array in a different function. As for slideshow.zip, I am not that far along with AS3 so just viewing this without a video was intimidating but I think my ultimate goal now will have to be picking this apart if I am going to create what I want. And yes I will zip the file together so you can have a look. Thanks a lot by the way. I am a sucky newb at this but I've learned a lot from my mistakes.

Link to comment
Share on other sites

No worries. Glad you're not running into the error anymore. I had to remove your file(s) because you included a bunch of members-only classes like LiquidStage, SplitTextField, etc. which aren't available to the general public :)

 

Slideshows can be a little tricky because it's best to accommodate special considerations like:

 

- What if the user clicks next/back very quickly multiple times (before the next image loads)?

- How can we make sure things are loaded in the most effective, efficient manner so that the application is the most responsive to the user's interaction? For example, you'd probably want to have things loading in the background so that the next image is ready to go the moment the user clicks on the next button. You should only load each image once to maximize performance.

- How can we juggle loading assets properly so that if the user requests an image while something else is loading, that new image is prioritized in the loading queue? This again ensures that the user gets the best experience.

- How can we handle errors or URLs that aren't loaded properly, etc.?

...etc.

 

So I don't blame you for feeling like that slide show example is a little complex. I tried to keep it relatively simple while addressing the most common (and important) considerations.

 

Good luck. Happy loading :)

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.
×