指向网络上的事物曾经是轻而易举的。你有一个鼠标,你来移动它 有时候,你会按下按钮,就这样所有不是 鼠标被模拟成一个鼠标,开发者也清楚该看什么。
不过,“简单”不一定代表“良好”。但随着时间的推移 重要的是,并非所有东西都是(或假装)鼠标: 压力感应笔和倾斜度感知笔,可实现超凡的创作自由度;你可以 因此您只需使用设备和手即可;嘿,为什么 不用超过一根手指?
我们推出过触摸事件 但它们是一个完全独立的 API 否则,您必须编写两个单独的事件模型, 支持鼠标和触摸。Chrome 55 附带更新的标准版 统一了这两种模型的工具:指针事件
“单一事件”模型
指针事件可统一 浏览器的指针输入模型,将触摸、钢笔和鼠标结合在一起 事件。例如:
document.addEventListener('pointermove',
ev => console.log('The pointer moved.'));
foo.addEventListener('pointerover',
ev => console.log('The pointer is now over foo.'));
下面列出了所有可用的事件 您需要比较熟悉的鼠标事件:
pointerover
|
指针已进入元素的边界框。
如果设备支持悬停操作,此测试会立即生效,
pointerdown 事件。
|
pointerenter
|
与 pointerover 类似,但不以消息气泡和标识名显示
后代以不同的方式显示。
规范详情。
|
pointerdown
|
指针已进入有效按钮状态,其中按钮处于未激活状态 按钮,具体取决于 输入设备。 |
pointermove
|
指针的位置发生了变化。 |
pointerup
|
指针已退出活动按钮状态。 |
pointercancel
|
发生了一些情况,这意味着指针不太可能发出任何 更多活动也就是说,您应该取消所有正在进行的操作 并将输入状态恢复到中立输入状态 |
pointerout
|
指针已离开元素或屏幕的边界框。此外,在
pointerup (如果设备不支持悬停)。
|
pointerleave
|
与 pointerout 类似,但不以消息气泡和标识名显示
后代以不同的方式显示。
规范详情。
|
gotpointercapture
|
元素收到了指针捕获。 |
lostpointercapture
|
正在捕获的指针已被 发布。 |
不同的输入类型
通常,利用指针事件,你能够以与输入无关的方式编写代码,
而无需为不同的输入设备注册单独的事件处理脚本。
当然,您仍然需要注意各输入类型之间的差异,例如,
悬停的概念适用如果您确实想要区分不同的输入设备类型,例如可以提供
针对不同输入使用单独的代码/功能 - 但您可以从
事件处理脚本内使用pointerType
PointerEvent
界面。例如,如果您为侧边抽屉式导航栏编写代码,
对 pointermove
事件具有以下逻辑:
switch(ev.pointerType) {
case 'mouse':
// Do nothing.
break;
case 'touch':
// Allow drag gesture.
break;
case 'pen':
// Also allow drag gesture.
break;
default:
// Getting an empty string means the browser doesn't know
// what device type it is. Let's assume mouse and do nothing.
break;
}
默认操作
在支持触控功能的浏览器中,某些手势用于滚动、缩放或刷新网页。
对于触摸事件,当这些默认事件发生时,
是否发生了操作,例如,当用户滚动时,系统仍会触发 touchmove
。
对于指针事件,每当触发滚动或缩放等默认操作时,
您会收到一个 pointercancel
事件,告知您浏览器
可以对指针进行控制例如:
document.addEventListener('pointercancel',
ev => console.log('Go home, the browser is in charge now.'));
内置速度:默认情况下,此模型可实现更好的效果。 相比触摸事件,您需要使用 被动事件监听器 以实现相同水平的响应速度。
您可以使用
touch-action
CSS 属性。将某个元素的设置为 none
会停用所有
浏览器定义的操作针对相应元素开始。但还有一些
用于更精细控制的其他值(例如 pan-x
),以允许
浏览器对沿 x 轴(而不是 y 轴)的移动做出反应。Chrome 55
支持以下值:
auto
|
默认;浏览器可以执行任何默认操作。 |
none
|
不允许浏览器执行任何默认操作。 |
pan-x
|
浏览器只能执行水平滚动默认操作。 |
pan-y
|
浏览器只能执行垂直滚动默认操作。 |
pan-left
|
浏览器只能执行水平滚动默认操作 并向左平移网页。 |
pan-right
|
浏览器只能执行水平滚动默认操作 并向右平移网页 |
pan-up
|
浏览器只能执行垂直滚动默认操作 并且仅向上平移网页 |
pan-down
|
浏览器只能执行垂直滚动默认操作 且仅向下平移网页 |
manipulation
|
浏览器只能执行滚动和缩放操作。 |
指针捕获
曾经花费令人沮丧的小时来调试损坏的 mouseup
事件,直到您意识到这是因为用户松开按钮
超出您的点击目标?不是?好吧,也许就只有我一个人。
然而,到目前为止,还没有一种很好的方法可以解决这个问题。没问题,
您可以在文档上设置 mouseup
处理程序,并在
来跟踪对象这不是最简洁的解决方案,
不过,尤其是在您构建网络组件并尽量确保一切正常时
隔离。
有了指针事件,我们给出了更好的解决方案:您可以捕获指针、
这样,在输入时一定会收到 pointerup
事件(或其他难以捉摸的事件),
朋友)。
const foo = document.querySelector('#foo');
foo.addEventListener('pointerdown', ev => {
console.log('Button down, capturing!');
// Every pointer has an ID, which you can read from the event.
foo.setPointerCapture(ev.pointerId);
});
foo.addEventListener('pointerup',
ev => console.log('Button up. Every time!'));
浏览器支持
在撰写本文时,Internet Explorer 11 支持指针事件, Microsoft Edge、Chrome 和 Opera;Firefox 部分支持。您可以 在 caniuse.com 上找到最新列表。
您可以使用指针事件 polyfill 来实现 填补差距。或者,在运行时检查浏览器支持 简单明了:
if (window.PointerEvent) {
// Yay, we can use pointer events!
} else {
// Back to mouse and touch events, I guess.
}
指针事件非常适合进行渐进式增强:
修改初始化方法以进行上述检查,添加指针事件
if
程序块中的处理脚本,并将鼠标/触摸事件处理脚本移动到
else
代码块。
快来试用一下吧,并将您的想法告诉我们!