## How to Constrain Dragging to a Circle

Garden variety movie clip dragging is easy to handle via the `MovieClip.startDrag()`

and `MovieClip.stopDrag()`

methods. In fact, it’s even easy to constrain dragging to an arbitrary rectangular area. Just invoke these methods when handling the clip’s `MovieClip.onPress`

and `MovieClip.onRelease`

events.

```
// Standard dragging
mc.onPress = function() {
this.startDrag();
}
mc.onRelease = function() {
this.stopDrag();
}
// Constrained dragging
mc.onPress = function() {
this.startDrag(true, 0, 0, 200, 100);
}
mc.onRelease = function() {
this.stopDrag();
}
```

In that second example, the `MovieClip.startDrag()`

method is supplied with optional arguments. The first, a Boolean (`true`

/`false`

) determines whether the clip is dragged from its center or from the mouse’s position when the mouse first clicked. The rest refer to coordinates of the clip’s parent. If this clip is situated in the main timeline, the parent would *be* the main timeline. In this case, the movie clip will only be draggable within a 200×100 pixel rectangle.

So, what if you want to constrain dragging to a circle?

### An answer, short and sweet

To accomplish circular constraint, you’ll need to forego the built-in dragging methods. Assuming an instance name of `mc`

(as above), past the following into a frame of your scripts layer.

```
mc.origX = mc._x;
mc.origY = mc._y;
mc.onPress = function() {
this.onMouseMove = function() {
var angle:Number = Math.atan2(
_root._ymouse - this.origY,
_root._xmouse - this.origX
);
var distance:Number = Math.sqrt(
Math.pow(_root._xmouse - this.origX, 2) +
Math.pow(_root._ymouse - this.origY, 2)
);
if (Math.ceil(distance) >= 100) {
this._x = this.origX + (Math.cos(angle) * 100);
this._y = this.origY + (Math.sin(angle) * 100);
} else {
this._x = _root._xmouse;
this._y = _root._ymouse;
}
};
};
mc.onRelease = function() {
delete this.onMouseMove;
};
mc.onReleaseOutside = mc.onRelease;
```

### How it works

The first two lines take advantage of the fact that the `MovieClip`

class is dynamic, which means it may have new properties added to it at runtime. Two arbitrarily named properties, `origX`

and `origY`

, are set to the movie clip’s current position. This is just a way to keep track of where the clip was originally positioned — this location will be the center point of the circle constraint.

Next, a function literal is assigned to the `MovieClip.onPress`

event of the `mc`

movie clip. We’ll come back to that in a moment. Skip to the end, for now, and notice that a function literal is also assigned to the `MovieClip.onRelease`

event. This essentially cancels the function assigned to the `onPress`

. So, *press* to do some dragging (explained in a bit) and *release* to stop. While we’re at it, set `MovieClip.onReleaseOutside`

to the same thing as the release handler — after all, this movie clip’s movement is going to be constrained, so the mouse will not always be over it when the mouse lets go (we still want to cancel the dragging when the user lets go, right?).

Now, the meat and potatoes.

The function assigned to the `MovieClip.onPress`

event does the following: it, in turn, assigns a function literal to the `MovieClip.onMouseMove`

event of the same movie clip (via the global `this`

property). At this point, whenever the mouse moves, the following ActionScript is performed.

First, an arbitrary variable, `angle`

, is recorded. By way of the `Math.atan2()`

method, angle is set to the angle, in radians, of the mouse’s location as it pivots around the original location of `mc`

. (Note: read Is _root Evil? if you’re worried about using `_root`

. In my opinion, this is a perfectly valid use for it.)

Second, an arbitrary variable, `distance`

, is recorded. This makes use of the Pythagorean theorem (a2 + b2 = c2) to note the distance between the mouse’s location and the original location of `mc`

.

Finally, `angle`

and `distance`

(same as radius, in this context) are used in the standard formula for describing a circle …

x position = cosine of angle times radius

y position = sine of angle times radius

If the distance of the mouse from `mc`

’s original location is equal to or greater than 100 (just an arbitrary number), then the mouse is outside the imaginary circle. (`Math.ceil()`

is used to round this number up, because it is mostly likely going to be a lengthy decimal number.) If the mouse is outside that circle, it means we need to position `mc`

right *on* that circle. This is accomplished with these two lines:

```
this._x = this.origX + (Math.cos(angle) * 100);
this._y = this.origY + (Math.sin(angle) * 100);
```

… in which this still refers to `mc`

. So `mc`

’s `MovieClip._x`

property is set to whatever it’s original location was plus the cosine formula mentioned above, using the current angle and the same arbitrary 100 pixel radius. Same goes for the y position.

On the other hand, if the distance between the mouse and `mc`

’s original location is less than 100, simply set `mc`

’s position to the mouse’s position.

```
this._x = _root._xmouse;
this._y = _root._ymouse;
```