Maintaining aspect ratio when sizing

The aspect ratio of an image is the ratio of its width to its height. For example, a standard NTSC television set uses an aspect ratio of 4:3, and an HDTV set uses an aspect ratio of 16:9. A computer monitor with a resolution of 640 by 480 pixels also has an aspect ratio of 4:3. A square has an aspect ratio of 1:1.

All images have an inherent aspect ratio. When you use the height and width properties of the Image control to resize an image, by default Flex preserves the aspect ratio of the image so that it does not appear distorted.

By preserving the aspect ratio of the image, Flex might not draw the image to fill the entire height and width specified for the <mx:Image> tag. For example, if your original image is a square 100 by 100 pixels, which means it has an aspect ratio of 1:1, and you use the following statement to load the image:

<mx:Image source="myImage.jpg" height="200" width="200"/>

The image increase to four times its original size and fills the entire 200 x 200 pixel area.

The following example sets the height and width of the same image to 150 by 200 pixels, an aspect ratio of 3:4:

<mx:Image source="myImage.jpg" height="150" width="200"/>

In this example, you do not specify a square area for the resized image. Flex maintains the aspect ratio of an image by default, therefore, Flex sizes the image to 150 by 150 pixels, the largest possible image that maintains the aspect ratio and conforms to the size constraints. The other 50 by 150 pixels remain empty. However, the <mx:Image> tag reserves the empty pixels and makes them unavailable to other controls and layout elements.

You can use a Resize effect to change the width and height of an image in response to a trigger. As part of configuring the Resize effect, you specify a new height and width for the image. Flex maintains the aspect ratio of the image by default, so it resizes the image as much as possible to conform to the new size, while maintaining the aspect ratio. For example, place your mouse pointer over the image in this example to enlarge it, and then move the mouse off the image to shrink it to its original size:

<?xml version="1.0"?>
<!-- controls\image\ImageResize.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Resize id="resizeBig" widthFrom="120" widthTo="200"/>
    <mx:Resize id="resizeSmall" widthFrom="200" widthTo="120"/>

    <mx:Image width="120" 
        source="@Embed('logo.jpg')" 
        rollOverEffect="{resizeBig}" 
        rollOutEffect="{resizeSmall}"/>
</mx:Application>

For more information on the Resize effect, see Using Behaviors.

If you do not want to preserve the aspect ratio when you resize an image, you can set the maintainAspectRatio property to false. By default, maintainAspectRatio is set to true to enable the preservation of the aspect ratio.

The following example resizes the Flex logo to the exact values of the height and width properties without regard for its aspect ratio:

<?xml version="1.0"?>
<!-- controls\image\ImageResizeMaintainAR.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Image id="image1" 
        source="@Embed('logo.jpg')" 
        width="250" height="100" 
        maintainAspectRatio="false"/> 
</mx:Application>

By choosing not to maintain the aspect ratio, you allow for the possibility of a distorted image. For example, the Adobe logo is 136 by 47 pixels by default. In the following example, it is distorted because the aspect ratio is not maintained when the image is resized:


Demonstration of aspect ratio

Positioning the image in a Canvas container

A Canvas container, and the Panel and Application containers with the layout property set to absolute, let you specify the location of its children within the container. To specify the absolute position of an image, you use the x and y properties of the Image control.

NOTE

 

In all other containers, the container controls the positioning of its children and ignores the x and y properties.

The x and y properties specify the location of the upper-left corner of the image in the Canvas container. In the following example, you set the position of the image at (40,40), 40 pixels down and 40 pixels to the right of the upper-left corner of the Canvas container:

<?xml version="1.0"?>
<!-- controls\image\ImageCanvas.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Canvas id="canvas0" 
        borderStyle="solid"
        width="200"
        height="200">
        <mx:Image id="img0" 
            source="@Embed('logo.jpg')" 
            x="40" y="40"/>
    </mx:Canvas>
</mx:Application>

This code results in the following application:


Positioning an image in the Canvas container

Setting visibility

The visible property of the Image control lets you load an image but render it invisible. By default, the image is visible. To make an image invisible, set the visible property to false. The following example loads an image but does not make it visible:

<?xml version="1.0"?>
<!-- controls\image\ImageVisible.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:VBox id="vbox0" 
        borderStyle="solid">
        <mx:Image id="img0" 
            visible="false" 
            source="@Embed(source='logo.jpg')"/>
    </mx:VBox>
</mx:Application>

The VBox container still allocates space for the image when it lays out its children. Thus, the VBox is the same size as the image file and, if your application contained a Button control after the <mx:Image> tag, the button would appear in the same location as if the image was visible.

