在本章中,我们将更详细地了解鼠标事件及其属性。
请注意:此类事件可能不仅来自“鼠标设备”,还来自其他设备,例如手机和平板电脑,在这些设备中,此类事件被模拟以实现兼容性。
鼠标事件类型
我们已经看到了一些这些事件
mousedown/mouseup
- 鼠标按钮在某个元素上单击/释放。
mouseover/mouseout
- 鼠标指针进入/离开某个元素。
mousemove
- 每次鼠标在某个元素上移动都会触发该事件。
click
- 如果使用的是鼠标左键,则在同一个元素上触发
mousedown
然后触发mouseup
之后触发。 dblclick
- 在短时间内在同一个元素上单击两次后触发。现在很少使用。
contextmenu
- 在按下鼠标右键时触发。还有其他打开上下文菜单的方法,例如使用特殊键盘键,在这种情况下它也会触发,因此它不完全是鼠标事件。
…还有其他几个事件,我们稍后会介绍。
事件顺序
正如您从上面的列表中看到的,用户操作可能会触发多个事件。
例如,左键单击首先触发 mousedown
(在按下按钮时),然后在释放按钮时触发 mouseup
和 click
。
当单个操作启动多个事件时,它们的顺序是固定的。也就是说,按 mousedown
→ mouseup
→ click
的顺序调用处理程序。
单击下面的按钮,您将看到这些事件。也可以尝试双击。
在下面的测试台上,所有鼠标事件都会被记录,如果它们之间有超过 1 秒的延迟,则它们将由水平规则分隔。
此外,我们可以看到 button
属性,它允许我们检测鼠标按钮;如下所述。
鼠标按钮
与单击相关的事件始终具有 button
属性,该属性允许获取确切的鼠标按钮。
我们通常不将其用于 click
和 contextmenu
事件,因为前者仅在左键单击时发生,而后者仅在右键单击时发生。
另一方面,mousedown
和 mouseup
处理程序可能需要 event.button
,因为这些事件会在任何按钮上触发,因此 button
允许区分“右键按下”和“左键按下”。
event.button
的可能值为
按钮状态 | event.button |
---|---|
左键(主按钮) | 0 |
中键(辅助按钮) | 1 |
右键(次按钮) | 2 |
X1 按钮(后退) | 3 |
X2 按钮(前进) | 4 |
大多数鼠标设备只有左右按键,因此可能的值是0
或2
。触控设备在用户点击时也会生成类似的事件。
此外,还有event.buttons
属性,它以整数形式包含当前按下的所有按键,每个按键一位。实际上,此属性很少使用,如果需要,可以在MDN中找到详细信息。
event.which
旧代码可能使用event.which
属性,这是获取按钮的旧式非标准方法,可能的值有
event.which == 1
– 左键,event.which == 2
– 中键,event.which == 3
– 右键。
目前,event.which
已弃用,我们不应使用它。
修饰键:shift、alt、ctrl 和 meta
所有鼠标事件都包含有关按下的修饰键的信息。
事件属性
shiftKey
: ShiftaltKey
: Alt(或 Mac 上的Opt)ctrlKey
: CtrlmetaKey
: Mac 上的Cmd
如果在事件期间按下了相应的键,则它们为true
。
例如,下面的按钮仅在Alt+Shift+单击时才有效
<button id="button">Alt+Shift+Click on me!</button>
<script>
button.onclick = function(event) {
if (event.altKey && event.shiftKey) {
alert('Hooray!');
}
};
</script>
Cmd
代替Ctrl
在 Windows 和 Linux 上,有修饰键Alt、Shift和Ctrl。在 Mac 上,还有一个:Cmd,对应于属性metaKey
。
在大多数应用程序中,当 Windows/Linux 使用Ctrl时,Mac 上使用Cmd。
也就是说:Windows 用户按Ctrl+Enter或Ctrl+A时,Mac 用户将按Cmd+Enter或Cmd+A,依此类推。
因此,如果我们想支持Ctrl+单击之类的组合,那么对于 Mac,使用Cmd+单击是有意义的。这对于 Mac 用户来说更方便。
即使我们想强制 Mac 用户Ctrl+单击——这有点困难。问题是:在 macOS 上,使用Ctrl进行左键单击会被解释为右键单击,它会生成contextmenu
事件,而不是像 Windows/Linux 那样的click
。
因此,如果我们希望所有操作系统的用户都能感到舒适,那么除了ctrlKey
之外,我们还应该检查metaKey
。
对于 JS 代码,这意味着我们应该检查if (event.ctrlKey || event.metaKey)
。
键盘组合作为工作流的补充是好的。因此,如果访问者使用键盘,它们将起作用。
但是,如果他们的设备没有键盘,那么应该有一种方法可以在没有修饰键的情况下使用。
坐标:clientX/Y、pageX/Y
所有鼠标事件都以两种方式提供坐标
- 相对于窗口:
clientX
和clientY
。 - 相对于文档:
pageX
和pageY
。
我们已经在 坐标 章节中介绍了它们之间的区别。
简而言之,相对于文档的坐标 pageX/Y
从文档的左上角开始计算,并且在页面滚动时不会改变,而 clientX/Y
从当前窗口的左上角开始计算。当页面滚动时,它们会改变。
例如,如果我们有一个大小为 500x500 的窗口,并且鼠标位于左上角,那么无论页面如何滚动,clientX
和 clientY
都是 0
。
如果鼠标位于中心,那么无论鼠标在文档中的什么位置,clientX
和 clientY
都是 250
。它们在这一点上类似于 position:fixed
。
将鼠标移到输入字段上以查看 clientX/clientY
(示例在 iframe
中,因此坐标相对于该 iframe
)
<input onmousemove="this.value=event.clientX+':'+event.clientY" value="Mouse over me">
防止在 mousedown 时进行选择
双击鼠标有一个副作用,在某些界面中可能会令人不安:它会选择文本。
例如,双击以下文本会将其选中,除了我们的处理程序之外
<span ondblclick="alert('dblclick')">Double-click me</span>
如果按下鼠标左键,并且在不释放的情况下移动鼠标,也会进行选择,这通常是不需要的。
有多种方法可以防止选择,您可以在 选择和范围 章节中阅读。
在这种特殊情况下,最合理的方法是在 mousedown
上防止浏览器操作。它可以防止这两种选择
Before...
<b ondblclick="alert('Click!')" onmousedown="return false">
Double-click me
</b>
...After
现在,加粗元素不会在双击时被选中,并且按其上的左键不会开始选择。
请注意:其中的文本仍然可以选择。但是,选择不应该从文本本身开始,而应该在文本之前或之后开始。通常这对用户来说很好。
如果我们想禁用选择以保护我们的页面内容不被复制粘贴,那么我们可以使用另一个事件:oncopy
。
<div oncopy="alert('Copying forbidden!');return false">
Dear user,
The copying is forbidden for you.
If you know JS or HTML, then you can get everything from the page source though.
</div>
如果您尝试复制 <div>
中的一段文本,那将不起作用,因为默认操作 oncopy
已被阻止。
当然,用户可以访问页面的 HTML 源代码,并从中获取内容,但不是每个人都知道如何操作。
摘要
鼠标事件具有以下属性
-
按钮:
button
。 -
修饰键(如果按下则为
true
):altKey
、ctrlKey
、shiftKey
和metaKey
(Mac)。- 如果你想处理 Ctrl,那么不要忘记 Mac 用户,他们通常使用 Cmd,因此最好检查
if (e.metaKey || e.ctrlKey)
。
- 如果你想处理 Ctrl,那么不要忘记 Mac 用户,他们通常使用 Cmd,因此最好检查
-
窗口相对坐标:
clientX/clientY
。 -
文档相对坐标:
pageX/pageY
。
mousedown
的默认浏览器操作是文本选择,如果它对界面不好,则应该阻止它。
在下一章中,我们将看到有关指针移动后事件的更多详细信息,以及如何跟踪其下的元素更改。
评论
<code>
标记,对于多行 - 将它们包装在<pre>
标记中,对于超过 10 行 - 使用沙箱(plnkr、jsbin、codepen…)