24
Jul
08

Flex Image Repeating Canvas Container

As per HTML designer, there is no need to put the whole strip of image which is linear, similar from top – bottom or left – right. The trick HTML designer uses is, he takes a 1px of image that strip and set that image as a background for a table(or row or cell) and set it to repeat.
When it comes to Flex, if we want to put a background image which has the similar linear from its directions. Then we can set the whole strip of image as background for containers.which makes a heavy embedding of image,. So i thought to create a similar kind of container which provides to set a repeating background image and should allow to repeat the image in both horizontal and vertical directions.

So here i come up with a solution, i created a custom Container which extends Canvas container. It accepts the Embedded image (1Px) class reference as well as repeat direction. The custom container works on the Graphics API using beginBitMapFill methods.
So check it out and drop a comment.

here is how to use it steps:
First embed the image(1 px) in your application and create ImageRepeatCanvas and assign the properties;


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" xmlns:flexscript="com.*">
<mx:Script>
	<![CDATA[
		[Bindable]
		[Embed(source='com/bg.png')]
		private var img:Class;
	]]>
</mx:Script>
<flexscript:ImageRepeatCanvas repeatDirection="horizantal"
 height="150" repeatImage="{img}" width="587" x="31.5" y="49">
	<mx:Button label="Button1" x="10" y="86"/>
	<mx:Button label="Button1" x="257.5" y="86"/>
	<mx:Button label="Button1" x="170" y="86"/>
	<mx:Button label="Button1" x="90" y="86"/>
</flexscript:ImageRepeatCanvas>
</mx:Application>

Next,….

create a directory name as “com” into your directory and put this container class into that directory;

(The class is well documented, you are free to alter, modify etc :) )


/*
	The ImageRepeatCanvas provides a container in which
	embeded images can be repeated
	as designers do in html tables.
*/

package com
{
	import flash.display.Bitmap;
	import flash.display.Graphics;
	import mx.containers.Canvas;

	/**
	 *  The ImageRepeatCanvas container gives a way of creating
	 * one image that repeat
	 *  across either directions.
	 *
	 *  @mxml
	 *
	 *
<pre>
	 *  <namespace:ImageRepeatCanvas
	 *       repeatImage="{EmbededImage Class Reference}"
	 *       repeatDirection="horizantal|horizantal"
	 *    />
	 *</pre>
*/

	public class ImageRepeatCanvas extends Canvas
	{
		//-------------------------------------------------------------
	    //  Variables
	    //-------------------------------------------------------------
		private var bgImg:Bitmap = new Bitmap();
		private var direction:String;
		public var repeatImage:Class;

		//--------------------------------------------------------------
	    //  Constants
	    //--------------------------------------------------------------
		public static var REPEAT_HORIZANAL:String = "horizantal";
		public static var REPEAT_VERTICAL:String = "vertical";

	    //---------------------------------------------------------------
	    //  Constructor
	    //---------------------------------------------------------------
		public function ImageRepeatCanvas()
		{
			super();

		}

		/**
	     *  A setter method to set the direction for repeation of image
	     */
		[Inspectable(category="General", enumeration="horizantal,vertical", defaultValue="horizantal")]
		public function set repeatDirection(val:String):void{
			direction = val;
		}

		/**
	     *  @private
	     */
		override protected function updateDisplayList(w:Number, h:Number):void{
			super.updateDisplayList(w,h);
			bgImg.bitmapData = new repeatImage().bitmapData;
			if(bgImg){
				switch(direction){
					case ImageRepeatCanvas.REPEAT_HORIZANAL:
									h = bgImg.height;
									break;
					case ImageRepeatCanvas.REPEAT_VERTICAL:
									w = bgImg.width;
									break;
				}
				var Grpx:Graphics = graphics;
				Grpx.clear();

				Grpx.beginBitmapFill(new repeatImage().bitmapData);
				drawRoundRect(0,0,w,h);
				Grpx.endFill();
			}
		}
	}
}

Waiting for your comments :)



