Proximity Menu Example and Source

This is an effect that I have seen on some Flash sites so I thought I would deconstruct it. To be honest, I’m not sure I like the effect, but with some tweaking it could be useful. Basically you have a menu of images or icons that react to the proximity of the mouse. If the mouse is close enough to a particular menu item, that menu item will snap to the mouse and follow it. When the mouse gets too far away the item will snap back into its original position.

In this example I created a nice rollover effect using blend modes. You can see how I created it by looking at the FLA file. All the ActionScript code is located in an external Document Class for easy viewing. I was planing on doing a tutorial on this but have decided to instead work on a multi-part tutorial on using AMFPHP. Look for that very soon!

You can download a ZIP file containing the FLA and the external AS file. If you just want to see the ActionScript, then you can view it below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package
{
    // Import Flash classes
    import flash.display.*;
    import flash.events.*;

    public class ProximityMenu extends MovieClip
    {
        private var ia:Array;
       
        public function ProximityMenu():void
        {
            ia = [im1, im2, im3, im4];
            for(var i:uint = 0; i < 4; i++)
            {
                ia[i].buttonMode = true;
                ia[i].ox = ia[i].x;
                ia[i].oy = ia[i].y;
                ia[i].tx = ia[i].ox;
                ia[i].ty = ia[i].oy;
                ia[i].addEventListener(MouseEvent.ROLL_OVER, onOver);
            }
            stage.addEventListener(Event.ENTER_FRAME, onMove);
        }
       
        private function onOver(e:MouseEvent):void
        {
            e.target.gotoAndPlay("over");
            addChild(MovieClip(e.target));
        }
       
        private function onMove(e:Event):void
        {
            for(var i:uint = 0; i < 4; i++)
            {
                var dist:Number =  getDist(mouseX, mouseY, ia[i].ox, ia[i].oy);
                if(dist < 70)
                {
                    ia[i].tx = mouseX;
                    ia[i].ty = mouseY;
                }
                else
                {
                    ia[i].tx = ia[i].ox;
                    ia[i].ty = ia[i].oy;
                }
                ia[i].x += Math.round((ia[i].tx - ia[i].x) * 0.3);
                ia[i].y += Math.round((ia[i].ty - ia[i].y) * 0.3);
            }
        }
       
        private function getDist(x1:Number, y1:Number, x2:Number, y2:Number):Number
        {
            var dx:Number = x2 - x1;
            var dy:Number = y2 - y1;
            return Math.sqrt(dx*dx + dy*dy);
        }
    }
}

Hope you enjoy it!
Lee


