package { import flash.display.MovieClip; import flash.geom.Matrix; import flash.geom.Point; import flash.events.MouseEvent; import flash.events.Event; public class DragRotater extends MovieClip { private const DEGREES_TO_RADIANS = Math.PI / 180; private var _deceleration:Number = 0.8; private var _ratio:Number = 0.02 * DEGREES_TO_RADIANS; private var myMatrix:Matrix; private var lastMouse:Point; private var velocity:Point; private var angularVelocity:Number = 0; public function DragRotater(myDeceleration:Number = NaN, myRatio:Number = NaN, degree:Boolean = true) { if (! isNaN(myDeceleration)) { _deceleration = myDeceleration; } if (! isNaN(myRatio)) { if (degree) { ratio = myRatio; } else { _ratio = myRatio; } } buttonMode = true; addEventListener(MouseEvent.MOUSE_DOWN, xMouseDown); } public function get deceleration():Number { return _deceleration; } public function set deceleration(myDeceleration:Number):void { _deceleration = myDeceleration; } public function get ratio():Number { return _ratio / DEGREES_TO_RADIANS; } public function set ratio(myRatio:Number):void { _ratio = myRatio * DEGREES_TO_RADIANS; } private function xMouseDown(eventObject:MouseEvent):void { removeEventListener(Event.ENTER_FRAME, xThrow); addEventListener(Event.ENTER_FRAME, xDrag); stage.addEventListener(MouseEvent.MOUSE_UP, xMouseUp); lastMouse = new Point(parent.mouseX,parent.mouseY); } private function xMouseUp(eventObject:MouseEvent):void { removeEventListener(Event.ENTER_FRAME, xDrag); stage.removeEventListener(MouseEvent.MOUSE_UP, xMouseUp); addEventListener(Event.ENTER_FRAME, xThrow); } private function xDrag(eventObject:Event):void { var position:Point = new Point(x, y); var currentMouse:Point = new Point(parent.mouseX, parent.mouseY); var radius:Point = lastMouse.subtract(position); var force:Point = currentMouse.subtract(lastMouse); var moment:Number = crossProduct2D(radius, force); angularVelocity += moment * _ratio; myMatrix = transform.matrix; myMatrix.translate(-lastMouse.x, -lastMouse.y); myMatrix.rotate(angularVelocity); myMatrix.translate(currentMouse.x, currentMouse.y); transform.matrix = myMatrix; lastMouse = currentMouse.clone(); velocity = force; angularVelocity *= _deceleration; } private function xThrow(eventObject:Event):void { myMatrix = transform.matrix; myMatrix.translate(-x, -y); myMatrix.rotate(angularVelocity); myMatrix.translate(x + velocity.x, y + velocity.y); transform.matrix = myMatrix; velocity.normalize(velocity.length * _deceleration); angularVelocity *= _deceleration; if (Math.abs(angularVelocity) < 0.1 && velocity.length < 0.1) { removeEventListener(Event.ENTER_FRAME, xThrow); } } private function crossProduct2D(point0:Point, point1:Point):Number { return point0.x * point1.y - point0.y * point1.x; } } }