3 Replies Latest reply on Dec 16, 2011 11:21 PM by drkstr_1

    How to create a mask in a Flex mobile AIR app?

    Gregory Lafrance Level 6

      I have an overlay that covers my entire Flex AIR mobile app.

       

      I need to create a mask that reveals a rectangular sub-portion of the app, like a window showing part of the app.

       

      Normally I would use a mask, but I thought I had heard that use of masks were discouraged in Flex mobile apps. Is this true?

       

      If so, is there any way to draw the blue overlay (perhaps with drawPath method) so it displays like this, revealing part of the app (the red part) without a mask:

       

      overlay.png

        • 1. Re: How to create a mask in a Flex mobile AIR app?
          Flex harUI Adobe Employee

          To create a rectangle with a hole, you use path and define the boundaries

           

          MoveTo: 0,0; // outer edge of 300x300 rect

          LineTo: 0, 300

          LineTo: 300,300

          LineTo: 300, 0

          lineTo: 0,0

          MoveTo: 100, 100 // inner edge of 100x100 rect at 100, 100

          LineTo: 100, 200

          LineTo: 200,200

          LineTo: 200, 100

          LineTo: 100, 100

          • 2. Re: How to create a mask in a Flex mobile AIR app?
            Gregory Lafrance Level 6

            This almost works, but something strange is going on. When I use variables like the following for the second rectangle (the mask) the second drawn rectangle does not produce a "cutout" in the larger rectangle:

            hostComponent.appData.editOverlayMaskX

             

            But if I use numbers, as in the commented lines below, the cutout is drawn correctly.

             

            Any ideas?

             

             

             

                  private function drawOverlay():void{
                    var pointsRect:Vector.<int> = new Vector.<int>(10, true);
                    
                    pointsRect[0] = 1;
                    pointsRect[1] = 2;
                    pointsRect[2] = 2;
                    pointsRect[3] = 2;
                    pointsRect[4] = 2;
                    pointsRect[5] = 1;
                    pointsRect[6] = 2;
                    pointsRect[7] = 2;
                    pointsRect[8] = 2;
                    pointsRect[9] = 2;
                    
                    var pointsCoord:Vector.<Number> = new Vector.<Number>(20, true);
                    // moveTo coordinates for starting point
                    pointsCoord[0] = 0; //x
                    pointsCoord[1] = 0; //y 
                    // lineTo coordinates for the card top right
                    pointsCoord[2] = hostComponent.width; 
                    pointsCoord[3] = 0; 
                    // lineTo coordinates for the card right side
                    pointsCoord[4] = hostComponent.width; 
                    pointsCoord[5] = hostComponent.height; 
                    // lineTo coordinates for the card bottom
                    pointsCoord[6] = 0; 
                    pointsCoord[7] = hostComponent.height; 
                    // lineTo coordinates for the points bar left side
                    pointsCoord[8] = 0; 
                    pointsCoord[9] = 0; 
            //        // moveTo coordinates for tapped component mask starting point
            //        pointsCoord[10] = 20; //x
            //        pointsCoord[11] = 20; //y 
            //        // lineTo coordinates for tapped component mask top right
            //        pointsCoord[12] = 439.68; 
            //        pointsCoord[13] = 20; 
            //        // lineTo coordinates for tapped component mask right side
            //        pointsCoord[14] = 439.68; 
            //        pointsCoord[15] = 40.32; 
            //        // lineTo coordinates for tapped component mask bottom
            //        pointsCoord[16] = 20; 
            //        pointsCoord[17] = 40.32; 
            //        // lineTo coordinates for tapped component mask left side
            //        pointsCoord[18] = 20; 
            //        pointsCoord[19] = 20; 
                    
                    // moveTo coordinates for tapped component mask starting point
                    pointsCoord[10] = hostComponent.appData.editOverlayMaskX; //x
                    pointsCoord[11] = hostComponent.appData.editOverlayMaskY; //y 
                    // lineTo coordinates for tapped component mask top right
                    pointsCoord[12] = hostComponent.appData.editOverlayMaskWidth; 
                    pointsCoord[13] = hostComponent.appData.editOverlayMaskY; 
                    // lineTo coordinates for tapped component mask right side
                    pointsCoord[14] = hostComponent.appData.editOverlayMaskWidth; 
                    pointsCoord[15] = hostComponent.appData.editOverlayMaskHeight; 
                    // lineTo coordinates for tapped component mask bottom
                    pointsCoord[16] = hostComponent.appData.editOverlayMaskX; 
                    pointsCoord[17] = hostComponent.appData.editOverlayMaskHeight; 
                    // lineTo coordinates for tapped component mask left side
                    pointsCoord[18] = hostComponent.appData.editOverlayMaskX; 
                    pointsCoord[19] = hostComponent.appData.editOverlayMaskY; 
                    
                    
                    if(hostComponent.appData.debug){
                      trace(pointsCoord[10] + "," + pointsCoord[11]);
                      trace(pointsCoord[12] + "," + pointsCoord[13]);
                      trace(pointsCoord[14] + "," + pointsCoord[15]);
                      trace(pointsCoord[16] + "," + pointsCoord[17]);
                      trace(pointsCoord[18] + "," + pointsCoord[19]);
                    }
                    
                    graphics.beginFill(bgColor, .55);
                    graphics.drawPath(pointsRect, pointsCoord);
                  }
            
            
            • 3. Re: How to create a mask in a Flex mobile AIR app?
              drkstr_1 Level 4

              This is in a skin?

               

              Why are you calling properties on hostComponent instead of drawing in the updateDisplayList method for the skin (or layoutContents if extending MobileSkin)?

               

              Also, if possible, it's best to rasterize post processing effects (masks/filters/etc) for performance. This is probably what was being referred to when you read about masks being discouraged. Sometimes it is better to push these things onto the CPU (like a graphic that is being resized in an animation, for example).

               

              *edit*

               

              I see later in your code you are referencing data on the hostComponent, which makes a little more sense now why you are depending on hostComponent within your skin. I usually discourage this, but have been guilty of it myself sometimes in a pinch. I think a better solution would be to pass up a DisplayObject via a SkinPart, and have the hostComponent draw on it ...but I am starting to dabble in the realm of personal preference at this point... At the very least, make sure you are not calling on hostComponent until after it's been updated.