捕获用户输入简介
用户交互(无论是通过键盘、鼠标、摄像头还是这些设备的组合)是交互性的基础。在 ActionScript 3.0 中,识别和响应用户交互主要涉及事件侦听。
InteractiveObject 类是 DisplayObject 类的一个子类,它提供了处理用户交互所需的事件和功能的通用结构。您无法直接创建 InteractiveObject 类的实例。而是由显示对象(如 SimpleButton、Sprite、TextField 和各种 Flash 和 Flex 组件)从此类中继承其用户交互模型,因而它们使用同一个通用结构。这意味着,您为处理从 InteractiveObject 派生的一个对象中的用户交互而编写的代码以及学会的方法适用于所有其它对象。
捕获键盘输入
从 InteractiveObject 类继承交互模型的显示对象可以使用事件侦听器来响应键盘事件。例如,您可以将事件侦听器放在舞台上以侦听并响应键盘输入。在以下代码中,事件侦听器捕获一个按键,并显示键名和键控代码属性:
function reportKeyDown(event:KeyboardEvent):void
{
trace("Key Pressed: " + String.fromCharCode(event.charCode) + " (character code: " + event.charCode + ")");
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, reportKeyDown);
有些键(如 Ctrl 键)虽然没有字型表示形式,也能生成事件。
在上面的代码示例中,键盘事件侦听器捕获了整个舞台的键盘输入。也可以为舞台上的特定显示对象编写事件侦听器;当对象具有焦点时将触发该事件侦听器。
在以下示例中,仅当用户在 TextField 实例内键入内容时,才会在”输出”面板中反映键击。按下 Shift 键可暂时将 TextField 的边框颜色更改为红色。
此代码假定舞台上有一个名为 tf 的 TextField 实例。
tf.border = true;
tf.type = "input";
tf.addEventListener(KeyboardEvent.KEY_DOWN,reportKeyDown);
tf.addEventListener(KeyboardEvent.KEY_UP,reportKeyUp);
function reportKeyDown(event:KeyboardEvent):void
{
trace("Key Pressed: " + String.fromCharCode(event.charCode) + " (key code: " + event.keyCode + " character code: " + event.charCode + ")");
if (event.keyCode == Keyboard.SHIFT) tf.borderColor = 0xFF0000;
}
function reportKeyUp(event:KeyboardEvent):void
{
trace("Key Released: " + String.fromCharCode(event.charCode) + " (key code: " + event.keyCode + " character code: " + event.charCode + ")");
if (event.keyCode == Keyboard.SHIFT)
{
tf.borderColor = 0x000000;
}
}
捕获鼠标输入
鼠标单击将创建鼠标事件,这些事件可用来触发交互式功能。您可以将事件侦听器添加到舞台上以侦听在 SWF 文件中任何位置发生的鼠标事件。也可以将事件侦听器添加到舞台上从 InteractiveObject 进行继承的对象(例如,Sprite 或 MovieClip)中;单击该对象时将触发这些侦听器。
与键盘事件一样,鼠标事件也会冒泡。在下面的示例中,由于 square 是 Stage 的子级,因此,单击正方形时,将从 Sprite square 和 Stage 对象中调度该事件:
var square:Sprite = new Sprite();
square.graphics.beginFill(0xFF0000);
square.graphics.drawRect(0,0,100,100);
square.graphics.endFill();
square.addEventListener(MouseEvent.CLICK, reportClick);
square.x =
square.y = 50;
addChild(square);
stage.addEventListener(MouseEvent.CLICK, reportClick);
function reportClick(event:MouseEvent):void
{
trace(event.currentTarget.toString() + " dispatches MouseEvent.Local coords [" + event.localX + "," + event.localY + "] Stage coords [" + event.stageX + "," + event.stageY + "]");
}
请注意,在上面的示例中,鼠标事件包含有关单击的位置信息。localX 和 localY 属性包含显示链中最低级别的子级上的单击位置。例如,单击 square 左上角时将报告本地坐标 [0,0],因为它是 square 的注册点。或者,stageX 和 stageY 属性是指单击位置在舞台上的全局坐标。同一单击报告这些坐标为 [50,50],因为 square 已移到这些坐标上。取决于响应用户交互的方式,这两种坐标对可能是非常有用的。
MouseEvent 对象还包含 altKey、ctrlKey 和 shiftKey 布尔属性。可以使用这些属性来检查在鼠标单击时是否还按下了 Alt、Ctrl 或 Shift 键。
创建拖放功能
通过使用拖放功能,用户可以在按鼠标左键的同时选择对象,将该对象移到屏幕上的新位置,然后松开鼠标左键以将其放在新位置上。下面的代码显示了一个这样的示例:
import flash.display.Sprite;
import flash.events.MouseEvent;
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0xFFCC00);
circle.graphics.drawCircle(0, 0, 40);
var target1:Sprite = new Sprite();
target1.graphics.beginFill(0xCCFF00);
target1.graphics.drawRect(0, 0, 100, 100);
target1.name = "target1";
var target2:Sprite = new Sprite();
target2.graphics.beginFill(0xCCFF00);
target2.graphics.drawRect(0, 200, 100, 100);
target2.name = "target2";
addChild(target1);
addChild(target2);
addChild(circle);
circle.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown)
function mouseDown(event:MouseEvent):void
{
circle.startDrag();
}
circle.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);
function mouseReleased(event:MouseEvent):void
{
circle.stopDrag();
trace(circle.dropTarget.name);
}
有关更多详细信息,请参阅”创建拖放交互组件”。
自定义鼠标光标
可以将鼠标光标(鼠标指针)隐藏或交换为舞台上的任何显示对象。要隐藏鼠标光标,请调用 Mouse.hide() 方法。可通过以下方式来自定义光标:调用 Mouse.hide(),侦听舞台上是否发生 MouseEvent.MOUSE_MOVE 事件,以及将显示对象(自定义光标)的坐标设置为事件的 stageX 和 stageY 属性。下面的示例说明了此任务的基本执行过程:
var cursor:Sprite = new Sprite();
cursor.graphics.beginFill(0x000000);
cursor.graphics.drawCircle(0,0,20);
cursor.graphics.endFill();
addChild(cursor);
stage.addEventListener(MouseEvent.MOUSE_MOVE,redrawCursor);
Mouse.hide();
function redrawCursor(event:MouseEvent):void
{
cursor.x = event.stageX;
cursor.y = event.stageY;
}
自定义上下文菜单
从 InteractiveObject 类进行继承的每个对象可以具有唯一的上下文菜单,用户在 SWF 文件内右键单击时将显示该菜单。默认情况下,菜单中包含几个命令,其中包括”前进”、”后退”、”打印”、”品质”和”缩放”。
除了”设置”和”关于”命令外,您可以从菜单中删除所有其它默认命令。如果将 Stage 属性 showDefaultContextMenu 设置为 false,则会从上下文菜单中删除这些命令。
要为特定显示对象创建自定义的上下文菜单,请创建 ContextMenu 类的一个新实例,调用 hideBuiltInItems() 方法,并将该实例分配给该 DisplayObject 实例的 contextMenu 属性。下面的示例为一个动态绘制的正方形提供了一个上下文菜单命令,用于将其更改为随机颜色:
var square:Sprite = new Sprite();
square.graphics.beginFill(0x000000);
square.graphics.drawRect(0,0,100,100);
square.graphics.endFill();
square.x =
square.y = 10;
addChild(square);
var menuItem:ContextMenuItem = new ContextMenuItem("Change Color");
menuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,changeColor);
var customContextMenu:ContextMenu = new ContextMenu();
customContextMenu.hideBuiltInItems();
customContextMenu.customItems.push(menuItem);
square.contextMenu = customContextMenu;
function changeColor(event:ContextMenuEvent):void
{
square.transform.colorTransform = getRandomColor();
}
function getRandomColor():ColorTransform
{
return new ColorTransform(Math.random(), Math.random(), Math.random(),1,(Math.random() * 512) - 255, (Math.random() * 512) -255, (Math.random() * 512) - 255, 0);
}
管理焦点
交互式对象可以按编程方式或通过用户动作来获得焦点。在这两种情况下,设置焦点会将对象的 focus 属性更改为 true。另外,如果将 tabEnabled 属性设置为 true,用户可通过按 Tab 将焦点从一个对象传递到另一个对象。请注意,默认情况下,tabEnabled 值为 false,但以下情况除外:
对于 SimpleButton 对象,该值为 true。
对于输入文本字段,该值为 true。
对于 buttonMode 设置为 true 的 Sprite 或 MovieClip 对象,该值为 true。
在上述各种情况下,都可以为 FocusEvent.FOCUS_IN 或 FocusEvent.FOCUS_OUT 添加侦听器,以便在焦点更改时提供其它行为。这对文本字段和表单尤其有用,但也可以用于 sprite、影片剪辑或从 InteractiveObject 类进行继承的任何对象。下面的示例说明了如何使用 Tab 键启用焦点循环切换,以及如何响应后续的焦点事件。在本例中,每个正方形在收到焦点时将改变颜色。
注意
Flash 创作工具使用键盘快捷键来管理焦点;因此,要正确模拟焦点管理,应在浏览器中测试 SWF 文件,而不是在 Flash 中进行测试。
var rows:uint = 10;
var cols:uint = 10;
var rowSpacing:uint = 25;
var colSpacing:uint = 25;
var i:uint;
var j:uint;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
createSquare(j * colSpacing, i * rowSpacing, (i * cols) + j);
}
}
function createSquare(startX:Number, startY:Number, tabNumber:uint):void
{
var square:Sprite = new Sprite();
square.graphics.beginFill(0x000000);
square.graphics.drawRect(0, 0, colSpacing, rowSpacing);
square.graphics.endFill();
square.x = startX;
square.y = startY;
square.tabEnabled = true;
square.tabIndex = tabNumber;
square.addEventListener(FocusEvent.FOCUS_IN, changeColor);
addChild(square);
}
function changeColor(event:FocusEvent):void
{
e.target.transform.colorTransform = getRandomColor();
}
function getRandomColor():ColorTransform
{
// 为红色、绿色和蓝色通道生成随机值。
var red:Number = (Math.random() * 512) - 255;
var green:Number = (Math.random() * 512) - 255;
var blue:Number = (Math.random() * 512) - 255;
// 使用随机颜色创建并返回 ColorTransform 对象。
return new ColorTransform(1, 1, 1, 1, red, green, blue, 0);
}