Pure ActionScript 3 inverted mask 2.0

Update: I´ve rewritten the inverted mask-class from scratch and moved it here. It now support animated movieclips, video, webcam-feed and pretty much everything eles. I think.

About ten months ago I wrote a little as3-class that took care of something I think Adobe should have implemented in the FlashPlayer a long time ago, the inverted mask. As time went by I’ve added some features I found useful while working on projects at work. In this version you can swap between inverted and normal masks, hide/show the mask and remove it from memory.

Finally I just want to say: Adobe, I love Flash but I still think this is way to complicated. A simple DisplayObject.invertedMask = theMask; would be just fine. I know it’s easy to say ”just do it” but this is a feature a lot of developers would find useful.

Demo

The InvertedMask.as-class

package com.mattiasnorell.bitmap
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.display.Sprite;

/**
* Inverted Mask
* Version 2.0
*
* ...
* Original author:    Rachel Diesel
*                     http://dieselation.com/2009/04/11/inverting-a-mask-in-actionscript-3/
*
* Pure AS3 code    Mattias Norell
*                     http://blog.mattiasnorell.com/2010/08/21/pure-actionscript-3-inverted-mask-2/
*
*/

public class InvertedMask extends Sprite{

private var inverted:Sprite;
private var dup:BitmapData;
private var newAlpha:Bitmap;
private var isInverted:Boolean;

public function InvertedMask($parent:DisplayObject,$mask:DisplayObject,$maskPos:Object):void {
inverted = new Sprite();
inverted.x = $parent.x;
inverted.y = $parent.y;

dup = new BitmapData($mask.width, $mask.height, true, 0xffffff);
dup.draw($mask);

newAlpha = new Bitmap(dup, "auto", false);
newAlpha.x = $maskPos.x;
newAlpha.y = $maskPos.y;
newAlpha.blendMode = BlendMode.ERASE;

$mask.parent.removeChild($mask);

$parent.x=$parent.y = 0;

inverted.addChild($parent);
inverted.addChild(newAlpha);

inverted.blendMode = BlendMode.LAYER;

addChild(inverted);

isInverted = true;
}

public function moveMask($target:Object,$maskPos:Object):void {
$target.getChildAt(0).getChildAt(1).x  = $maskPos.x;
$target.getChildAt(0).getChildAt(1).y  = $maskPos.y;
}

public function Show():void{
inverted.blendMode = BlendMode.LAYER;
}

public function Hide():void{
inverted.blendMode = BlendMode.NORMAL;
}

public function autoShowHide():void{
(inverted.blendMode == BlendMode.LAYER) ? Hide() : Show();
}

public function swapMaskType($type:String = "auto"):void{
if($type == 'auto'){
$type = (isInverted == true) ? 'normal' : 'inverted';
}

if($type == 'inverted'){
Show();
inverted.mask = null;
isInverted = true;
}else if($type == 'normal'){
Hide();
inverted.mask = newAlpha;
isInverted = false;
}else{
trace("You must use either 'inverted','normal' or 'auto'.");
}
}

public function remove():void{
inverted.mask = null;
inverted.blendMode = BlendMode.NORMAL;

newAlpha.bitmapData.dispose();
newAlpha = null;
dup.dispose();
dup = null;
}
}
}

Source for the demo swf

When I code I use Flash Develop, hence the [Embed]-code below. If you use the Flash IDE just remove those two rows and import the image from the library.

package{
	import flash.display.Sprite;
	import flash.events.MouseEvent;

	public class Main extends Sprite{

		[Embed(source="image.jpg")]
		public var imgCls:Class;

		public function Main():void{
			var img:Sprite = new Sprite();
			img.addChild(new imgCls());
			addChild(img);

			var mask:Sprite = new Sprite();
			mask.graphics.beginFill(0xFF0000,1);
			mask.graphics.drawRect(0,0,30,30);
			mask.graphics.endFill();
			addChild(mask);

			var newMask:InvertedMask = new InvertedMask(img, mask, { x:0, y:0 } );
			addChild(newMask);

			newMask.addEventListener(MouseEvent.MOUSE_MOVE, moveMask);
			newMask.addEventListener(MouseEvent.CLICK, swap);
		}

		private function swap(e:MouseEvent):void {
			e.currentTarget.swapMaskType();
		}

		private function moveMask(e:MouseEvent):void {
			e.currentTarget.moveMask(e.currentTarget, { x:mouseX-10, y:mouseY-10 } );
		}
	}
}

Kommentarer



*