If you want to make the image invisible, and have its parent container ignore the image when sizing and positioning its other children, set the includeInLayout property of the Image control to false. By default, the includeInLayout property to true, so that even when the image is invisible, the container sizes and positions it as if it were visible.

Often, you use the visible property to mark all images invisible, except one image. For example, assume that you have an area of your application dedicated to showing one of three possible images based on some user action. You set the visible property set to true for only one of the possible images; you set the visible property set to false for all other images, which makes them invisible.

You can use ActionScript to set image properties. In the following example, when the user clicks the button, the action sets the visible property of the image to true to make it appear:

<?xml version="1.0"?>
<!-- controls\image\ImageAS.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        <![CDATA[
            private function showImage():void {
                image1.visible=true;
            }
        ]]>
    </mx:Script>
    <mx:VBox id="vbox0" 
        width="80" 
        height="80">
        <mx:Image id="image1" 
            visible="false" 
            source="@Embed(source='logo.jpg')"/> 
        <mx:Button id="myButton" 
            label="Show" click="showImage();"/>
    </mx:VBox>
</mx:Application>

This following examples shows the results, before and after a user clicks the button:


Setting image properties in ActionScript

If you set the visible property, you can control when images are loaded. By allocating space but making images invisible when a page loads, you ensure that any slower performance occurs during the initialization stage when users expect it, rather than as they interact with the application and perform actions that require the image. By setting the visible property, you can also prevent resizing and relayout within your application at seemingly random intervals.

Techniques for using the Image control

Often in a product catalog, when a user clicks an item, the catalog displays an image of the item. One strategy for building a catalog is to load the catalog images into your application, but make them all invisible. When a user selects a product, you make that image visible.

However, this strategy requires that you add an Image control for all the images in your catalog and load the images, even if they are invisible, when the application starts. The resulting SWF file would be unnecessarily large, because it would contain all the images and the start-up time would be negatively affected by loading invisible images.

A better strategy is to dynamically load the images from your server, as necessary. In this way, your SWF file stays small, because it does not have to contain invisible images, and your start-up time improves.

As part of its implementation, the ActionScript class that defines the <mx:Image> tag is a subclass of the SWFLoader class. After creating an image, you can use the properties and methods of the SWFLoader control with your image, including the load() method, which loads an image file dynamically.

NOTE

 

The load() method of the SWFLoader control only works with GIF, JPEG, PNG, and SWF files; you cannot use it to load SVG files.

The following example uses the load() method to replace the logo.jpg image with the logowithtext.gif image when the user clicks a button:

<?xml version="1.0"?>
<!-- controls\image\ImageLoad.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

  <mx:Script>
    <![CDATA[
      private function afterImage():void {
        image1.load('http://localhost:8100/flex/assets/logowithtext.jpg');
      }
    ]]>
  </mx:Script>

  <mx:VBox id="vbox0" 
      width="150" height="100">
      <mx:Image id="image1" source="logo.jpg"/> 
      <mx:Button id="myButton" 
          label="Show Second Image" 
          click="afterImage();"/>
  </mx:VBox>
</mx:Application>

Notice in this example that the application accesses the images in the local file system; they are not embedded or accessed by URL. Therefore, you have to compile this application with the use-network flag set to false.

The container that holds the image does not adjust the layout of its children when you call the load() method. Therefore, you typically replace one image with another image of the same size. If the new image is significantly larger than the original, it can overlay other components in the container.

You can make the selection of the replacement image based on a user action in your application. For example, you might want to load an image based on a user selection in a list box or data grid.

In the next example, you use the index number of the selected item in a data grid to determine the image to load. In this example, images are named 1.jpg, 2.jpg, 3.jpg, and so on, corresponding to items in the grid.

// Retrieve the image associated with the item selected in the grid.
private function getImage():void {
    var cartGrid = dgrid;
    var imageSource:String = 'images/' + cartGrid.getSelectedIndex() + '.jpg';
    image1.load(imageSource);
}

In this example, the images are stored in the images directory. The complete path to an image is the directory name, the index number, and the file suffix .jpg.

You register this function as the event listener for a change event in the data grid, as follows:

<mx:DataGrid id="dgrid" height="200" width="350" change="getImage();"/>

When a user changes the currently selected item in the data grid, Flex calls the getImage() function to update the displayed image.

You could modify this example to use information about the selected item to determine the image to load, rather than using the selected item's index. For example, the grid could contain a list of objects, where each object has a property that contains the image name associated with it.

In addition to the load() method, you can also access other properties of the SWFLoader control, including percentLoaded. The percentLoaded property is particularly useful because it lets you to display a progress bar so users know that the application did not become unresponsive. For a complete list of the SWFLoader properties and methods, see Adobe Flex 2 Language Reference.


Flex 2.01

Take a survey