package { import flash.display.Graphics; import flash.display.MovieClip; import flash.events.MouseEvent; import flash.geom.Point; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.ui.ContextMenu; import flash.ui.ContextMenuItem; import flash.ui.ContextMenuBuiltInItems; import flash.events.ContextMenuEvent; public class WeightedTrace extends MovieClip { private var BIG_DIST:Number = Math.sqrt(12); // lower = more sensitive ~[5,50] seems good private var MAX_WEIGHT:Number = 25; // thickest line possible (with slow draw speed) private var MIN_WEIGHT:Number = 1; // thinnest line possible (with fast draw speed) private var dMin:Number = 1; // minimum distance moved (first guess, will be updated while running) private var dMax:Number = 0; // maximum distance moved (first guess, will be updated while running) private var lastW:Number; private var lastMousePos:Point; private var currentMousePos:Point = new Point(); private var CM:ContextMenu; public function WeightedTrace() { super(); stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove); var item_clear:ContextMenuItem = new ContextMenuItem("Clear Canvas"); item_clear.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, onClear); CM = new ContextMenu(); CM.hideBuiltInItems(); CM.customItems.push(item_clear); CM.addEventListener(ContextMenuEvent.MENU_SELECT, onReset); contextMenu = CM; } private function onClear(e:ContextMenuEvent) { graphics.clear(); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove); } private function onReset(e:ContextMenuEvent) { stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove); lastMousePos = null; dMin = 1; dMax = 0; } private function onMove(e:MouseEvent):void { currentMousePos.x = stage.mouseX / stage.stageWidth; currentMousePos.y = stage.mouseY / stage.stageHeight; var w:Number; if (lastMousePos) { var d:Number = Math.pow(Point.distance(lastMousePos, currentMousePos), .05); if (d < dMin) dMin = d; if (d > dMax) dMax = d; d = (d - dMin) / (dMax - dMin); w = 1 - d; } else { graphics.moveTo(currentMousePos.x * stage.stageWidth, currentMousePos.y * stage.stageHeight); } if (lastW) { // average weight to smooth sharp changes w = (w*1 + lastW*2) / 3; graphics.lineStyle(w * (MAX_WEIGHT - MIN_WEIGHT) + MIN_WEIGHT, 0x000000); graphics.lineTo(currentMousePos.x * stage.stageWidth, currentMousePos.y * stage.stageHeight); } lastW = w; lastMousePos = currentMousePos.clone(); } } }