Commentary

  1. Cool menu with even better content. ;-)

  2. Jonathan Lackey says:

    Very cool. Thanks Lee!
    Now to find a place to use it. Shouldn’t be hard.

  3. Will says:

    I’m not a big fan of it. I think it may confuse users. Though I like the shine effect you have on the pictures.

    I look forward to your take on AMFPHP. I’ve used it extensively on my website http://www.cellpaint.com.

  4. Aubby says:

    Yeah. Cool effect, really comes out and ‘grabs’ u, or the mouse I guess. Personally I think its a little kitchy. Might be cooler as some kind of informational node in some information-gathering-display type of thing. Hmm. Maybe implemented as some kind of item dock in an air app or something. Wheee. Ideas!!

  5. Abel says:

    Personally I had hoped you had coded the mouse over blending effect as well. I can understand why you didn’t, but I think that could have been a very interesting and reusable class.

  6. gordee says:

    Possibly better suited to a touch screen perhaps … I also like the shine effect more than the snap effrvt. As ever thanks for sharing :)

  7. gordee says:

    That would be snap “effect” not effrvt!

  8. Beppino says:

    Very cool and fantastic shine effect trick, thanks Lee.
    Also a question: it’s necessary to call
    addChild(MovieClip(e.target));
    in the onOver function?
    Thanks al lot!

  9. creacog says:

    If one moves the cursor slowly, in the current version, with one image/option ‘active’, it is possible to move to positions where the next image as moved to pointer-position the old one back to it’s resting place, but for the old one to remain the ‘active’ option.

    I think it would feel better if the moment of the activation was brought forward with a tweak here and there.

  10. Beppino says:

    Sorry, I’ve miss a part of my last message:
    I’ve instead tried:
    setChildIndex(MovieClip(e.target),numChildren-1);
    :-[
    It’s ok?

  11. I particularly not like of these menus, but is a nice effect.

  12. oliver_l1 says:

    Unusual cool menu.I also look forward to your take on AMFPHP!.

  13. Robert says:

    Nice photos by the way!

  14. lee says:

    I did some timed comparisons of AMFPHP vs XML, and URLVariables, and Wade later asked whether I was using the C extension (or something unknown to myself), saying that it would dramatically improve the speed. I wasn’t to my knowledge. And I’ve also heard that even those you may specify AMF3 from Flash, AMFPHP doesn’t necessarily transfer with AMF3 protocol. Regardless AMFPHP was already faster than XML or URLVariables. As well I find it easier to consume and use the result data from AMFPHP than any other method. BlazeDS wasn’t available at the time, and I’ve not looked into using BlazeDS at all…

    Here’s my speed comparisons: http://www.leefernandes.com/blog/blog/Entries/2007/10/17_E4X_XML_vs_URLVariables_vs_AMFPHP_1.9_beta2.html

  15. I remember back in the days when Mjau-Mjau had their website built with the same effect, and that was about 4 years ago. What amazing time those were! :)

    Good to see such a clean code released for such a great effect. Keep up the good work Lee, and remember to live! ;)

  16. Steve W says:

    I’m going to have to agree with the Will, it’s a nice effect but i’d never use it for any kind of navigation. The only thing I could see something like this being used for is previewing thumbnail images of a gallery or something. Rolling over would make the image bigger and optionally add some description or title to it.

    Great shine effect. Yet another reason for me to get cracking on learning Actionscript 3 better.

  17. lee says:

    @Beppino Yes you need to call that so the image pops in front of the others.

  18. Macaca says:

    I like the shine also (simple technique, great effect), but the sticky proximity interaction ‘feels’ like a broken drag-n-drop thingie.

    Maybe the proximity range is a bit to large, or maybe don’t move the thumbs at all but just make them bigger the closer the mouse comes.

  19. J2 says:

    Hi~

    Which is the better for performance, addChild(MovieClip(e.target))
    or setChildIndex(MovieClip(e.target),numChildren-1) ?

    Thanks for the cool menu.

  20. Hi Lee.
    The addChild() issue that Beppino brought up I find interesting.. If I hadn’t seen this beautiful and clean example of yours [ ;) ], I would have guessed that calling addChild() to add a child that is in fact already there, would just add it on top of the child that is already there or cause an error since its not dynamic. But in your example, it seems that Flash picks up on that your calling addChild() to a child that is already there, and therefore just places that child on top of the display list (depth). Am I right? Maybe you could elaborate a little on that (pretty please).
    Thanks.

  21. lee says:

    @Christian Yes you are absolutely right. Calling addChild() on an item that is already on the list simply puts it at the top. I learned that from the Learning ActionScript 3 book.

  22. kaiserkingkaiser says:

    those who find it lacking with functionality, you can always expand lee’s example… i dont think lee would provide you something you exactly need for your site…

  23. Dan says:

    Nice effect… Glad i’m not the only one who was confused with how exactly addChild() worked to bring the item to the top!

  24. Great – I’ve swapped depths of several clips with a tedious function with swapChildren() before… silly me. Thanks a lot for clarifying. :)

  25. Min Thu says:

    Great effect, simply interesting!

  26. peter says:

    Looking very much forward to the new tutorial.

    I also like this class you’ve posted, looks very useful

    best regards
    Peter

  27. Terje B. says:

    AMFPHP…..thank you, thank you, thank you, Lee :)

  28. Robert says:

    Just excellent. Love the shine effect!

  29. Claude says:

    I try to understand the script:
    One problem: Where “over” in gotoandplay(“over”) is defined ?
    When i put anything at its place it continues working.
    thanks to answer me.

  30. George says:

    The effect may seem superfluous in this demo but I can think of certain areas where it would benefit the UI.

    For example, you could have an OS X dock style navigation menu. When not in use the menu could shrink down to a size where it’s both unobtrusive but also barely usable. The menu could then scale up in a predictive manner so by the time the mouse arrived at the menu it will have grown to the point where it’s usable. You could augment this further by predictively scaling the icon/menu entry you think the user is trying to hit (similar to the OS X dock effect except the scaling of an icon would be initiated before the users mouse was over the dock).

  31. JCRobinson says:

    Dude, nice girl friend!

    JC

  32. Amp says:

    Thanks for share, Lee.
    but I have some question about it. When I apply to my own work, it isn’t run anymore. So, I used to learn the as 3.0, it should have to set var for call the .as file, right? But I don’t see that code in your work. Is that the point to make my work is not run?

    Thanks for make inspiration for my work.

  33. Soviet says:

    Tried to do something with this Class, but it gives me “Error #1010: A term is undefined and has no properties.” or other funny errors :P .

  34. bob says:

    sometimes, there are two movieclip is moving, so i modify the onMove function, search for the max index movieclip, then set the action to it only. thanks, very cool.

    onMove function code:

    private function onMove(e:Event):void
    {
    var idxArray:Array = new Array();

    for(var i:uint = 0; i < 4; i++)
    idxArray.push(getChildIndex(ia[i]));

    idxArray.sort();

    var mc:MovieClip = MovieClip(getChildAt(idxArray.pop()));
    var dist:Number = getDist(mouseX, mouseY, mc.ox, mc.oy);

    if(dist < 70)
    {
    mc.tx = mouseX;
    mc.ty = mouseY;
    }
    else
    {
    mc.tx = mc.ox;
    mc.ty = mc.oy;
    }

    mc.x += Math.round((mc.tx – mc.x) * 0.3);
    mc.y += Math.round((mc.ty – mc.y) * 0.3);
    }

  35. Hey Lee, when I had seen this the first time, I thought it was really cool. I noticed you seemed to not think it would be very useful, though, if only for effect, but it gave me an idea. My sister has wanted a website for her photography for a while, and I thought of using those as links. I editted the idea a bit, but thought you might like to see the results. ;)

    http://www.dbinspiredarts.com/

    Thanks for the inspiration! Look forward to being in your session at MAX!

  36. Leonardo says:

    Hi Lee, first of all thank you very much for all your dedication in these kind of examples and in the tutorials of gotoandlearn!

    Here it’s my small problem, I’m just beginning working with Flash and tried to aply this great buttons into a fla with two scenes, the first one for preloader and the second one with the main stuff.
    The problem appears when the init fuction of the ProximityMenu class tries to start working with the buttons before the second scene is loaded and this error appears:

    Error #1009: Cannot access a property or method of a null object reference.
    at ProximityMenu$iinit()

    How should I fix this? sorry if it’s a stupid question… I’ll keep trying to fix it in the meantime

    Thanks!

  37. kj says:

    awesome!! especially for a noob like me! :)

  38. THanks i simply love the effect, very subtle

  39. Lew says:

    This menu example worked great for my site. I am trying to use it as a sort of ‘easter egg.’ So when people are moving their mice around the screen, the pictures will snap to the mouse, hopefully grabbing their attention and making them feel like they’re interacting with the page. Thanks much for this example. But now to why I’m posting.

    I am very new to Flash CS3 and I can’t seem to get this to work with the code already implemented in my site. I added it to the Document Class box in the Properties menu in my FLA, but when I compile it, the code I have in place breaks and I get this error “1046: Type was not found or was not a compile-time constant: URLRequest.” I’ve tried researching this error, but can’t seem to find a solution that fixes the issue.

    I have code written into my FLA for buttons that link to various places on my site and if this .as is in the Document Class box, everything breaks down. I don’t have the foggiest clue as to how to fix it. Any help would be greatly appreciated.

  40. Santiago says:

    Hi Lee.

    This is not exactly regarding this thread, but more to a core functionality with this thread – downloading :-)

    Do you use a plugin, that enables visitors to download a zip from this blog?

    And also do you use another plugin so you can make the javascript popup windows on the blog?

    Best regards
    Santiago

  41. Fidiman says:

    Hi,

    You can use the static method “distance” of the Point class too ?

    var dist:Number = Point.distance( new Point(x1,y1), new Point(x2,y2);

    Is it less fast ?

  42. Leipziger says:

    Hi, who is the turorial? It´s time to make it

  43. Leipziger says:

    please ;.)

  44. Leipziger says:

    make this mc´s with a Kinematic-Bone?

  45. Leipziger says:

    sorry for my bad english. I´m german

  46. alexandrosss says:

    i cant put link into the im1 im2 etc

  47. alexandrosss says:

    i have put 5more photos
    ia = [im1, im2, im3, im4, im5, im6, im7, im8];
    for(var i:uint=0; i<8; i++)

  48. May says:

    i put 2 photos
    ia = [im1, im2, im3, im4, im5, im6];
    for(var i:uint=0; i<6; i++)
    the result:
    1120: Access of undefined property im5.
    1120: Access of undefined property im6.
    Plz someone help me

  49. Cora says:

    Hi there

    Heeeelp pls!?!?!
    I’d love to use this script on a website, but I’m new at AS3 and I’m struggling!
    Everything works fine, but I don’t know how to add a click function on each of the movieclips – in other words, when you click either of the images, it plays another movieclip on another frame. Just not sure what code goes where…

    Thanks in advance!

  1. [... This is an effect that I have seen on some Flash sites so I thought I would deconstruct it. To be honest, I'm not sure I like the effect, but ...]

  2. [... This is an effect that I have seen on some Flash sites so I thought I would deconstruct it. To be honest, I'm not sure I like the effect, but ...]

Leave a Comment