views:

79

answers:

1

I'm attempting to find overlap between elements on a flex canvas, an adaptation of http://www.gskinner.com/blog/archives/2005/08/flash_8_shape_b.html

The attempt here is to place some text and figure overlap with previously placed text. The simple example below illustrates the problem.

Both ImageSnapshot.captureBitmapData(canvas); or BitmapData.draw(canvas);

do not seem to capture the elements placed on the canvas dynamically.

Any clues on how I can accomplish this?

Thanks in advance for any help. -vivek

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
               creationComplete="init()">
    <fx:Script>
        <![CDATA[
            import mx.controls.Image;
            import mx.controls.Text;
            import mx.graphics.ImageSnapshot;

            public function init():void {
                var l:Label = new Label();
                l.text = 'Dynamic Label!';
                l.x = text.x+50;
                l.y = text.y;
                canvas1.addElement(l);

                var bounds:Rectangle = text.getBounds(this);
                trace(bounds.top + ',' + bounds.left + ',' + bounds.width + ',' + bounds.height);
                var bmd:BitmapData = new BitmapData(text.width, text.height);
                bmd.draw(text);
                var bm:Bitmap = new Bitmap(bmd);
                var img:Image  = new Image();
                img.source = bm;
                img.x = 0;
                img.y = 20;
                canvas2.addChild(img);

                var c2:BitmapData = ImageSnapshot.captureBitmapData(canvas1);
                var bmd2:BitmapData = new BitmapData(text.width,text.height);
                bmd2.copyPixels(c2,bounds,new Point(0,0));
                var bm2:Bitmap = new Bitmap(bmd2);
                var img2:Image  = new Image();
                img2.source = bm2;
                img2.x = 0;
                img2.y = 50;
                canvas2.addChild(img2);

                var c3:BitmapData = new BitmapData(canvas1.width, canvas1.height);
                c3.draw(canvas1);
                var bmd3:BitmapData = new BitmapData(text.width,text.height);
                bmd3.copyPixels(c3,bounds,new Point(0,0));
                var bm3:Bitmap = new Bitmap(bmd2);
                var img3:Image  = new Image();
                img3.source = bm3;
                img3.x = 0;
                img3.y = 50;
                canvas3.addChild(img3);

            }
        ]]>
    </fx:Script>
    <mx:Canvas id="canvas1" width="400" height="100" backgroundColor="#FF0000">
        <s:Label id="text" x="200" y="50" text="This is a test"/>
    </mx:Canvas>
    <mx:Canvas id="canvas2" y="100" width="400" height="100" backgroundColor="#00FF00"/>    
    <mx:Canvas id="canvas3" y="200" width="400" height="100" backgroundColor="#0000FF"/>
</s:Application>
+2  A: 

Calling addChild doesn't make the component immediately visible/available within its parent. You need the creation process to complete before you grab the bitmap, which involves multiple phases/events. Put your grabbing code into a separate method and call it AFTER the creation process completes for your dynamically created component. Do that by using the callLater method, which will put your method call at the end of the event queue. Here's your code with callLater added (not that pretty, but hopefully it gets the point across):

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
               creationComplete="init()">
    <fx:Script>
        <![CDATA[
            import mx.controls.Image;
            import mx.controls.Text;
            import mx.graphics.ImageSnapshot;

            public function init():void {
                var l:Label = new Label();
                l.text = 'Dynamic Label!';
                l.x = text.x+50;
                l.y = text.y;
                canvas1.addElement(l);

                this.callLater(addRect);
            }

            private function addRect():void {

                var bounds:Rectangle = text.getBounds(this);
                trace(bounds.top + ',' + bounds.left + ',' + bounds.width + ',' + bounds.height);
                var bmd:BitmapData = new BitmapData(text.width, text.height);
                bmd.draw(text);
                var bm:Bitmap = new Bitmap(bmd);
                var img:Image  = new Image();
                img.source = bm;
                img.x = 0;
                img.y = 20;
                canvas2.addChild(img);

                var c2:BitmapData = ImageSnapshot.captureBitmapData(canvas1);
                var bmd2:BitmapData = new BitmapData(text.width,text.height);
                bmd2.copyPixels(c2,bounds,new Point(0,0));
                var bm2:Bitmap = new Bitmap(bmd2);
                var img2:Image  = new Image();
                img2.source = bm2;
                img2.x = 0;
                img2.y = 50;
                canvas2.addChild(img2);

                var c3:BitmapData = new BitmapData(canvas1.width, canvas1.height);
                c3.draw(canvas1);
                var bmd3:BitmapData = new BitmapData(text.width,text.height);
                bmd3.copyPixels(c3,bounds,new Point(0,0));
                var bm3:Bitmap = new Bitmap(bmd2);
                var img3:Image  = new Image();
                img3.source = bm3;
                img3.x = 0;
                img3.y = 50;
                canvas3.addChild(img3);

            }
        ]]>
    </fx:Script>
    <mx:Canvas id="canvas1" width="400" height="100" backgroundColor="#FF0000">
        <s:Label id="text" x="200" y="50" text="This is a test"/>
    </mx:Canvas>
    <mx:Canvas id="canvas2" y="100" width="400" height="100" backgroundColor="#00FF00"/>    
    <mx:Canvas id="canvas3" y="200" width="400" height="100" backgroundColor="#0000FF"/>
</s:Application>
Wade Mueller
perfect! thanks Wade. following up the line of thought, I came across http://livedocs.adobe.com/flex/3/html/help.html?content=components_06.html which led to using the UPDATE_COMPLETE event to achieve the same purpose.
Vivek
Great, glad I could help. Good tip on the UPDATE_COMPLETE event.
Wade Mueller