轻量高效的拓扑图组件
zh

Safari Web Content Guide - 事件处理

2011-07-22

事件处理

本章介绍iPhone OS中用户网页交互时产生的事件,表单和文档会产生和桌面版相似的事件,iPhone OS 上的 Safari通过手势模拟鼠标事件,此外你还可以直接监听多点触摸和手势事件,这些是iPhone OS特有的,方位事件是另一种iPhone OS特有的事件,还有一点需要知道是哪些事件不被支持,如剪切,复制,粘贴。 用户可使用手势代替鼠标事件,如双拍缩放,滑动平移,但是单触多点触摸能否产生这些事件取决于点击对象是否可点击或者可滚动,见 “One-Finger Events” 和 “Two-Finger Events.”中的描述。

可点击对象有:链接,表单对象,图片热点区或者其他添加了 mousemovemousedownmouseup, 或 onclick 监听的元素,可滚动元素是任何有正确 overflow 样式的对象,文本区域和可滚动的 iframe 元素。因为这些差异,你可能需要更改某些元素为可点击的,见 “Making Elements Clickable,” 中的介绍,了解其在iPhone OS下的行为特点。

此外,你可关闭Safari的默认行为,见 “Preventing Default Behavior”,并直接处理这些多点触摸和手势事件,这样保证开发人员能如同本地程序那样,实现独特,参阅 “Handling Multi-Touch Events” 和 “Handling Gesture Events” 了解更多触摸事件。 如果你希望在设备手持姿态变化时改变网页布局,可以参考 “Handling Orientation Events.” iPhone OS中支持的事件列表,见 “Supported Events” 触摸事件联合CSS特效是很常见的方式,见 Safari CSS Visual Effects Guide 了解更多CSS特效

单点触摸事件

本节使用流程图将手势分解成单个的可派发事件的执行动作,其中一些事件在iPhone OS中的发生是有条件的,如用户单指或双指触摸,有些手势不产生任何事件。 单指平移不会产生任何事件,直到用户停止平移 - 当页面停止移动并重新绘制时,会产生一个 onscroll 事件会产生 - 如图 6-1.

Figure 6-1 The panning gesture

The panning gesture

显示信息冒泡将不会产生任何事件,如图6-2,但是,如果用户点击并按住一个图片,信息冒泡将被一个图片保存界面代替。

iPhone OS Note: 图片保存单在 iPhone OS 2.0 起提供

Figure 6-2 点击,按住手势

The touch and hold gesture

最后,双击也不会产生任何事件,如图6-3

Figure 6-3 The double-tap gesture

The double-tap gesture

鼠标事件如其他浏览器所期待的那样派发,如图6-4。如果用户点击了一个不可点击的对象,没有事件发生,如果用户点击了一个可点击对象,事件按这样的顺序发生: mouseovermousemovemousedownmouseup, 和 click.  mouseout 事件只有在用户点击另一个可点击对象时产生,同时,如果 mousemove 事件中页面内容被改变,随后发生的事件将不会被发送,这样可以保证用户点击在新的内容上(if the contents of the page changes on the mousemove event, no subsequent events in the sequence are sent. This behavior allows the user to tap in the new content.)。

Figure 6-4 One-finger gesture emulating a mouse

One-finger gesture emulating a mouse

双指事件

双指拉伸和合并手势将不产生任何鼠标事件,如图6-5.

Figure 6-5 The pinch open gesture

The pinch open gesture

Figure 6-6 插图显示的是双指平移滚动产生的鼠标事件,这些事件如下所示:

  • 如果用户双指在可滚动对象上按下并划动,将会产生 mousewheel 事件.
  • 如果元素不可滚动,则平移整个页面,移动过程中不会产生任何事件
  • 停止移动时,会产生一个 onscroll 事件.

Figure 6-6 Two-finger panning gesture

Two-finger panning gesture

表单和文档事件

表单和文档产生特殊的事件,包括 blurfocusloadunloadresetsubmitchange 和 abort. 参阅 “Supported Events” 获取完整的 iPhone OS所支持的事件列表

使元素可点击

因为iPhone OS 下 Safari 采用模拟鼠标事件的方式,使你的一些元素在iPhone 下没有预期的行为,特别是一些菜单只使用 mousemove 事件处理,如列表 6-1,这时需要特殊处理,因为iPhone OS不会把他们当作可点击的元素来处理。 Listing 6-1 使用 mouseover 事件处理的菜单

<span onmouseover = "..."
  onmouseout  = "..."
WHERE TO BUY
</span>

要解决这个问题,需要添加一个空的 onclick 事件处理 onclick = "void(0)", 这样,iPhone OS 下 Safari就可以认为这个 span 元素是可点击元素,如表 6-2 Listing 6-2 添加一个 onclick 处理

