One By One Design

Active Window(S) Blur

After taking another look at this post, I came up with a way of making multiple windows that will all blur the same image. I have to admit, though, I’m not particularly fond nor proud of the way I did it. The trouble is this: a masked display object can only have a single mask – so all items which will be used as a mask must be added to a single encompassing parent. But you would also like each mask item to be draggable along with the window it “rides behind”. Therefore, ideally, you’d like each mask item to be a child of the window instance (as I did it in the previous post). But there lies the rub. A display object can have only a single parent, hence you can’t add the child to both the mask and the window.

The solution I came up with was this: add the masking item to the mask instance and move the masking item with the window using an ENTER_FRAME event (rather than a parent-child relationship). If anyone has a more elegant solution, please post a comment. I’m probably overlooking something simple, but brilliant…

The MWindowBlur (Multiple Window Blur) class:

package com.onebyonedesign.extras { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.DisplayObjectContainer; import flash.display.Sprite; import flash.events.Event; import flash.filters.BlurFilter; import flash.geom.Point; import flash.utils.Dictionary; /** * Allows creation of multiple windows that blur the same background image * @author Devon O. */ public class MWindowBlur { private var _background:DisplayObjectContainer; private var _blurData:BitmapData; private var _blurImage:Bitmap; private var _blurAmount:int; private var _blur:BlurFilter; private var _mask:Sprite = new Sprite(); private var _point:Point = new Point(); private var _windows:Array = []; private var _maskDictionary:Dictionary = new Dictionary(true); public function MWindowBlur(background:DisplayObjectContainer, blurAmount:int = 8) { _background = background; _blurAmount = (blurAmount >= 0 && blurAmount <= 255) ? blurAmount : 8; _blur = new BlurFilter(_blurAmount, _blurAmount, 3); createBlur(); } public function addWindow(window:DisplayObjectContainer):Boolean { if (_windows.indexOf(window) > -1) return false; var WindowClass:Class = Object(window).constructor; var m:DisplayObjectContainer = new WindowClass(); m.transform = window.transform; m.filters = window.filters; if (window.scale9Grid) { m.scale9Grid = window.scale9Grid; } _maskDictionary[window] = m; _windows.push(window); if (!_mask.willTrigger(Event.ENTER_FRAME)) _mask.addEventListener(Event.ENTER_FRAME, moveMask); _mask.addChild(m); if (!_background.contains(_mask)) _background.addChild(_mask); return true; } public function removeWindow(window:DisplayObjectContainer = null):Boolean { if (!_windows.length) return false; if (!window) return removeWindow(_windows[_windows.length - 1]); var index:int = _windows.indexOf(window); if (index < 0) return false; _windows.splice(index, 1); _mask.removeChild(_maskDictionary[window]); if (!_windows.length) _mask.removeEventListener(Event.ENTER_FRAME, moveMask); return true; } public function kill():void { if (_mask.willTrigger(Event.ENTER_FRAME)) _mask.removeEventListener(Event.ENTER_FRAME, moveMask); if (_background.contains(_mask)) _background.removeChild(_mask); if (_background.contains(_blurImage)) _background.removeChild(_blurImage); _blurData.dispose(); _blurImage = null; _blurData = null; _maskDictionary = null; _background = null; _blur = null; } public function get blurAmount():int { return _blurAmount; } public function set blurAmount(value:int):void { _blurAmount = value; createBlur(); } private function createBlur():void { if (_blurData) _blurData.dispose(); _blur.blurX = _blur.blurY = _blurAmount; _blurData = new BitmapData(_background.width, _background.height, false); _blurData.draw(_background); _blurData.applyFilter(_blurData, _blurData.rect, _point, _blur); _blurImage = new Bitmap(_blurData); _blurImage.mask = _mask; _background.addChild(_blurImage); } private function moveMask(event:Event):void { var i:int = _windows.length; while (i--) { var w:DisplayObjectContainer = _windows[i]; var m:DisplayObjectContainer = _maskDictionary[w]; m.transform = w.transform; } } } }

The Flash document class for a test ride:

