/** * Based on the code of the book Foundation ActionScript 3.0 Image Effects" by Todd Yard. */ package { import flash.events.*; import flash.display.GraphicsPathCommand; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.*; [SWF(width=550, height=400, backgroundColor=0xFFFFFF)] /** * Demonstrates how Graphics.drawPath() may be used to redraw vector lines by saving the drawing commands and data. */ public class graphic_flex_draw_classes_ChangingPointsOnAPathCurves extends Sprite { private const COLOR:uint = 0xFF; private const THICKNESS:uint = 3; private var _pathCommands:Vector.; private var _pathData:Vector.; private var _anchors:Vector.; private var _controlPoints:Vector.; private var _anchor:Sprite; private var _anchorIndex:uint; /** * Constructor. */ public function graphic_flex_draw_classes_ChangingPointsOnAPathCurves() { this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); } private function onAddedToStage(e:Event):void { this.init(); } /** * Initialization method for instantiating vector arrays and establishing listener for MOUSE_DOWN on the stage. */ private function init():void { _anchors = new Vector.(); _controlPoints = new Vector.; _pathCommands = new Vector.(); _pathData = new Vector.(); graphics.lineStyle(THICKNESS, COLOR); stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown); } /** * Adds an anchor point at the specified position. * * @param x The x position of the new anchor. * @param y The y position of the new anchor. */ private function addAnchor(x:Number, y:Number):void { var anchor:Sprite = new Sprite(); // this will draw a big dot if(_anchors.length % 2 == 0) anchor.graphics.lineStyle(10); else anchor.graphics.lineStyle(6,0xFF0000,0.5); anchor.graphics.lineTo(1, 0); anchor.addEventListener(MouseEvent.MOUSE_DOWN, onAnchorDown); anchor.addEventListener(MouseEvent.MOUSE_UP, onAnchorUp); anchor.x = x; anchor.y = y; addChild(anchor); _anchors.push(anchor); } /** * Uses Graphics.drawPath() to redraw path using commands and data stored in the vectors. */ private function redrawPath():void { graphics.clear(); graphics.lineStyle(THICKNESS, COLOR); graphics.drawPath(_pathCommands, _pathData); var dataLength:uint = _pathData.length; // must move to the last data position so that a new lines are drawn from this position graphics.moveTo(_pathData[dataLength-2], _pathData[dataLength-1]); } /** * Handler for when an anchor point is clicked. This begins drag of anchor point. * * @param event The MouseEvent caused by the click. */ private function onAnchorDown(event:MouseEvent):void { _anchor = event.target as Sprite; _anchor.startDrag(); // save the index so that the anchor's data can be easily accessed in the _pathData vector _anchorIndex = _anchors.indexOf(_anchor); stage.addEventListener(MouseEvent.MOUSE_MOVE, onAnchorMove); event.stopPropagation(); } /** * Handler for when the mouse moves while dragging an anchor. This updates the path data and redraws the path. * * @param event The MouseEvent caused by the move. */ private function onAnchorMove(event:MouseEvent):void { // update the path data that corresponds to the dragged anchor _pathData[_anchorIndex*2] = _anchor.x; _pathData[_anchorIndex*2+1] = _anchor.y; redrawPath(); if(_anchorIndex % 2!= 0){ graphics.lineStyle(1, 0, .5); graphics.moveTo(_pathData[_anchorIndex*2-2],_pathData[_anchorIndex*2-1]) graphics.lineTo(_anchor.x, _anchor.y); graphics.lineTo(_pathData[_anchorIndex*2+2],_pathData[_anchorIndex*2+3]); } event.updateAfterEvent(); } /** * Handler for when an anchor point is released after dragging. This removes the stage MOUSE_MOVE listener. * * @param event The MouseEvent caused by the release. */ private function onAnchorUp(event:MouseEvent):void { if (_anchor) { _anchor.stopDrag(); stage.removeEventListener(MouseEvent.MOUSE_MOVE, onAnchorMove); } } /** * Handler for when the stage is clicked. This adds a new anchor point and draws to the new anchor. * * @param event The MouseEvent caused by the click. */ private function onStageMouseDown(event:MouseEvent):void { var x:Number = stage.mouseX; var y:Number = stage.mouseY; // this means this is the first anchor, so only move to position without drawing if (_pathCommands.length < 1) { _pathCommands.push(GraphicsPathCommand.MOVE_TO); graphics.moveTo(x, y); addAnchor(x, y); _pathData.push(x, y); // else there are previous anchors, so simply draw to the new position } else { _pathCommands.push(GraphicsPathCommand.CURVE_TO); var dataLength:uint = _pathData.length; //calculate the initial values for the control points var cpX:Number = _pathData[dataLength-2]+(x-_pathData[dataLength-2])/2; var cpY:Number = _pathData[dataLength-1]+(y -_pathData[dataLength-1])/2; addAnchor(cpX, cpY); addAnchor(x, y); //graphics.curveTo(cpX, cpY, x, y); _pathData.push(cpX,cpY,x, y); redrawPath(); } } } }