本文深入解析移动端Web开发中的JavaScript触摸与手势事件。详细阐述touchstart、touchmove、touchend及touchcancel等核心事件的触发机制与属性,包括touches、changedTouches等数组用法。同时介绍iOS Safari引入的gesture事件,涵盖rotation与scale属性,并提供桌面端模拟触摸及实际代码示例,帮助开发者实现流畅的多点触控交互体验。
移动端触摸开发挑战与模拟方案
在移动应用开发中,一种常见的策略是先在桌面端完成原型设计,随后再针对目标移动设备进行特定功能的适配。其中,多点触摸功能因大多数PC缺乏触摸输入设备而难以在桌面环境中进行测试。
若必须在移动设备上执行测试,开发周期可能会延长。因为每次代码修改都需要提交至服务器并加载到设备中。此外,由于平板电脑和智能手机上缺乏Web开发者常用的调试工具,应用运行后的调试工作也相对有限。
解决这一问题的方案之一是在开发机器上模拟触发事件。对于单点触摸,可以通过基于鼠标事件来模拟触摸行为。如果开发者拥有具备触摸输入功能的设备(如部分现代MacBook),则也可以模拟多点触摸操作。
单点触摸事件
若需在桌面端模拟单点触摸,可尝试使用Phantom Limb工具,该程序能在网页上模拟触摸事件并提供虚拟手势引导。此外,还有Touchable这一jQuery插件,它能够跨平台统一处理触摸和鼠标事件。
多点触摸事件
为了使多点触摸Web应用在浏览器或具备多点触控功能的设备(如Apple MacBook或MagicPad)上正常运行,开发者可以借助MagicTouch.js填充工具。该工具能捕获触控板发出的触摸事件,并将其转换为符合标准的触摸事件。具体步骤如下: 1. 下载npTuioClient NPAPI插件,并将其安装至~/Library/Internet Plug-Ins/目录。 2. 下载适用于Mac MagicPad的TongSeng TUIO应用并启动服务器。 3. 下载MagicTouch.js JavaScript库,以便基于npTuioClient回调模拟符合规范的触摸事件。 4. 在应用中按以下方式引入magictouch.js脚本和npTuioClient插件:
< head>
...
< script src="/path/to/magictouch.js" kesrc="/path/to/magictouch.js">< /script>
< /head>
< body>
...
< object id="tuio" type="application/x-tuio" style="width: 0px; height: 0px;">
Touch input plugin failed to load!
< /object>
< /body>
该方法仅在Chrome 10版本上进行了测试,但经过适当调整,预计可在其他现代浏览器中运行。
若计算机不具备多点触摸输入功能,可使用其他TUIO跟踪器(如reacTIVision)来模拟触摸事件。更多信息可参考TUIO项目页面。
需要注意的是,所定义的手势可与操作系统层面的多点触摸手势保持一致。在OS X系统中,用户可以通过“系统偏好设置”中的“触控板”面板来配置系统级事件。
随着多点触摸功能在跨移动浏览器中得到广泛支持,令人欣慰的是,新的Web应用正充分利用这一丰富的API。
原文来源:html5rocks.com 原文标题:Developing for Multi-Touch Web Browsers
JavaScript触摸事件基础
一、手机上的触摸事件
基本事件:
touchstart:手指刚接触屏幕时触发。 touchmove:手指在屏幕上移动时触发。 touchend:手指从屏幕上移开时触发。
此外,还有一个较少使用的事件:touchcancel,当触摸过程被系统取消时触发。
每个事件都包含以下列表属性,例如在touchend事件中,targetTouches的值通常为0:
touches:位于屏幕上的所有手指的列表。 targetTouches:位于该特定元素上的所有手指的列表。 changedTouches:涉及当前事件的所有手指的列表。
每个事件列表中的每个触摸对象还包含以下属性:
其中,常用的坐标属性包括pageX和pageY:
pageX:相对于页面的X坐标。 pageY:相对于页面的Y坐标。 clientX:相对于视区的X坐标。 clientY:相对于视区的Y坐标。 screenX:相对于屏幕的X坐标。 screenY:相对于屏幕的Y坐标。 identifier:当前触摸点的唯一编号。 target:手指所触摸的DOM元素。
其他相关事件及方法: event.preventDefault():用于阻止触摸时浏览器的缩放及滚动条滚动。 var supportTouch = "createTouch" in document:用于判断浏览器是否支持触摸事件。
二、示例
以下是获取不同类型滑动操作的代码具体做法,结合前人经验进行了封装,可供借鉴学习:
var touchFunc = function(obj,type,func) {
//滑动范围在5x5内则做点击处理,s是开始,e是结束
var init = {x:5,y:5,sx:0,sy:0,ex:0,ey:0};
var sTime = 0, eTime = 0;
type = type.toLowerCase();
obj.addEventListener("touchstart",function(){
sTime = new Date().getTime();
init.sx = event.targetTouches[0].pageX;
init.sy = event.targetTouches[0].pageY;
init.ex = init.sx;
init.ey = init.sy;
if(type.indexOf("start") != -1) func();
}, false);
obj.addEventListener("touchmove",function() {
event.preventDefault();//阻止触摸时浏览器的缩放、滚动条滚动
init.ex = event.targetTouches[0].pageX;
init.ey = event.targetTouches[0].pageY;
if(type.indexOf("move")!=-1) func();
}, false);
obj.addEventListener("touchend",function() {
var changeX = init.sx - init.ex;
var changeY = init.sy - init.ey;
if(Math.abs(changeX)>Math.abs(changeY)&&Math.abs(changeY)>init.y) {
//左右事件
if(changeX > 0) {
if(type.indexOf("left")!=-1) func();
}else{
if(type.indexOf("right")!=-1) func();
}
}
else if(Math.abs(changeY)>Math.abs(changeX)&&Math.abs(changeX)>init.x){
//上下事件
if(changeY > 0) {
if(type.indexOf("top")!=-1) func();
}else{
if(type.indexOf("down")!=-1) func();
}
}
else if(Math.abs(changeX)<init.x && Math.abs(changeY)<init.y){
eTime = new Date().getTime();
//点击事件,此处根据时间差细分下
if((eTime - sTime) > 300) {
if(type.indexOf("long")!=-1) func(); //长按
}
else {
if(type.indexOf("click")!=-1) func(); //当点击处理
}
}
if(type.indexOf("end")!=-1) func();
}, false);
};
转载的文章:手机触摸屏的JS事件
处理Touch事件可以追踪用户每一根手指的位置。开发者可以绑定以下四种Touch事件:
1. touchstart:手指放到屏幕上时触发。 2. touchmove:手指在屏幕上移动时触发。 3. touchend:手指从屏幕上拿起时触发。 4. touchcancel:系统取消touch事件时触发。关于系统具体何时取消,文档中未明确说明。
属性
1. clientX / clientY:触摸点相对于浏览器窗口viewport的位置。 2. pageX / pageY:触摸点相对于页面的位置。 3. screenX / screenY:触摸点相对于屏幕的位置。 4. identifier:touch对象的唯一ID。
//touchstart事件
function touchSatrtFunc(e) {
//evt.preventDefault(); //阻止触摸时浏览器的缩放、滚动条滚动等
var touch = e.touches[0]; //获取第一个触点
var x = Number(touch.pageX); //页面触点X坐标
var y = Number(touch.pageY); //页面触点Y坐标
//记录触点初始位置
startX = x;
startY = y;
}
//touchmove事件
function touchMoveFunc(e) {
//evt.preventDefault(); //阻止触摸时浏览器的缩放、滚动条滚动等
var touch = evt.touches[0]; //获取第一个触点
var x = Number(touch.pageX); //页面触点X坐标
var y = Number(touch.pageY); //页面触点Y坐标
var text = 'TouchMove事件触发:(' + x + ', ' + y + ')';
//判断滑动方向
if (x - startX != 0) {
//左右滑动
}
if (y - startY != 0) {
//上下滑动
}
}
转载的第二篇文章:Mobile Web前端开发系列: 事件处理(二)
上篇文章讲解了HTML基本事件,本文重点讲解触摸事件。触摸事件的触发条件是手指接触屏幕、在屏幕上移动或从屏幕离开。事件是触摸的集合,起始于手指初次放置在屏幕上,终止于最后一个手指离开屏幕。从开始到结束过程中的所有触摸操作都存储在相同事件的记录中。
touch事件
touch事件可分为单点触摸和多点触摸两种。单点触摸在高端机型中普遍支持,Safari 2.0及Android 3.0以上版本支持多点触摸,最多支持5个手指同时触摸屏幕,iPad最多支持11个手指。可采用以下事件模型捕获这些事件: ontouchstart、ontouchmove、ontouchend、ontouchcancel。
当用户手指按下屏幕时,触发ontouchstart;移动一个或多个手指时,触发ontouchmove;移走手指时,触发ontouchend。至于ontouchcancel的触发时机,通常发生在更高级别的事件发生时,例如弹出alert、接到电话或有推送消息时,这会取消当前的touch操作。在开发Web游戏时,ontouchcancel非常重要,可在触发时暂停或保存游戏。
手势事件与属性详解
gesture事件
gesture事件的运行原理与touch事件相同,但仅在屏幕上存在至少两个手指时触发。Safari 2.0及Android 3.0以上版本支持。手势事件具备测量两指放缩和旋转操作的优势,事件模型如下: ongesturestart、ongesturechange、ongestureend。
事件属性
无论使用触摸还是手势事件,都需要将这些事件转换为单独的触摸以便使用。为此,需要访问事件对象的一系列属性。
targetTouches:目标元素的所有当前触摸。 changedTouches:页面上最新更改的所有触摸。 touches:页面上的所有触摸。
changedTouches、targetTouches和touches分别包含略有不同的触摸列表。targetTouches和touches包含当前位于屏幕上的手指列表,但changedTouches仅列出最后发生的触摸。在使用touchend或gestureend事件时,此属性尤为重要,因为此时屏幕上已无手指,targetTouches和touches应为空,但可通过changedTouches数组了解最后发生的情况。
由于触摸属性均生成数组,可使用JavaScript数组函数访问它们。例如,event.touches[0]返回第一次触摸,使用event.touches.length可计算当前存储的触摸数量。
查看单独触摸时,通过event.targetTouches[0]可访问其他触摸,每个触摸包含具体信息。
clientX、clientY:相对于当前屏幕的X或Y位置。 pageX、pageY:相对于整体页面的X或Y位置。 screenX、screenY:相对于用户计算机屏幕的X或Y位置。 identifier:事件的唯一标识符。 target:生成触摸的目标对象。
手势事件的事件对象比普通触摸事件多出两个属性:rotation(手指的旋转角度)和scale(放缩的值)。
转载文章:JavaScript触摸与手势事件
iOS Safari专有事件与实现
iOS版Safari为传达特殊信息,新增了一些专有事件。由于iOS设备无鼠标和键盘,常规鼠标和键盘事件在移动Safari开发中不够用。随着Android中WebKit的加入,许多此类专有事件已成为事实标准。
1.触摸事件
包含iOS 2.0软件的iPhone 3G发布时,也包含了一个新版本的Safari浏览器。这款移动Safari提供了与触摸(touch)操作相关的新事件。后来,Android上的浏览器也实现了相同的事件。触摸事件会在用户手指放在屏幕上面、在屏幕上滑动或从屏幕上移开时触发。具体包括以下几个触摸事件。
touchstart:当手指触摸屏幕时触发,即使已有手指在屏幕上也会触发。 touchmove:当手指在屏幕上滑动时连续触发。调用preventDefault()可阻止滚动。 touchend:当手指从屏幕上移开时触发。 touchcancel:当系统停止跟踪触摸时触发。文档中未明确说明确切触发时机。
上述事件均会冒泡且可取消。虽然这些触摸事件未在DOM规范中定义,但均以兼容DOM的方式实现。因此,每个触摸事件的event对象都提供了鼠标事件中常见的属性:bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey和metaKey。
除常见DOM属性外,触摸事件还包含下列三个用于跟踪触摸的属性: touches:表示当前跟踪的触摸操作的Touch对象数组。 targetTouches:特定于事件目标的Touch对象数组。 changedTouches:表示自上次触摸以来发生改变的Touch对象数组。
每个Touch对象包含下列属性: clientX:触摸目标在视口中的X坐标。 clientY:触摸目标在视口中的Y坐标。 identifier:表示触摸的唯一ID。 pageX:触摸目标在页面中的x坐标。 pageY:触摸目标在页面中的y坐标。 screenX:触摸目标在屏幕中的x坐标。 screenY:触摸目标在屏幕中的y坐标。 target:触摸的DOM节点坐标。
使用这些属性可跟踪用户对屏幕的触摸操作。示例如下。
function handleTouchEvent(event) {
//只跟踪一次触摸
if (event.touches.length == 1) {
var output = document.getElementById("output");
switch (event.type) {
case "touchstart":
output.innerHTML = "Touch started (" + event.touches[0].clientX + "," + event.touches[0].clientY + ")";
break;
case "touchend":
output.innerHTML += "<br>Touch ended (" + event.changedTouches[0].clientX + "," + event.changeTouches[0].clientY + ")";
break;
case "touchmove":
event.preventDefault(); //阻止滚动
output.innerHTML += "<br>Touch moved (" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")";
break;
}
}
}
document.addEventListener("touchstart", handleTouchEvent, false);
document.addEventListener("touchend", handleTouchEvent, false);
document.addEventListener("touchmove", handleTouchEvent, false);
以上代码会跟踪屏幕上发生的一次触摸操作。为简化起见,仅在有一次活动触摸操作时输出信息。当touchstart事件发生时,会将触摸的位置信息输出到
元素中。当touchmove事件发生时,会取消其默认行为以阻止滚动(触摸移动的默认行为是滚动页面),然后输出触摸操作的变化信息。而touchend事件则会输出有关触摸操作的最终信息。注意,在touchend事件发生时,touch集合中已无Touch对象,因为不存在活动触摸操作;此时需转而使用changedTouches集合。
这些事件会在文档的所有元素上触发,从而可分别操作页面的不同部分。在触摸屏幕上的元素时,事件发生的顺序如下: touchstart、mouseover、mousemove、mousedown、mouseup、click、touchend。
支持触摸事件的浏览器包括iOS版Safari、Android版WebKit、beta版Dolfin、OS6+中的BlackBerry WebKit、Opera Mobile 10.1和LG专有OS中的phantom浏览器。目前仅IOS版Safari支持多点触屏。桌面版Firefox 6+和Chrome也支持触摸事件。
2.手势事件
IOS 2.0中的Safari还引入了一组手势事件。当两个手指触摸屏幕时产生手势,通常会改变显示项的大小或旋转显示项。有三个手势事件,分别如下: gesturestart:当一个手指已按在屏幕上面,另一个手指触摸屏幕时触发。 gesturechange:当触摸屏幕的任何一个手指位置发生变化时触发。 gestureend:当任何一个手指从屏幕上面移开时触发。
只有两个手指都触摸到事件的接收容器时才会触发这些事件。在一个元素上设置事件处理程序,意味着两个手指必须同时位于该元素范围内才能触发手势事件(该元素即为目标)。由于这些事件冒泡,将事件处理程序放在文档上也可处理所有手势事件,此时事件的目标即为两个手指都位于其范围内的元素。
触摸事件和手势事件之间存在某种关系。当一个手指放在屏幕上时,触发touchstart事件。如果另一个手指又放在屏幕上,则会先触发gesturestart事件,随后触发基于该手指的touchstart事件。如果一个或两个手指在屏幕上滑动,将触发gesturechange事件;但只要有一个手指移开,就会触发gestureend事件,紧接着又会触发基于该手指的touchend事件。
与触摸事件一样,每个手势事件的event对象都包含标准鼠标事件属性:bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey和metaKey。此外,还包含两个额外属性:rotation和scale。其中,rotation属性表示手指变化引起的旋转角度,负值表示逆时针旋转,正值表示顺时针旋转(该值从0开始)。scale属性表示两个手指间距的变化情况(例如向内收缩会缩短距离);该值从1开始,随距离拉大而增长,随距离缩减而减小。
下面是使用手势事件的一个示例:
function handleGestureEvent(event) {
var output = document.getElementById("output");
switch(event.type) {
case "gesturestart":
output.innerHTML = "Gesture started (rotation=" + event.ratation +",scale=" + event.scale + ")";
break;
case "gestureend":
output.innerHTML += "<br>Gesture ended (rotation+" + event.rotation + ",scale=" + event.scale + ")";
break;
case "gesturechange":
output.innerHTML += "<br>Gesture changed (rotation+=" + event.rotation + ",scale+" + event.scale + ")";
break;
}
}
document.addEventListener("gesturestart", handleGestureEvent, false);
document.addEventListener("gestureend", handleGestureEvent, false);
document.addEventListener("gesturechange", handleGestureEvent, false);
与前面演示触摸事件的例子一样,这里的代码只是将每个事件都关联到同一个函数中,然后通过该函数输出每个事件的相关信息。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。