Sticky Button class for Flash Actionscript 3

Enjoy this old, but still nice mjau-mjau.com sticky buttons script for AS3. Couldn't find it anywhere for AS2 or AS3 so i rewrote it for AS3; Feel free to use anywhere...


StickyButton Class for AS 3.0

There are very many ways you can use or adopt this class. Here is one of the simplest ways by specifying MovieClip base class in Library:
Download example (Flash CS3 .FLA file)

 
package {
 
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
 
	/**
	 * @author - darklow, First Intelligence www.first.lv (rewriting from AS 1.0 to AS 3.0)
	 * @author - www.mjau-mjau.vom (original AS 1.0 code author)
	 */
 
	public class StickyButton extends MovieClip	{
 
		private var accel:Number = .6;
		private var convert:Number = .7;
		private var r:Number = 3;
 
		private var xstart:Number;
		private var ystart:Number;
 
		private var targetx:Number;
		private var targety:Number;
		private var t:Number;
 
		private var xpos:Number = 0;
		private var ypos:Number = 0;
		private var drag:Number = 0;
		private var drag_this:Boolean = false;
		private var mouseOnStage:Boolean = false;
 
		public function StickyButton() {
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		private function init(e:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
			var iterations:Number = 5;
			xstart = x;
			ystart = y;
			targetx = xstart;
			targety = ystart;
			var xx:Number = (2 * Math.PI) * (1 / iterations);
			t = Math.tan(xx);
			addEventListener(Event.ENTER_FRAME, checkFrame);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, function(event:MouseEvent):void {
				mouseOnStage = true;
			});
			stage.addEventListener(Event.MOUSE_LEAVE, function(event:Event):void {
				mouseOnStage = false;
			});
		}
		private function checkFrame(e:Event):void {
			if (this.hitTestPoint(root.mouseX, root.mouseY, true) && mouseOnStage) {
				var deltax:Number = parent.mouseX - xstart;
				var deltay:Number = parent.mouseY - ystart;
				targetx = (parent.mouseX - deltax / r);
				targety = (parent.mouseY - deltay / r);
				if (!drag_this) {
					drag_this = true;
					drag++;
				}
			} else {
				targetx = xstart;
				targety = ystart;
				if (drag_this) {
					drag_this = false;
					drag--;
				}
			}
			xpos = xpos * accel + (targetx - x) * convert;
			x += xpos;
			ypos = ypos * accel + (targety - y) * convert;
			y += ypos;
		}
	}
}
 

13 Responses

Add your comment

  1. Dennis

    once I save this as *.AS file, how do you use it on a button? thanks for help….

  2. darklow

    There are very many ways you can use or adopt this class. Here is one of the simplest ways by specifying MovieClip base class in Library. I updated post with .FLA example ;)

  3. Dennis

    Thanks so much for the sample files. I get it now :) What is the best way to add an event to recenter the image once the mouse leaves a certain area? I notice the image gets stuck when leaving the stage, but I would like it to return once a certain limit is reached within the stage.

    addEventListener(Event.MOUSE_LEAVE, recenter);

    private function recenter(e:Event):void
    xpos = 100;
    ypos = 200;

  4. In that case we need to use Event.MOUSE_LEAVE and also MouseEvent.MOUSE_MOVE events and track if mouse is on the stage at all. I updated examples ;)

  5. Dennis

    Wow you are pro at this. Instead of detect if mouse left stage, how to detect if mouse has gone out of defined zone or for example 100 x or y from start?

  6. You can create transparent shape under the buttons in wanted size and track if mouse leaves or are over this area.
    1) Define private var mouseOnArea:Boolean = false;
    2) Create transparent shape under the buttons in desired size
    3) After shape is created, add listeners to it:
    shape.addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent):void {
    mouseOnArea = true;
    }
    shape.addEventListener(MouseEvent.MOUSE_OUT, function(event:MouseEvent):void {
    mouseOnArea = false;
    }
    4) Change this line:
    if (this.hitTestPoint(root.mouseX, root.mouseY, true) && mouseOnStage) {
    to:
    if (this.hitTestPoint(root.mouseX, root.mouseY, true) && mouseOnStage && mouseOnArea) {

    Should work ;)

  7. Dennis

    If you create an hidden shape under the area, do you have to name the instance?

  8. Yes you have to use instance name, but access to this shape is a bit different, because button (StickyButton class object) and background shape are children of same parent, you must access it through parent:
    Give your shape some instance name, for exameple: area
    and you can access to it using:
    var area:MovieClip = (this.parent as MovieClip).getChildByName(’area’) as MovieClip;
    trace(area);

  9. Love the code!, thank you for sharing.

  10. Jay

    How can I get this script to work if the button registration point is 0,0 ?

  11. Jay

    The solution is to update these lines:

    targetx = (parent.mouseX – deltax / r) – (width / r);
    targety = (parent.mouseY – deltay / r) – (height / r);

  12. p0rh9Z Good point. I hadn’t thought about it quite that way. :)

Leave a Comment