package { import com.onebyonedesign.extras.MWindowBlur; import com.onebyonedesign.ui.OBO_ValueSlider; import com.onebyonedesign.ui.events.ValueSliderEvent; import fl.controls.Button; import flash.display.MovieClip; import flash.display.Sprite; import flash.events.MouseEvent; import flash.filters.DropShadowFilter; import flash.text.AntiAliasType; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; /** * Demonstrates MWindowBlur (for multiple windows) Class * @author Devon O. */ public class Main extends Sprite { // GraphicWindow is MovieClip in .fla library private var _activeWindow:GraphicWindow; // Background is MovieClip in .fla library private var _bg:Background; private var _windowBlur:MWindowBlur; private var _shadow:DropShadowFilter = new DropShadowFilter(2, 90, 0x000000, 1, 2, 2, 1, 3); private var _windowArray:Array = []; public function Main():void { // Background is MovieClip in .fla library _bg = new Background(); addChild(_bg); init(); } private function init():void { initBlur(); initControlPanel(); addWindow(); } private function initBlur():void { _windowBlur = new MWindowBlur(_bg); } private function initControlPanel():void { var cp:Sprite = new Sprite(); cp.graphics.beginFill(0xEAEAEA); cp.graphics.drawRoundRect(0, 0, 222, 70, 10, 10); cp.graphics.endFill(); cp.filters = [_shadow]; cp.x = 10; cp.y = stage.stageHeight - cp.height - 10; var tf:TextField = new TextField(); var fmt:TextFormat = new TextFormat("_sans", 11); tf.defaultTextFormat = fmt; tf.autoSize = TextFieldAutoSize.LEFT; tf.selectable = false; tf.mouseEnabled = false; tf.antiAliasType = AntiAliasType.ADVANCED; tf.text = "Blur amount:"; tf.x = 5; tf.y = 5; cp.addChild(tf); var blurSlider:OBO_ValueSlider = new OBO_ValueSlider(139, 0, 32, _windowBlur.blurAmount); blurSlider.x = tf.x + tf.textWidth + 8; blurSlider.y = 13; blurSlider.addEventListener(ValueSliderEvent.DRAG, blurChangeHandler); cp.addChild(blurSlider); var b1:Button = new Button(); b1.label = "Add Window"; b1.x = 5; b1.y = 40; b1.addEventListener(MouseEvent.CLICK, addWindow); cp.addChild(b1); var b2:Button = new Button(); b2.label = "Remove Window"; b2.x = b1.x + b1.width + 10; b2.y = 40; b2.addEventListener(MouseEvent.CLICK, removeWindow); cp.addChild(b2); addChild(cp); } private function addWindow(event:MouseEvent = null):void { // GraphicWindow is MovieClip in library var window:GraphicWindow = new GraphicWindow(); window.width = randRange(50, 300); window.height = randRange(50, 200); window.x = randRange(0, 500 - window.width); window.y = randRange(0, 500 - window.height); window.filters = [_shadow]; _windowArray.push(window); addChild(window); _windowBlur.addWindow(window); window.addEventListener(MouseEvent.MOUSE_DOWN, pressHandler); } private function removeWindow(event:MouseEvent):void { if (_windowArray.length) { _windowBlur.removeWindow(); removeChild(_windowArray.pop()); } } private function blurChangeHandler(event:ValueSliderEvent):void { _windowBlur.blurAmount = int(event.value); } private function pressHandler(event:MouseEvent):void { _activeWindow = event.currentTarget as GraphicWindow; addChild(_activeWindow); stage.addEventListener(MouseEvent.MOUSE_UP, releaseHandler); _activeWindow.startDrag(false); } private function releaseHandler(event:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_UP, releaseHandler); _activeWindow.stopDrag(); } private function randRange(min:Number, max:Number):Number { return Math.floor(Math.random() * (max - min + 1)) + min; } } }

And a quick example:

[kml_flashembed movie="http://blog.onebyonedesign.com/wp-content/uploads/2008/07/windowblur2.swf" height="500" width="500" /]

Posted by

Post a comment

Your email address will not be published. Required fields are marked *