case
12Apr/0910

How To – Center a image on a canvas in flex


This is the solution for the anoying behaivor of the image control into a canvas or hbox or whatever. If the image is set to be scaled to a maximum width and height and maintaining the aspect ration, it won't center itself even if it has the horizontalCenter set to "0". So...here's how it looks (top) and how it suppose to look (bottom)

canvas

Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 
    <mx :Script>
        < ![CDATA[
 
                // Maximum  width
                private var mxw:Number = 500;
                // Maximum height
               private var mxh:Number = 250;
 
               public function onImageComplete(e:Event):void
               {
                var wthMaxRatio:Number = mxw / mxh;
 
                // no resize needed
                if (e.target.contentWidth <= mxw && e.target.contentHeight <= mxh)
                {
                    e.target.x = (mxw - e.target.contentWidth) / 2;
                    e.target.y = (mxh - e.target.contentHeight) / 2;
                }
                else
                {
                    var wthImgRatio:Number = e.target.contentWidth / e.target.contentHeight;
 
                    if (wthImgRatio > wthMaxRatio)
                    {
                        // will max out the width
                        e.target.width = mxw;
                        var imgHeight:Number = Math.round( (mxw / e.target.contentWidth) * e.target.contentHeight );
                        var newY:Number = Math.round( (mxh - imgHeight) / 2 );
                        e.target.x = 0;
                        e.target.y = newY;
                    }
                    else
                    {
                        // will max out the height
                        e.target.height = mxh;
                        var imgWidth:Number = Math.round( (mxh / e.target.contentHeight) * e.target.contentWidth );
                        var newX:Number = Math.round( (mxw - imgWidth) / 2 );
                        e.target.x = newX;
                        e.target.y = 0;
                    }
                }
              }
         ]]>
    </mx>
 
 
      <mx :Canvas width="500" height="250"
            verticalScrollPolicy="off" horizontalScrollPolicy="off"
            backgroundColor="#000000">
 
            <mx :Image id="theimage"
                maintainAspectRatio="true"
		scaleContent="true"
                complete="onImageComplete(event)" />
 
        </mx>

Comments (10) Trackbacks (1)
  1. Lazy way, embed the image in a Canvas and set the verticalCenter/horizontalCenter of the canvas.

  2. @widged
    That won’t do. If you want to scale the image, it won’t center

  3. I think the best way to do this is to set the maxWidth/maxHeight attributes instead of the width/heigth.. and stay with the verticalCetner/horizontalCenter=0 .. this works fine.

    example:

  4. @guille
    no quille, it won’t work. If you set maxWidth and maxHeight to the picture as much as the canvas will permit, if the picture is 10 times larger than the canvas, when it shrinks with the maintainAspectRatio set to true, the image component width and height will be the ones that you set to maxWidth and maxHeight, but the graphic itself inside will be draw to the left, and not to the center. that was the initial problem I enounced. Check it. You’ll see it won’t work.

    1.<?xml version=“1.0” encoding=“utf-8”?>
    2.<mx:Application xmlns:mx=“http://www.adobe.com/2006/mxml” layout=“absolute”>
    3. <mx:Canvas width=“450” height=“250”>
    4. <mx:Image source=“image.jpg” scaleContent=“true” maintainAspectRatio=“true” maxHeight=“250” maxWidth=“450” horizontalCenter=“0” verticalCenter=“0”/>
    5. </mx:Canvas>
    6.</mx:Application>
    7. 

    Generated by FlexWebFormater

  5. I can confirm guille’s word. Nice solution. I came up with same. Anyone got something cleaner (that you know works)?

  6. I have something a little cleaner.

    Check it out Flex Image Centering

    var ratio:Number = Math.min(image.maxWidth/image.contentWidth,image.maxHeight/image.contentHeight );
    image.width = ratio * image.contentWidth;
    image.height = ratio * image.contentHeight;

  7. I got completely tripped up by this as well, and ultimately found the solution after several hours of the worst kind of programming rage imaginable.

    I finally realized that instead of setting the horizontalAlign and verticalAlign properties on the box (or canvas) that contains the image control, that the image control is treating its image data as a child of itself, and that you can set the vertAlign and horiAlign on the image control with the desired results! Also, go ahead and blow out the height and width of the Image control (100%) while setting real dimensions for the container box, and use scaleContent and maintainAspectRatio and get down wit yo bad self you sexy flex developer!

    Thanks for listening.
    Jack

  8. @jaryckon
    Damn, homie, u totally killed that sh*t!
    Kudos to you for the quick & elegant solution.

    width=”100%” height=”100%”
    horizontalAlign=”center” verticalAlign=”middle”

    Works every time.

  9. your solution didn’t work for me, so this is what I’m using instead.

    package com.customClasses
    {
    import mx.containers.Canvas;
    import mx.controls.Image;

    /**
    * @author Anton.Stepanov
    * actionscriptpro_at_gmail
    */
    public class ImageThumbPreview extends Canvas
    {
    private static var DEFAULT_IMAGE_TO_CANVAS_SCALE:Number = 0.8;

    private var imgScale:Number = DEFAULT_IMAGE_TO_CANVAS_SCALE;

    private var img:Image;

    public function ImageThumbPreview()
    {
    super();
    }

    public function set imageScale(value:Number):void
    {
    imgScale = value;
    }

    public function get imageScale():Number
    {
    return imgScale
    }

    public function set thumbImg(value:Image):void
    {
    if (img) this.removeChild(img);
    img = value;

    // Maximum width
    var mxw:Number = this.width * imgScale;
    // Maximum height
    var mxh:Number = this.height * imgScale;

    // no resize needed
    if (img.width <= mxw && img.contentHeight <= mxh)
    {
    img.x = (mxw – img.contentWidth) / 2;
    img.y = (mxh – img.contentHeight) / 2;
    }
    else
    {
    var scaleRatio:Number
    var scaleRatioX:Number = mxw / img.contentWidth;
    var scaleRatioY:Number = mxh / img.contentHeight;

    if (scaleRatioX < scaleRatioY)
    {
    scaleRatio = img.scaleX = img.scaleY = scaleRatioX;
    }
    else
    {
    scaleRatio = img.scaleX = img.scaleY = scaleRatioY;
    }

    img.x = (this.width – (img.contentWidth * scaleRatio)) / 2;
    img.y = (this.height – (img.contentHeight * scaleRatio)) / 2;
    }
    addChild(img);

    }

    public function get thumbImg():Image {
    return img;
    }

    }
    }

  10. This is just what I needed thanks for sharing! I have been looking for some help with the image-flex I have just started getting into it and I don’t understand a lot about it. Any help like this and tips would be so useful. I’m so excited to figure this out and have fun with my pictures!


Leave a comment


*

CommentLuv badge