26 【触摸事件和其它常见事件】
1.触摸操作概述
Section titled “1.触摸操作概述”浏览器的触摸 API 由三个部分组成。
- Touch:一个触摸点
- TouchList:多个触摸点的集合
- TouchEvent:触摸引发的事件实例
Touch接口的实例对象用来表示触摸点(一根手指或者一根触摸笔),包括位置、大小、形状、压力、目标元素等属性。有时,触摸动作由多个触摸点(多根手指)组成,多个触摸点的集合由TouchList接口的实例对象表示。TouchEvent接口的实例对象代表由触摸引发的事件,只有触摸屏才会引发这一类事件。
很多时候,触摸事件和鼠标事件同时触发,即使这个时候并没有用到鼠标。这是为了让那些只定义鼠标事件、没有定义触摸事件的代码,在触摸屏的情况下仍然能用。如果想避免这种情况,可以用event.preventDefault方法阻止发出鼠标事件。
2.Touch 接口
Section titled “2.Touch 接口”2.1 Touch 接口概述
Section titled “2.1 Touch 接口概述”Touch 接口代表单个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。
其中一些event事件属性
identifier:必需,类型为整数,表示触摸点的唯一 ID。target:必需,类型为元素节点,表示触摸点开始时所在的网页元素。clientX:可选,类型为数值,表示触摸点相对于浏览器窗口左上角的水平距离,默认为0。clientY:可选,类型为数值,表示触摸点相对于浏览器窗口左上角的垂直距离,默认为0。screenX:可选,类型为数值,表示触摸点相对于屏幕左上角的水平距离,默认为0。screenY:可选,类型为数值,表示触摸点相对于屏幕左上角的垂直距离,默认为0。pageX:可选,类型为数值,表示触摸点相对于网页左上角的水平位置(即包括页面的滚动距离),默认为0。pageY:可选,类型为数值,表示触摸点相对于网页左上角的垂直位置(即包括页面的滚动距离),默认为0。radiusX:可选,类型为数值,表示触摸点周围受到影响的椭圆范围的 X 轴半径,默认为0。radiusY:可选:类型为数值,表示触摸点周围受到影响的椭圆范围的 Y 轴半径,默认为0。rotationAngle:可选,类型为数值,表示触摸区域的椭圆的旋转角度,单位为度数,在0到90度之间,默认值为0。force:可选,类型为数值,范围在0到1之间,表示触摸压力。0代表没有压力,1代表硬件所能识别的最大压力,默认为0。
2.2 Touch 接口的实例属性
Section titled “2.2 Touch 接口的实例属性”(1)Touch.identifier
Touch.identifier属性返回一个整数,表示触摸点的唯一 ID。这个值在整个触摸过程保持不变,直到触摸事件结束。
(2)Touch.screenX,Touch.screenY,Touch.clientX,Touch.clientY,pageX,pageY
Touch.screenX属性和Touch.screenY属性,分别表示触摸点相对于屏幕左上角的横坐标和纵坐标,与页面是否滚动无关。
Touch.clientX属性和Touch.clientY属性,分别表示触摸点相对于浏览器视口左上角的横坐标和纵坐标,与页面是否滚动无关。
Touch.pageX属性和Touch.pageY属性,分别表示触摸点相对于当前页面左上角的横坐标和纵坐标,包含了页面滚动带来的位移。
(3)Touch.radiusX,Touch.radiusY,Touch.rotationAngle
Touch.radiusX属性和Touch.radiusY属性,分别返回触摸点周围受到影响的椭圆范围的 X 轴半径和 Y 轴半径,单位为像素。乘以 2 就可以得到触摸范围的宽度和高度。
Touch.rotationAngle属性表示触摸区域的椭圆的旋转角度,单位为度数,在0到90度之间。
上面这三个属性共同定义了用户与屏幕接触的区域,对于描述手指这一类非精确的触摸,很有帮助。指尖接触屏幕,触摸范围会形成一个椭圆,这三个属性就用来描述这个椭圆区域。
下面是一个示例。
(4)Touch.force
Touch.force属性返回一个0到1之间的数值,表示触摸压力。0代表没有压力,1代表硬件所能识别的最大压力。
(5)Touch.target
Touch.target属性返回一个元素节点,代表触摸发生时所在的那个元素节点。即使触摸点已经离开了这个节点,该属性依然不变。
3.触摸事件的种类
Section titled “3.触摸事件的种类”触摸引发的事件,有以下几种。可以通过TouchEvent.type属性,查看到底发生的是哪一种事件。
touchstart:用户开始触摸时触发,它的target属性返回发生触摸的元素节点。touchend:用户不再接触触摸屏时(或者移出屏幕边缘时)触发,它的target属性与touchstart事件一致的,就是开始触摸时所在的元素节点。它的changedTouches属性返回一个TouchList实例,包含所有不再触摸的触摸点(即Touch实例对象)。touchmove:用户移动触摸点时触发,它的target属性与touchstart事件一致。如果触摸的半径、角度、力度发生变化,也会触发该事件。touchcancel:触摸点取消时触发,比如在触摸区域跳出一个模态窗口(modal window)、触摸点离开了文档区域(进入浏览器菜单栏)、用户的触摸点太多,超过了支持的上限(自动取消早先的触摸点)。
下面是一个例子。
4.其他常见事件
Section titled “4.其他常见事件”4.1 资源事件
Section titled “4.1 资源事件”4.1.1 beforeunload 事件
Section titled “4.1.1 beforeunload 事件”beforeunload事件在窗口、文档、各种资源将要卸载前触发。它可以用来防止用户不小心卸载资源。
如果该事件对象的returnValue属性是一个非空字符串,那么浏览器就会弹出一个对话框,询问用户是否要卸载该资源。但是,用户指定的字符串可能无法显示,浏览器会展示预定义的字符串。如果用户点击“取消”按钮,资源就不会卸载。
上面代码中,用户如果关闭窗口,浏览器会弹出一个窗口,要求用户确认。
浏览器对这个事件的行为很不一致,有的浏览器调用event.preventDefault(),也会弹出对话框。IE 浏览器需要显式返回一个非空的字符串,才会弹出对话框。而且,大多数浏览器在对话框中不显示指定文本,只显示默认文本。因此,可以采用下面的写法,取得最大的兼容性。
注意,许多手机浏览器(比如 Safari)默认忽略这个事件,桌面浏览器也有办法忽略这个事件。所以,它可能根本不会生效,不能依赖它来阻止用户关闭浏览器窗口,最好不要使用这个事件。
另外,一旦使用了beforeunload事件,浏览器就不会缓存当前网页,使用“回退”按钮将重新向服务器请求网页。这是因为监听这个事件的目的,一般是为了网页状态,这时缓存页面的初始状态就没意义了。
4.1.2 unload 事件
Section titled “4.1.2 unload 事件”unload事件在窗口关闭或者document对象将要卸载时触发。它的触发顺序排在beforeunload、pagehide事件后面。
unload事件发生时,文档处于一个特殊状态。所有资源依然存在,但是对用户来说都不可见,UI 互动全部无效。这个事件是无法取消的,即使在监听函数里面抛出错误,也不能停止文档的卸载。
手机上,浏览器或系统可能会直接丢弃网页,这时该事件根本不会发生。而且跟beforeunload事件一样,一旦使用了unload事件,浏览器就不会缓存当前网页,理由同上。因此,任何情况下都不应该依赖这个事件,指定网页卸载时要执行的代码,可以考虑完全不使用这个事件。
该事件可以用pagehide代替。
4.1.3 load 事件,error 事件
Section titled “4.1.3 load 事件,error 事件”load事件在页面或某个资源加载成功时触发。注意,页面或资源从浏览器缓存加载,并不会触发load事件。
error事件是在页面或资源加载失败时触发。abort事件在用户取消加载时触发。
这三个事件实际上属于进度事件,不仅发生在document对象,还发生在各种外部资源上面。浏览网页就是一个加载各种资源的过程,图像(image)、样式表(style sheet)、脚本(script)、视频(video)、音频(audio)、Ajax请求(XMLHttpRequest)等等。这些资源和document对象、window对象、XMLHttpRequestUpload 对象,都会触发load事件和error事件。
最后,页面的load事件也可以用pageshow事件代替。
4.2 网页状态事件
Section titled “4.2 网页状态事件”4.2.1 DOMContentLoaded 事件
Section titled “4.2.1 DOMContentLoaded 事件”网页下载并解析完成以后,浏览器就会在document对象上触发 DOMContentLoaded 事件。这时,仅仅完成了网页的解析(整张页面的 DOM 生成了),所有外部资源(样式表、脚本、iframe 等等)可能还没有下载结束。也就是说,这个事件比load事件,发生时间早得多。
注意,网页的 JavaScript 脚本是同步执行的,脚本一旦发生堵塞,将推迟触发DOMContentLoaded事件。
4.2.2 readystatechange 事件
Section titled “4.2.2 readystatechange 事件”readystatechange事件当 Document 对象和 XMLHttpRequest 对象的readyState属性发生变化时触发。document.readyState有三个可能的值:loading(网页正在加载)、interactive(网页已经解析完成,但是外部资源仍然处在加载状态)和complete(网页和所有外部资源已经结束加载,load事件即将触发)。
这个事件可以看作DOMContentLoaded事件的另一种实现方法。
4.3 窗口事件
Section titled “4.3 窗口事件”4.3.1 scroll 事件
Section titled “4.3.1 scroll 事件”前面的鼠标事件已经介绍过
scroll事件在文档或文档元素滚动时触发,主要出现在用户拖动滚动条。
该事件会连续地大量触发,所以它的监听函数之中不应该有非常耗费计算的操作。
4.3.2 resize 事件
Section titled “4.3.2 resize 事件”resize事件在改变浏览器窗口大小时触发,主要发生在window对象上面。
该事件也会连续地大量触发,所以最好像上面的scroll事件一样,通过throttle函数控制事件触发频率。
4.3.3 fullscreenchange 事件,fullscreenerror 事件
Section titled “4.3.3 fullscreenchange 事件,fullscreenerror 事件”fullscreenchange事件在进入或退出全屏状态时触发,该事件发生在document对象上面。
fullscreenerror事件在浏览器无法切换到全屏状态时触发。
4.4 剪贴板事件
Section titled “4.4 剪贴板事件”以下三个事件属于剪贴板操作的相关事件。
cut:将选中的内容从文档中移除,加入剪贴板时触发。copy:进行复制动作时触发。paste:剪贴板内容粘贴到文档后触发。
举例来说,如果希望禁止输入框的粘贴事件,可以使用下面的代码。
上面的代码使得用户无法在<input>输入框里面粘贴内容。
cut、copy、paste这三个事件的事件对象都是ClipboardEvent接口的实例。ClipboardEvent有一个实例属性clipboardData,是一个 DataTransfer 对象,存放剪贴的数据。
上面的代码使得复制进入剪贴板的,都是开发者指定的数据,而不是用户想要拷贝的数据。
4.5 焦点事件
Section titled “4.5 焦点事件”焦点事件发生在元素节点和document对象上面,与获得或失去焦点相关。它主要包括以下四个事件。
focus:元素节点获得焦点后触发,该事件不会冒泡。blur:元素节点失去焦点后触发,该事件不会冒泡。focusin:元素节点将要获得焦点时触发,发生在focus事件之前。该事件会冒泡。focusout:元素节点将要失去焦点时触发,发生在blur事件之前。该事件会冒泡。
这四个事件的事件对象都继承了FocusEvent接口。FocusEvent实例具有以下属性。
FocusEvent.target:事件的目标节点。FocusEvent.relatedTarget:对于focusin事件,返回失去焦点的节点;对于focusout事件,返回将要接受焦点的节点;对于focus和blur事件,返回null。
由于focus和blur事件不会冒泡,只能在捕获阶段触发,所以addEventListener方法的第三个参数需要设为true。
上面代码针对表单的文本输入框,接受焦点时设置背景色,失去焦点时去除背景色。
鼠标的事件属性。
- onclick
- ondblclick
- onmousedown
- onmouseenter
- onmouseleave
- onmousemove
- onmouseout
- onmouseover
- onmouseup
- onwheel
键盘的事件属性。
- onkeydown
- onkeypress
- onkeyup
焦点的事件属性。
- onblur
- onfocus
表单的事件属性。
- oninput
- onchange
- onsubmit
- onreset
- oninvalid
- onselect
触摸的事件属性。
- ontouchcancel
- ontouchend
- ontouchmove
- ontouchstart