Fullscreen background image with Flex

actionscript-3apache-flexflash

I want to load an image into the background of my Flex app. However, I am wondering about a few things, and have a few contraints.

I want it to be much like the way it's done with CSS. See this example of fullscreen background images with CSS.

It is very important that there is no white-space (background colour) showing behind the image, and that the image is not stretched. This would mean some of the image would be cut off. This is absolutly fine. Actually, the first five points in the bulleted list on the linked page above are all exactly what I am after.

I am relitivly new to the Flex framework, but have a strong AS3 background. So I can do this easily with actionscript using a mask, stage.width/height, the stages RESIZE event, and a little bit of Math. But I am wondering what would be the "Flex" way of doing this?

I don't want to narrow the answers, but would I create my own component, that extends canvas, that I put behind all my other content? Or to I set some property of the application? Or what?

Thanks.

Best Answer

Here's a custom component that will fill any rectangle with an image. It will not stretch the image if the rectangle aspect ratio is not the same as the image, nor will it show white space, but rather it will clip the edges of the image. The image will be scaled. Always at least one dimension will be 100% filling the rectangle, but the other dimension will be clipped.

This is based on Flex's UIComponent, component life-cycle, and Image.

ClippedImage.as

package com.preston.www.view.background.components {
import flash.events.Event;
import flash.geom.Rectangle;

import mx.controls.Image;
import mx.core.UIComponent;

//--------------------------------------
//  Events
//--------------------------------------

[Event(name="complete", type="flash.events.Event")]

public class ClippedImage extends UIComponent {

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    public function ClippedImage() {
        image = new Image();
        image.addEventListener(Event.COMPLETE,image_completeHandler);
        addChild(image);
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    private var image:Image;

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  source
    //----------------------------------

    public function get source():Object {
        return image.source;
    }

    public function set source(value:Object):void {
        image.source = value;
    }

    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------

    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
        super.updateDisplayList(unscaledWidth, unscaledHeight);

        var imageMeasuredWidth:Number = image.measuredWidth;
        var imageMeasuredHeight:Number = image.measuredHeight;
        var imageAspectRatio:Number = imageMeasuredWidth / imageMeasuredHeight;

        var imageWidth:Number;
        var imageHeight:Number;

        // try setting image according to width first
        imageWidth = unscaledWidth;
        imageHeight = imageWidth / imageAspectRatio;

        // if a gap exists vertically, set image according to height
        if (imageHeight < unscaledHeight) {
            imageHeight = unscaledHeight;
            imageWidth = imageAspectRatio * imageHeight;
        }

        image.setLayoutBoundsSize(imageWidth, imageHeight);

        // set image x and y
        var imagex:Number = (unscaledWidth - imageWidth) / 2;
        var imagey:Number = (unscaledHeight - imageHeight) / 2;

        image.setLayoutBoundsPosition(imagex, imagey);

        scrollRect = new Rectangle(0, 0, unscaledWidth, unscaledHeight);
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------

    private function image_completeHandler(event:Event):void {
        dispatchEvent(event);
    }
}
}

Then, in your app you just set an mxml tag for this component as follows:

<components:ClippedImage id="background" width="100%" height="100%"
                         source="assets/images/winery.jpg"/>
Related Topic