views:

428

answers:

2

I am using a mx:Resize effect to change the width of an image in Flex (leaving the height to look after itself) but I want the image to remain vertically centered on the page. Whilst I could calculate the aspect ratio of the photo, and work out the new y value to keep it centred, I would have to include a mx:Move effect too, and I am hopful that Flex has a simpler way.

This is for a photo gallery where images are loaded at run-time, and swapped about, so I really would like to avoid recalculating the aspect ratio and vertical position every time the updateComplete event fires. It seems so messy.

I tried putting my image inside a mx:VBox with verticalAlign="middle", thinking that the box would do all the centering for me, but this only seems to happen when the app first starts - i need it to gradually adjust the position during the period where the effect plays (to keep it central even when part-way through).

Here's a stripped-down example (which doesn't work):

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="600" height="600">

<mx:Resize id="fxResize" target="{imgPhotoA}" widthTo="350" duration="500" />

<mx:Button x="10" y="10" label="Resize" click="fxResize.play()" />

<mx:VBox id="boxPhotoA" x="100" y="20" height="500" width="350" verticalAlign="middle"  borderStyle="solid" verticalScrollPolicy="off" horizontalScrollPolicy="off">
    <mx:Image id="imgPhotoA" width="60" maintainAspectRatio="true" source="http://sstatic.net/so/img/logo.png"/&gt;
</mx:VBox>

</mx:Application>

I am a newcomer to Flex, so apologies if I am doing something daft. Looking at the source of the Adobe example photo gallery hasn't helped me realise a solution - I don't think they use effects, but create their own routine to alter the size and position. The code looks horrid!

A: 

You could try creating an event handler for the effectEnd event of the Resize control, something that calls invalidateDisplayList on the VBox, something like:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="600" height="600">

<mx:Script>
  <![CDATA[
    private function resizeFinishedHandler(Event:Event) : void {
       boxPhotoA.invalidateDisplayList();
    }
  ]]>
</mx:Script>

<mx:Resize id="fxResize" target="{imgPhotoA}" widthTo="350" duration="500" 
  effectEnd="resizeFinishedHandler(event)" />

<mx:Button x="10" y="10" label="Resize" click="fxResize.play()" />

<mx:VBox id="boxPhotoA" x="100" y="20" height="500" width="350" verticalAlign="middle"  borderStyle="solid" verticalScrollPolicy="off" horizontalScrollPolicy="off">
    <mx:Image id="imgPhotoA" width="60" maintainAspectRatio="true" source="http://sstatic.net/so/img/logo.png"/&gt;
</mx:VBox>

</mx:Application>

Hope this helps.

Robusto
I'm afraid that didn't work. The vertical position of the image never moves. I will read more about the updateDisplayList() method thouhg, now you have made me aware of it!
Magnus Smith
I've realised I need the image to be continually adjusted to keep it central, not just at the end of the effect transition. Sorry.
Magnus Smith
A: 

Since the boss wanted this ready for tomorrow, I had to give up on the idea of Flex doing the work for me, and calculate the values myself.

Note that I knew that all my JPGs were 120px wide, but the heights could vary. This made horizontal positioning easy, so its only the vertical positioning I will refer to below...

PART ONE

Every time the complete event fired on an image object (i.e. a JPG was loaded into it) I set its position based on its height. Assuming the centreline was a line 300 px down from the top of the screen, I used:

oImage.y = 300 - (oImage.contentHeight / 2)

I avoided the updateComplete event as it seemed to fire off hundreds of times when an effect moved/resized the image. I also avoided the height property (in favour of contentHeight) as I found a strange issue with the image tag whereby I had to set its height to a value (I only wanted to set the width really) in order for the resize effect to actually do anything. I used height="999" and let the image take care of its own aspect ratio.

PART TWO

Just before I called the play() method on my effects, I had to set the yTo value for each move effect, to ensure the image would move to the correct vertical position to take into account it being resized at the same time (e.g. if image shrinks, it needs to be moved down slightly).

For each image, I needed to work out the aspect ratio and then I could calculate what the new height of the image would be after resizing.

private function calculate_yto_value(oImage:Image, iWidthAfterTheEffect:int):int {
    var iAspectRatio:Number = oImage.contentHeight / oImage.width
    var iHeightAfterTheEffect:Number = iAspectRatio * iWidthAfterTheEffect
    return 300 - (iHeightAfterTheEffect / 2)
}

fxMovePhoto.yTo = calculate_yto_value(imgPhotoA, 60)
Magnus Smith