Recipe 6.8.
Creating Mouse Interactions
Problem
You want
users to interact with your movie using their mouse.
Solution
Use the various mouse events to listen for mouse
interactions on display objects of type InteractiveObject. Use the
read-only mouseX and
mouseY properties
from DisplayObject to
examine the mouse location relative to a display object, or the
localX and localY properties from the MouseEvent passed to a mouse
event handler.
Discussion
Basic mouse interaction can be created with the
SimpleButton class, as
described in Recipe
6.5. The SimpleButton class provides an easy way to
create a clickable button with different button visual states: up,
over, and down.
However, there are times when buttons just don't
provide enough interactivity. By listening to the various mouse
events, you can create interesting interactive experiences. For
instance, consider that you want to track the mouse cursor to
create an interactive drawing program, drawing lines on-screen
based on the user's mouse movement. Or, consider that you have a
maze that a user must navigate their mouse through without
colliding with the walls to find the exit. Or, perhaps the user's
mouse movement needs to control the direction of a golf club, and
the mouse button is used to swing.
These situations require use of the
special
InteractiveObject display object, which provides the ability
to respond to the user's mouse. If you go back to the introduction
for this chapter, you'll recall that the InteractiveObject
class is a base class fairly high in the display object class
hierarchy. Because of this, the Sprite, Loader, TextField, and MovieClip classes are all
examples of the InteractiveObject class since they fall
underneath InteractiveObject in the hierarchy, and you may
already be familiar with their use.
Instances of the InteractiveObject
dispatch the necessary events specific to mouse interaction. The
following is a list of more useful mouse events:
click
-
Generated when the user presses and releases the
mouse button over the interactive display object.
doubleClick
-
Generated when the user presses and releases the
mouse button twice in rapid succession over the interactive display
object.
mouseDown
-
Generated when the user presses the mouse button
over the interactive display object.
mouseUp
-
Generated when the user releases the mouse
button over the interactive display object.
mouseOver
-
Generated when the user moves the mouse pointer
from outside of the bounds of interactive display object to inside
of them.
mouseMove
-
Generated when the user moves the mouse pointer
while the pointer is inside the bounds of the interactive display
object.
mouseOut
-
Generated when the user moves the mouse pointer
from inside the bounds of an interactive display object to outside
of them.
mouseWheel
-
Generated when the user rotates the mouse wheel
while the mouse pointer is over the interactive display object.
Using these events is simply a matter of calling
addEventListener( ) on
the InteractiveObject and defining an event handler to
handle the MouseEvent passed to it.
The following code snippet creates a
Sprite, draws a red circle inside of it, and outputs a
message to the console whenever the mouse moves over the
circle:
package {
import flash.display.Sprite;
import flash.events.*;
import flash.geom.Point;
public class InteractiveMouseDemo extends Sprite {
public function InteractiveMouseDemo( ) {
var circle:Sprite = new Sprite( );
circle.x = 10;
circle.y = 10;
circle.graphics.beginFill( 0xFF0000 );
circle.graphics.drawCircle( 0, 0, 5 );
circle.graphics.endFill( );
circle.addEventListener( MouseEvent.MOUSE_MOVE, handleMouseMove );
addChild( circle );
}
// Event handle to capture the move event over the circle
private function handleMouseMove( event:MouseEvent ):void {
trace( "mouse move" );
}
}
}
In this example, notice that the message appears
only when the mouse is moved while the pointer is over the circle.
The circle defines the bounds for the Sprite in this
case.
|
Mouse events are generated from a particular
interactive display object only when the pointer is within the
bounds of that object.
|
|
Another common use of mouse events stems from
wanting to inspect the location of the mouse pointer to create
mouse interactivity. For example, to draw a line with the mouse,
the mouse location needs to be known so the line can be plotted
accurately. There are two ways to determine the location of the
mouse pointer:
The mouseX and mouseY properties can be
inspected to determine the location of the mouse cursor relative to
the top-left corner of the DisplayObject. Both of the
properties are read-only; it is not possible to set the location of
the mouse cursor, only to examine the location.
So, imagine that a rectangle is at x
location 20 and y location 50 and the user moves the mouse
pointer to x location 25 and y location 60. The
mouseX property of the rectangle returns 5 and
mouseY of the rectangle reports 10 because from the
rectangle's perspective, the mouse is 5 pixels in from the left and
10 pixels down from the top.
The localX and localY properties of the
MouseEvent are also relative. In the MouseEvent case,
the properties are relative to interactive display object that
dispatched the event. Therefore, consider that a rectangle reports
mouseX of 10 and dispatches a mouseMove event.
The event's localX property is also 10.
To get the global position of the mouse from
local coordinates, use the localToGlobal( ) method of the
DisplayObject class. The localToGlobal( ) method
takes flash.geom.Point as a parameter that specifies the
local coordinates, and returns a new Point with the
coordinates converted to the global space. The following code
snippet focuses on the event handler and demonstrates how to
convert localX and localY to global
coordinates:
// Event handler to respond to a mouseMove event
private function handleMouseMove( event:MouseEvent ):void {
/* Displays:
local x: 3.95
local y: 3.45
*/
trace( "local x: " + event.localX );
trace( "local y: " + event.localY );
// Create the point that localToGlobal should convert
var localPoint:Point = new Point( event.localX, event.localY );
// Convert from the local coordinates of the display object that
// dispatched the event to the global stage coordinates
var globalPoint:Point = event.target.localToGlobal( localPoint );
/* Displays:
global x: 13.95
global y: 13.45
*/
trace( "global x: " + globalPoint.x );
trace( "global y: " + globalPoint.y );
}
A complete working example of creating
interactivity through handling the various mouse events can be
demonstrated by the simple drawing program that follows. Whenever
the mouse is pressed, the drawing starts. As the user moves the
mouse around the screen, a line is drawn that follows the movement
of the mouse pointer. When the user releases the mouse button, the
drawing stops:
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
public class DrawingDemo extends Sprite {
// Flag to indicate whether the mouse is in draw mode
private var _drawing:Boolean;
public function DrawingDemo( ) {
// Configure the line style
graphics.lineStyle( 2, 0xFFCC33 );
// Drawing is false until the user presses the mouse
_drawing = false;
// Add the mouse listeners on the stage object to be
// notfied of any mouse event that happens while the
// mouse is over the entire movie
stage.addEventListener( MouseEvent.MOUSE_DOWN, startDrawing );
stage.addEventListener( MouseEvent.MOUSE_MOVE, draw );
stage.addEventListener( MouseEvent.MOUSE_UP, stopDrawing );
}
public function startDrawing( event:MouseEvent ):void {
// Move to the current mouse position to be ready for drawing
graphics.moveTo( mouseX, mouseY );
_drawing = true;
}
public function draw( event:MouseEvent ):void {
if ( _drawing ) {
// Draw a line from the last mouse position to the
// current one
graphics.lineTo( mouseX, mouseY );
}
}
public function stopDrawing( event:MouseEvent ):void {
_drawing = false;
}
}
}
See Also
Recipes 6.5,
6.9,
and Chapter
7
|