20 Responses to “Flex Image Repeating Canvas Container”


  1. 1 Dane
    August 9, 2008 at 5:54 am

    Just wanted to say that this is awesome and exactly what I was looking for and it works perfectly.

  2. September 3, 2008 at 6:53 pm

    Great example! 1000 thanks!

  3. 3 ernest
    October 2, 2008 at 7:35 pm

    going to try this out – looks like just what i need.

    you do know that the word is ‘horizontal’ not ‘horizantal’ or ‘HORIZANAL’ as you use these in your code… someone might have a hard time setting things up with these Strings.

    cheers

  4. 4 Shrikant Patil
    October 3, 2008 at 5:15 am

    Hi, ernest,.

    Thanks for your commitment. Yes that is a spell mistake i had done in the coding… i will update it soon.. thanks again.

  5. 5 Kach
    November 6, 2008 at 2:13 am

    Thank you for your solution. It worked for my project’s needs.

    However, if I use a PNG image with transparency (for the image’s edge to fade into the application background’s color) as the image to repeat horizontally, the transparency does not come through. Any solution to this?

  6. 6 Shrikant Patil
    November 6, 2008 at 5:01 am

    Hi,
    Thanks for you comment.
    If you see at the code, while it start to repeat the given image, it check the height and width of the image and starts repeating that image. so its totally on to you to create exact repeating image.

  7. 7 joe joe
    January 8, 2009 at 11:40 pm

    Awesome! Thanks so much.

  8. January 29, 2009 at 6:56 am

    Thanks for the script, but… If I make the width=”100%”, the repeating image does not span or even show up. This may be due to my own naiveness, but do you know any way to work around this?

  9. 9 Tom
    February 13, 2009 at 4:11 pm

    something I used to do all the time in Dreamweaver / HTML days and now running into this need with Flex…. and then I find this. Perfect!!!!

    Good work just what the doctor ordered.

  10. 10 Andrew
    April 20, 2009 at 6:13 pm

    Thanks for this… looks great.

    But what about if we wanted to change the background image at runtime?

    • 11 Shrikant Patil
      April 21, 2009 at 8:06 am

      all you need to do is the make public repeatingImage variable as bindable in class file. like;
      [Bindable]
      public var repeatingImage:Class…….

  11. 12 Andrew
    April 20, 2009 at 6:15 pm

    Sorry, I should have taken a closer look – it seems like you can simply put a non-embeded image link for repeatImage?

  12. May 14, 2009 at 8:25 am

    :) I’m 40,001 visitor to this blog! 40,001 hits

  13. 14 Stef
    May 14, 2009 at 10:03 am

    Wow, extra.
    But can you explain me how to do if I want to repeat horizontal & vertical ?
    Thanks a lot.

    • 15 Shrikant Patil
      May 15, 2009 at 4:16 am

      check for the ‘repeatDirection’ property of the component where you can set the either – horizantal or vertical.

      • 16 Stef
        May 15, 2009 at 8:23 am

        Thanks, but if I want horizontal AND vertical, not OR ?
        In this code, you can choose between, in css, repeat-x or repeat-y, but you can’t choose repeat.
        I’ve tried to modify it, but for sure, I’m not so strong for Flex at this time ^^

        Thanks a lot.

  14. 17 Andrew
    July 11, 2009 at 1:06 pm

    …I still can’t figure out how to switch the background at runtime. Could you be more specific with your suggestion?

  15. 18 Gabor
    July 18, 2009 at 11:53 am

    Thank you! …was very helpfull.

  16. July 22, 2009 at 2:41 pm

    Thanks a lot for taking the time to post this! :)

    Slight suggestion for a way you could improve compatibility (to include embedded UIMovieClip symbols, etc.). (Sorry in advance if my attempt at using a pre-tag in a comment fails.)

    override protected function updateDisplayList( w:Number, h:Number ):void {
      super.updateDisplayList( w, h );
    
      var imageInstance:* = new image();
      var bitmapData:BitmapData;
    
      if ( imageInstance is Bitmap ) {
        bitmapData = ( imageInstance as Bitmap ).bitmapData;
    
      } else if ( imageInstance is DisplayObject ) {
        bitmapData = new BitmapData( ( imageInstance as DisplayObject ).width, ( imageInstance as DisplayObject ).height );
        bitmapData.draw( imageInstance as DisplayObject );
    
      } else {
        return; // We can't work with this.
      }
    
      switch ( _direction ) {
        case HORIZANAL:
          h = bitmapData.height;
          break;
        case VERTICAL:
          w = bitmapData.width;
          break;
      }
    
      graphics.clear();
      graphics.beginBitmapFill( bitmapData );
      drawRoundRect( 0, 0, w, h );
      graphics.endFill();
    }

Leave a Reply