<span onmouseover = "..."
  onmouseout  = "..."
  onclick = "void(0)">
WHERE TO BUY
</span>

处理多点触摸事件

你可以如本地程序那样,使用多点触控事件和手势监听 如果你监听了多点触摸事件,当Dom 元素被触摸或移动时,系统会派发 [TouchEvent](http://developer.apple.com/library/safari/documentation/UserExperience/Reference/TouchEventClassReference/TouchEvent/TouchEvent.html#//apple_ref/javascript/cl/TouchEvent)  事件,如果你不阻止默认行为( 详见“Preventing Default Behavior.” ),系统会增派一个模拟的鼠标事件,多点触摸过程中,触摸事件对象提供所有的触摸对象快照,最重要的是这些触摸对象都保持最新,触摸事件的不同类型见_Safari DOM Additions Reference_ 中的描述。 objects to those DOM elements as fingers touch and move across a surface. These are sent in addition to the emulated mouse events unless you prevent this default behavior as described in “Preventing Default Behavior.”A touch event provides a snapshot of all touches during a multi-touch sequence, most importantly the touches that are new or have changed for a particular target. The different types of multi-touch events are described in TouchEvent in Safari DOM Additions Reference. A multi-touch sequence begins when a finger first touches the surface. Other fingers may subsequently touch the surface, and all fingers may move across the surface. The sequence ends when the last of these fingers is lifted from the surface. An application receives touch event objects during each phase of any touch. Touch events are similar to mouse events except that you can have simultaneous touches on the screen at different locations. A touch event object is used to encapsulate all the touches that are currently on the screen. Each finger is represented by a touch object. The typical properties that you find in a mouse event are in the touch object, not the touch event object. Note that a sequence of touch events is delivered to the element that received the original touchstart event regardless of the current location of the touches. Follow these steps to use multi-touch events in your web application.

  1. Register handlers for multi-touch events in HTML as follows:
<div
  ontouchstart="touchStart(event);"
  ontouchmove="touchMove(event);"
  ontouchend="touchEnd(event);"
  ontouchcancel="touchCancel(event);"
></div>
  1. Alternatively, register handlers in JavaScript as follows:
element.addEventListener("touchstart", touchStart, false);
element.addEventListener("touchmove", touchMove, false);
element.addEventListener("touchend", touchEnd, false);
element.addEventListener("touchcancel", touchCancel, false);
  1. Respond to multi-touch events by implementing handlers in JavaScript. For example, implement the touchStart method as follows:
function touchStart(event) {
  // Insert your code here
}
  1. Optionally, get all touches on a page using the touches property as follows:
var allTouches = event.touches;

Note that you can get all other touches for an event even when the event is triggered by a single touch. 5. Optionally, get all touches for the target element using the targetTouches property:

var targetTouches = event.targetTouches;
  1. Optionally, get all changed touches for this event using the changedTouches property:
var changedTouches = event.changedTouches;
  1. Access the Touch object properties—such as the target, identifier, and location in page, client, or screen coordinates—similar to mouse event properties. For example, get the number of touches:
event.touches.length

Get a specific touch object at index i:

var touch = event.touches[i];

Finally, get the location in page coordinates for a single-finger event:

var x = event.touches[0].pageX;
var y = event.touches[0].pageY;

You can also combine multi-touch events with CSS visual effects to enable dragging or some other user action. To enable dragging, implement the touchmove event handler to translate the target:

function touchMove(event) {
    event.preventDefault();
    curX = event.targetTouches[0].pageX - startX;
    curY = event.targetTouches[0].pageY - startY;
    event.targetTouches[0].target.style.webkitTransform =
        'translate(' + curX + 'px, ' + curY + 'px)';
}

Typically, you implement multi-touch event handlers to track one or two touches. But you can also use multi-touch event handlers to identify custom gestures. That is, custom gestures that are not already identified for you by gesture events described in “Handling Gesture Events.” For example, you can identify a two-finger tap gesture as follows:

  1. Begin gesture if you receive a touchstart event containing two target touches.
  2. End gesture if you receive a touchend event with no preceding touchmove events.

Similarly, you can identify a swipe gesture as follows:

  1. Begin gesture if you receive a touchstart event containing one target touch.
  2. Abort gesture if, at any time, you receive an event with >1 touches.
  3. Continue gesture if you receive a touchmove event mostly in the x-direction.
  4. Abort gesture if you receive a touchmove event mostly the y-direction.
  5. End gesture if you receive a touchend event.

手势事件处理

多点触摸事件可以组合成更高级别的手势事件

多点触摸过程中,[GestureEvent](http://developer.apple.com/library/safari/documentation/UserExperience/Reference/GestureEventClassReference/GestureEvent/GestureEvent.html#//apple_ref/javascript/cl/GestureEvent) 事件也会产生,手势事件中包含缩放比例和旋转角度信息,如果平台支持,手势可以组合,如果不支持,一个手势结束另一个手势开始。如果你只想响应手势,可以只监听 GestureEvent 对象而不用处理低级别的 TouchEvent ,手势事件的不同类型描述见 Safari DOM Additions Reference.

按下面的步骤使用手势事件

  1. Register handlers for gesture events in HTML:
<div
  ongesturestart="gestureStart(event);"
  ongesturechange="gestureChange(event);"
  ongestureend="gestureEnd(event);"
></div>
  1. Alternatively, register handlers in JavaScript:
element.addEventListener("gesturestart", gestureStart, false);
element.addEventListener("gesturechange", gestureChange, false);
element.addEventListener("gestureend", gestureEnd, false);
  1. Respond to gesture events by implementing handlers in JavaScript. For example, implement the gestureChange method as follows:
function gestureChange(event) {
  // Insert your code here
}
  1. Get the amount of rotation since the gesture started:
var angle = event.rotation;

The angle is in degrees, where clockwise is positive and counterclockwise is negative. 5. Get the amount scaled since the gesture started:

var scale = event.scale;

The scale is smaller if less than 1.0 and larger if greater than 1.0.

你可以在手势事件中配合CSS特效实现缩放旋转或其他定制的用户动作,如,监听 gesturechange 事件,实现对目标对象的缩放和旋转:

onGestureChange: function(e) {
    e.preventDefault();
    e.target.style.webkitTransform =
        'scale(' + e.scale  + startScale  + ') rotate(' + e.rotation + startRotation + 'deg)';
}

取消默认行为

iPhone OS Note:  多点触摸和手指输入的 preventDefault 方法从 iPhone OS 2.0 开始支持.

The default behavior of Safari on iPhone OS can interfere with your application’s custom multi-touch and gesture input. You can disable the default browser behavior by sending the preventDefault message to the event object. For example, to prevent scrolling on an element in iPhone OS 2.0, implement the touchmove and touchstart event handlers as follows :

function touchMove(event) {
    // Prevent scrolling on this element
    event.preventDefault();
    ...
}

To disable pinch open and pinch close gestures in iPhone OS 2.0, implement the gesturestart and gesturechange event handlers as follows:

function gestureChange(event) {
    // Disable browser zoom
    event.preventDefault();
    ...
}

Important: The default browser behavior may change in future releases.

处理方位事件

An event is sent when the user changes the orientation of iPhone OS. By handling this event in your web content, you can determine the current orientation of the device and make layout changes accordingly. For example, display a simple textual list in portrait orientation and add a column of icons in landscape orientation. Similar to a resize event, a handler can be added to the <body> element in HTML as follows:

<body onorientationchange="updateOrientation();">

where updateOrientation is a handler that you implement in JavaScript. In addition, the window object has an [orientation](http://developer.apple.com/library/safari/documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html#//apple_ref/javascript/instp/DOMWindow/orientation) property set to either 0-9090, or 180. For example, if the user starts with the iPhone in portrait orientation and then changes to landscape orientation by turning the iPhone to the right, the window’s orientation property is set to -90. If the user instead changes to landscape by turning the iPhone to the left, the window’s orientation property is set to 90. Listing 6-3 adds an orientation handler to the body element and implements the updateOrientation JavaScript method to display the current orientation on the screen. Specifically, when an orientationchange event occurs, the updateOrientation method is invoked, which changes the string displayed by the division element in the body. Listing 6-3 Displaying the orientation

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Orientation</title>
        <meta name = "viewport" content="width=320, user-scalable=0"/>
        <script type="text/javascript" language="javascript">
            function updateOrientation()
            {
                var displayStr = "Orientation : ";
                switch(window.orientation)
                {
                    case 0:
                        displayStr += "Portrait";
                    break;
                    case -90:
                        displayStr += "Landscape (right, screen turned clockwise)";
                    break;
                    case 90:
                        displayStr += "Landscape (left, screen turned counterclockwise)";
                    break;
                    case 180:
                        displayStr += "Portrait (upside-down portrait)";
                    break;
                }
                document.getElementById("output").innerHTML = displayStr;
            }
    </script>
    </head>
    <body onorientationchange="updateOrientation();">
        <div id="output"></div>
    </body>
</html>

支持的事件

Be aware of all the events that iPhone OS supports and under what conditions they are generated. Table 6-1specifies which events are generated by Safari on iPhone OS and which are generated conditionally depending on the type of element selected. This table also lists unsupported events.

iPhone OS Note: Although drag and drop are not supported, you can produce the same effect using touch events as described in “Using Touch to Drag Elements” in Safari CSS Visual Effects Guide.

Next Prev