Home > Code Snippets, Tutorials > Dragging Object Around Circle in Flash with ActionScript 3

Dragging Object Around Circle in Flash with ActionScript 3

Dragging Object Around Circle in Flash with ActionScript 3

Challenge

Create a UI that allows dragging of DisplayObject around a circle.

Solution

The following two critical parts are used for implementation:

  1. We will employ MouseEvent.MOUSE_MOVE event so that our object reacts to the mouse pointer movements.
  2. Object position is calculated using Math package trigonometry methods. Moving around circle is all about angles.

There is not much to talk about. Below is a code that accomplishes what we want. All the “magic” happens in onMove() function. The result is: when you push mouse button down over the arrow and hold it – mouse move makes arrow rotate around the circle. Please read code comments.

Timeline Version

// UI container
var dial:Sprite;
// Draggable object. Can be anything. I chose arrow.
var arrow:Sprite;
// circle radius - play with changing this value
var radius:Number = 150;
// calculated angle
var angle:Number = 0;
// convert to radians - do it once to save on processing power
var angleConvert:Number = 180 / Math.PI;
// initiate application
init();
function init():void 
{
	makeDial();
	makeArrow();
}
/**
 * MouseEvent.MOUSE_MOVE handler.
 * @param	e
 */
function onMove(e:MouseEvent):void 
{
	// calculate angle between mouse position and the center of dial
	angle = Math.atan2(mouseY - dial.y, mouseX - dial.x);
	// reposition arrow according to angle
	arrow.x = radius * Math.cos(angle);
	arrow.y = radius * Math.sin(angle);
	// rotate arrow so that it always point outward
	arrow.rotation = angleConvert * angle + 90;
}
/**
 * MouseEvent.MOUSE_DOWN handler
 * @param	e
 */
function onArrowDown(e:MouseEvent):void 
{
	/**
	 * MouseEvents listeners are added to STAGE - not arrow.
	 * This way event if Mouse is not over arrow - interaction is preserved.
	 */
	stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
	stage.addEventListener(MouseEvent.MOUSE_UP, onStageUp);
}
/**
 * MouseEvent.MOUSE_UP handler
 * @param	e
 */
function onStageUp(e:MouseEvent):void 
{
	// by removing listeners we stop interaction.
	stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
	stage.removeEventListener(MouseEvent.MOUSE_UP, onStageUp);
}
/**
 * Instantiates dial container and draws circle inside it.
 */
function makeDial():void {
	dial = new Sprite();
	var g:Graphics = dial.graphics;
	g.lineStyle(1, 0x004000);
	g.drawCircle(0, 0, radius);
	dial.x = dial.y = radius + 50;
	addChild(dial);
}
/**
 * Instantiates arrow, draws triangle and adds arrow to dial display list.
 */
function makeArrow():void {
	arrow = new Sprite();
	// draw triangle
	var g:Graphics = arrow.graphics;
	g.beginFill(0x000080);
	g.moveTo(0, -15);
	g.lineTo(7, 6);
	g.lineTo( -7, 6);
	g.endFill();
	// position arrow on the top of circle
	arrow.y = -radius;
	dial.addChild(arrow);
	// make arrow interactive
	arrow.buttonMode = arrow.useHandCursor = true;
	arrow.addEventListener(MouseEvent.MOUSE_DOWN, onArrowDown);
}

Class Version

package 
{
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	public class Dial extends Sprite
	{
		// UI container
		private var dial:Sprite;
		// Draggable object. Can be anything. I chose arrow.
		private var arrow:Sprite;
		// circle radius - play with changing this value
		private var radius:Number = 150;
		// convert to radians - do it once to save on processing power
		private var angleConvert:Number = 180 / Math.PI;
		// calculated angle
		private var angle:Number = 0;
		/**
		 * Constructor.
		 */
		public function Dial() 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		/**
		 * Initializes UI
		 * @param	e
		 */
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			makeDial();
			makeArrow();
		}
		/**
		 * MouseEvent.MOUSE_MOVE handler.
		 * @param	e
		 */
		private function onMove(e:MouseEvent):void 
		{
			// calculate angle between mouse position and the center of dial
			angle = Math.atan2(mouseY - dial.y, mouseX - dial.x);
			// reposition arrow according to angle
			arrow.x = radius * Math.cos(angle);
			arrow.y = radius * Math.sin(angle);
			// rotate arrow so that it always point outward
			arrow.rotation = angleConvert * angle + 90;
		}
		/**
		 * MouseEvent.MOUSE_DOWN handler
		 * @param	e
		 */
		private function onArrowDown(e:MouseEvent):void 
		{
			/**
			 * MouseEvents listeners are added to STAGE - not arrow.
			 * This way event if Mouse is not over arrow - interaction is preserved.
			 */
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
			stage.addEventListener(MouseEvent.MOUSE_UP, onStageUp);
		}
		/**
		 * MouseEvent.MOUSE_UP handler
		 * @param	e
		 */
		private function onStageUp(e:MouseEvent):void 
		{
			// by removing listeners we stop interaction.
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onStageUp);
		}
		/**
		 * Instantiates dial container and draws circle inside it.
		 */
		private function makeDial():void {
			dial = new Sprite();
			var g:Graphics = dial.graphics;
			g.lineStyle(1, 0x004000);
			g.drawCircle(0, 0, radius);
			dial.x = dial.y = radius + 50;
			addChild(dial);
		}
		/**
		 * Instantiates arrow, draws triangle and adds arrow to dial display list.
		 */
		private function makeArrow():void {
			arrow = new Sprite();
			// draw triangle
			var g:Graphics = arrow.graphics;
			g.beginFill(0x000080);
			g.moveTo(0, -15);
			g.lineTo(7, 6);
			g.lineTo( -7, 6);
			g.endFill();
			// position arrow on the top of circle
			arrow.y = -radius;
			dial.addChild(arrow);
			// make arrow interactive
			arrow.buttonMode = arrow.useHandCursor = true;
			arrow.addEventListener(MouseEvent.MOUSE_DOWN, onArrowDown);
		}
	}
}
About these ads
Categories: Code Snippets, Tutorials
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: