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:









[...] bookmarks tagged proud Active Window(S) Blur saved by 6 others Ottsell bookmarked on 07/07/08 | [...]
Very nice. A couple suggestions:
1) When two windows are layered, it would be nice if the front window blurred the one behind it.
2) Presently, the blur amount seems to be a global value. Can it be set for each window individually?
Awesome job.
[...] Read more [...]
I appreciate you taking the time to create this example. I am trying to build this, but, as a newbie to AS, I am having some trouble. I can’t seem to resolve the Background or GraphicWindow data type. Any suggestions?
Hey Steve,
Both items are MovieClips inside the .fla library. Once you have an object in the library, you can right click it and pick “linkage” from the context menu. Check the “Export for actionscript” box, leave the other boxes alone and in the Class textbox just put “Background” (for the image you want to be blurred) or “GraphicWindow” (for the window you want to drag around). Hope that helps out..
Devon,
Could you please post a .ZIP with the ActiveBlur class, FLA, and its corresponding document class?
Cheers!
Well, there’s really no more than what’s posted above, but since so many are asking, you can get the .fla that created the above .swf here. You’ll also need the ui package mentioned in this post to create the value slider control above – but the package isn’t necessary for general usage of the MWindowBlur class.
Hi, I’ve put together a really simple timeline example to try and get this working (before trying it on a more complicated project), but it doesn’t seem to be working… can you see any reason why?
////////////////////////////////////////////////////////////////////////////////
import com.onebyonedesign.extras.*;
var bg:Sprite = new Sprite();
var matr:Matrix = new Matrix();
matr.createGradientBox(200, 50, 20, -50, 200);
bg.graphics.beginGradientFill(“linear”, [0xff0000, 0x00ff00], [1,1], [150,255], matr);
bg.graphics.drawRoundRect(100,20,200,250,20);
bg.graphics.endFill();
addChild(bg);
var blur:MWindowBlur=new MWindowBlur(bg,100);
var box:Sprite = new Sprite();
box.graphics.beginFill(0x0000ff, 0.5);
box.graphics.drawRect(0,0,100,100);
box.graphics.endFill();
addChild(box);
box.addEventListener(MouseEvent.MOUSE_DOWN, drag);
blur.addWindow(box);
function drag(e:Event) {
box.removeEventListener(MouseEvent.MOUSE_DOWN, drag);
box.addEventListener(MouseEvent.MOUSE_UP, drop);
box.startDrag();
}//drag
function drop(e:Event) {
box.addEventListener(MouseEvent.MOUSE_DOWN, drag);
box.removeEventListener(MouseEvent.MOUSE_UP, drop);
box.stopDrag();
}//drag
Hey Chris. There’s a couple things causing the problem. For some reason, the blur windows cannot be created programmatically – they have to be exported from the library or on the stage. So, if you make your box a class in the library, that will take care of the biggest problem. The other thing is that the background object should be aligned to the origin (0,0). Do those two things and it should work fine.
RSS feed for comments on this post. / TrackBack URI