事件名称 | 备注 |
---|---|
touchstart | 触点与触摸屏接触时触发 |
touchmove | 触点在触摸屏上移动时触发 |
touchend | 触点离开触摸屏时在该触点接触触摸屏时的元素上触发 |
touchcancel | fired when a touch point has been disrupted in an implementation-specific manner(如触点太多) |
Touch对象用于描述触点与触摸屏的一个接触点,具有以下属性:
clientX
: 触点相对于viewport的水平像素距离,不包含滚动条偏移clientY
: 触点相对于viewport的竖直像素距离,不包含滚动条偏移identifier
: 触点与触摸屏接触时赋予的唯一标识id,在该触点与触摸屏接触阶段id不变pageX
: 触点相对于viewport的水平像素距离,包含滚动条偏移pageY
: 触点相对于viewport的竖直像素距离,包含滚动条偏移screenX
: 触点相对于屏幕的水平像素距离screenY
: 触点相对于屏幕的竖直像素距离target
: 触点最初与触摸屏接触时的元素TouchEvent对象用描述touch事件,包含以下属性:
touches
: 所有与屏幕接触的触点changedTouches:
touchstart时包含刚与触摸屏接触的触点;
touchemove时包含上次事件后移动的触点;
touchend和
touchcancel`时包含离开触摸屏的触点targetTouches
: 触点接触时target为本元素的所有触点altKey
: 事件发生时alt键是否按下ctrlKey
: 事件发生时ctrl 键是否按下metaKey
: 事件发生时meta键是否按下shiftKey
: 事件发生时shift键是否按下touches, changedTouch, targetTouches在线demo
用户代理可能同时发送touch事件和鼠标事件。如果用户代理同时发送两种事件,touchstart
事件必须在所有鼠标事件之前发送。在touchstart
和touchmove
监听器中如果调用了preventDefault
方法,用户代理不应该再发送任何的鼠标事件。
如果用户代理将touch事件解析为鼠标事件,那它必须在touchend
位置按顺序发送mousemove
,mousedown
,mouseup
,click
事件。
在viewpoint设置中阻止缩放
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no">
document.body.addEventListener('touchmove', function (e) {
e.preventDefault();
}, false);
touch事件经常需要处理多个触点, 渲染时使用requestAnimationFrame分别处理每一个触点能提高用户体验.
var touches = [];
canvas.addEventListener('touchmove', function (e) {
touches = e.touches;
requestAnimationFrame(render);
}, false);
function render() {
if (touches.length) {
// do some work
touches.pop();
requestAnimationFrame(render);
}
}
event.touches
是所有与屏幕接触的触点.
<div id="d2">
<style>
#d2 .target {
display: inline-block;
padding: 20px;
background: #ddd;
border: 1px solid #000;
}
#d2 .fixed {
position: fixed;
}
</style>
<span class="target">手指touch, 然后移动, 元素将跟随</span>
<script>
var target = document.querySelector('#d2 .target');
target.addEventListener('touchmove', function (e) {
if (event.targetTouches.length == 1) {
e.preventDefault();
var touch = event.targetTouches[0];
target.style.left = (touch.pageX - 50) + 'px';
target.style.top = (touch.pageY - 50)+ 'px';
target.classList.add('fixed');
}
}, false);
</script>
</div>
需要监听touchmove
事件动态判断水平还是竖直滑动。
var touchStartClientX,
touchStartClientY;
document.addEventListener('touchstart', function (event) {
if (event.targetTouches.length > 1) {
return; // 忽略多个手指触摸
}
touchStartClientX = event.touches[0].clientX;
touchStartClientY = event.touches[0].clientY;
event.preventDefault();
}, false);
document.addEventListener('touchmove', function (event) {
event.preventDefault();
}, false);
document.addEventListener('touchend', function (event) {
if (event.targetTouches > 0) {
return; // 忽略多个触点
}
var touchEndClientX = event.touches[0].clientX,
touchEndClientY = event.touches[0].clientY;
var dx = touchEndClientX - touchStartClientX;
var absDx = Math.abs(dx);
var dy = touchEndClientY - touchStartClientY;
var absDy = Math.abs(dy);
// 如果移动距离大于10px,认为它是滑动
if (Math.max(absDx, absDy) > 10) {
var dir = absDx > absDy ? (dx > 0 ? 'left' : 'right') :
(dy > 0 ? 'down' : 'up');
}
}, false);
UC等很多Android浏览器只触发一次touchmove
, 解决方法是在touchstart
中调用preventDefault
解决..
这样会取消掉后续的click事件, 造成click链接失效, click监听器不执行等. 可以在touchstart事件监听器检查元素. 进行特殊检查
经与UC的开发讨论,得出如下结果~~
参考