Making the points interactive: Hovering

In this recipe we focus on enriching the data display itself. When the user puts the mouse cursor over one of the points, we want to emphasize that point and show a small popup that displays more information about that point.

For example, we display the exact coordinates, but in a real-life application, you may want to show many other types of information. For instance, in a map display, you can show more information on the location that's beneath the cursor. In a results display, you might only show the average results, but when hovering over a point, you can also show the highest and lowest values.

Getting ready

We will start from the class that we have seen many times before:

package com.graphing.hover
{
    import flash.display.Sprite;
    import com.graphing.PointGraph;

    public class Recipe3 extends Sprite
    {
        private var _graph:PointGraph;
        private var _data:Array = [[0, 20], [50, 70], [100, 0], [150, 150], [200, 300], [250, 200], [300, 400], [350, 20], [400, 60], [450, 250], [500, 90], [550, 400], [600, 500], [650, 450], [700, 320]];

        public function Recipe3() 
        {
            _graph = new PointGraph();
            _graph.data = _data;
            _graph.graphWidth = 800;
            _graph.graphHeight = 600;
            _graph.graphLeft = -50;
            _graph.graphRight = 750;
            _graph.graphTop = 550;
            _graph.graphBottom = -50;
            _graph.createGraph();
            addChild(_graph);

            _graph.drawHorizontalAxis(0, 0, 700, 50, ["0", "700"]);
            _graph.drawVerticalAxis(0, 0, 500, 50, ["0", "250", "500"]);
        }
    }
}

How to do it...

First we will restructure the PointGraph code a bit, so that it's a little more modular and we can add some of the functionality more easily.

Let's extract the actual point shape into a new class, called PointGraphPoint (our first idea was to call this class simply point but that would have caused a lot of confusion with ActionScript's built-in point class):

  1. Start by adding a PointGraphPoint class:
    package com.graphing 
    {
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Point;
    
        public class PointGraphPoint extends Sprite
        {
            public function PointGraphPoint(point:Point, color:uint)
            {
                graphics.beginFill( color , 1 );
                graphics.drawCircle( 0 , 0 , 5 );
                x = point.x;
                y = point.y;
            }
        }
    }
  2. And now use that code in the drawPoint method of the PointGraph class:
    public function drawPoint(x:Number, y:Number, color:uint = 0xff9933):PointGraphPoint
    {
        var transformedLocation:Point = _matrix.transformPoint(new Point(x, y));
        var point:PointGraphPoint = new PointGraphPoint(transformedLocation, color); 
        addChild(point);
        return point;
    }

Now let's add a little zoom animation. When the user hovers the mouse over the point, it should become slightly bigger to emphasize it. This effect can be obtained fairly easily.

  1. In the PointGraphPoint class's constructor start listening for the mouse over and out events:
    addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
    addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
  2. And the implementation of the event handlers:
    private function onMouseOver(event:MouseEvent):void {
        scaleX = 1.5;
        scaleY = 1.5;
    }
    
    private function onMouseOut(event:MouseEvent):void {
        scaleX = 1;
        scaleY = 1;
    }

    Now let's show a message when the mouse is over a point in the graph. For this recipe, we want to show the coordinates of the point, so the user doesn't have to use the axes to find out.

    To display the information, we create a separate class.

  3. Create a new class called HoverInfo with the following code:
    package com.graphing.hover 
    {
        import flash.display.Sprite;
        import flash.text.TextField;
    
        public class HoverInfo extends Sprite {
            private var _text:TextField;
    
            public function HoverInfo() {
                _text = new TextField();
                _text.text = "info";
                _text.x = 5;
                _text.y = -20;
                addChild(_text);
            }
    
            public function set text(value:String):void {
                _text.text = value;
            }
        }
    
    }
  4. Add the following instance to the Recipe3 class:
    private var _hoverInfo:HoverInfo = new HoverInfo();
  5. To display it when the user hovers over a point, we first add the event listeners in the Recipe3 constructor:
    _graph.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
    _graph.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
  6. And implement those:
    private function onMouseOver(event:MouseEvent):void {
        if (event.target is PointGraphPoint) {
            addChild(_hoverInfo);
            _hoverInfo.text = event.target.message;
            _hoverInfo.x = event.target.x;
            _hoverInfo.y = event.target.y;
        }
    }
    
    private function onMouseOut(event:MouseEvent):void {
        if (_hoverInfo.parent != null) {
            removeChild(_hoverInfo);
        }
    }

You may have noticed that the actual text we display is taken from event.target.message. The event.target event is the PointGraphPoint class in this case, so we still need to add this field to it:

public var message:String;

Now it's a matter of filling up the point's message field with the message you'd like to show. In this case, we do this in the drawPoint method of the PointGraph class:

point.message = "(" + x + "," + y + ")";

How it works...

In this recipe, we've attached the event listeners in two ways. It's a good idea to know the two options and apply them as you see fit:

  • For emphasis on the points, we attached the listener to a single point. As we've seen, this results in very compact code that's very easy to read, because the code is present right in the PointGraphPoint class.
  • To show the message, we used a different approach: A listener is added to the entire graph, so the mouse over event will trigger every time the user hovers over a point or any element of the axes. In the listener method, we distinguished between the specific graph element from which the event came. This works because events are "bubbled" through the DisplayList hierarchy. In this case, only two listeners are needed, which can service the entire graph.

The second approach results in a more complicated and potentially a more confusing code. So in general, the first way is preferable, but it's good to know the options.

We also showed a slight performance optimization in how the HoverInfo class is used. We only instantiate it once and re-use it when information is displayed. Since the user's mouse pointer can only be over one point, this technique works. If you want to create something similar, where multiple information boxes will be displayed (for instance on a multi-touch display), you will need to adapt the approach.

There's more...

This recipe can be extended in many ways.

Attaching data to points

In the case of this recipe, we decided to attach the message directly to the data point. In many cases, this may not be possible, but you will need at least a way to identify the individual point, otherwise there's no way to know what message to show (unless it's always the same).

In general, you will probably replace the message field by an object that can hold any kind of data. For instance, if you are showing a time based graph, you could put the time in there and show a message based on that. Or you could put a database ID in the field and use it to look up information from the database when the user hovers over the point.

Better display

To keep the recipe simple and concise, little attention was given to the actual display. Given that the HoverInfo class is a standalone entity within the display list, you can put anything in there. You may add bitmaps or use the graphics class to draw something.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.109.141