鼠标与滚轮事件

鼠标事件是web开发中最常用的一类事件,毕竟鼠标是最主要的定位设备

DOM3级事件中定义了9个鼠标事件:

  1. click:在用户单击主鼠标按钮(一般为鼠标左键)或者按下回车时触发,这一点对确保易访问性十分重要,这意味着 onclick 事件处理程序既可以通过键盘执行也可以通过鼠标执行
  2. dbclick:在用户双击主鼠标按钮时触发(鼠标左键)。从技术上说该事件并不是DOM2级规范所支持的,但是由于浏览器对其的广泛实现在DOM3级规范中将其纳入标准
  3. mousedown:用户按下任意鼠标按钮触发,不能通过键盘触发
  4. mouseenter:鼠标光标从元素外部移入元素内部时触发,该事件不冒泡,并且在光标从元素移入元素子元素时不会触发
  5. mouseleave:光标从元素上方移出元素范围时触发,该事件不冒泡,移入后代元素不会触发
  6. mousemove:鼠标指针在元素内部移动时重复触发,不能通过键盘触发该事件
  7. mouseout:鼠标位于元素上方,此时将鼠标移至另一个元素触发,其子元素也会触发,不能通过键盘触发该事件
  8. mouseover:鼠标位于元素外部,首次移入元素范围内触发,其子元素也会触发,不能通过键盘触发该事件
  9. mouseup:用户释放鼠标按钮时触发,不能通过键盘触发

需要注意的是,页面上所有元素都支持鼠标事件。除了mouseenter和mouseleave事件,其余的鼠标事件都会冒泡,也可以被取消,取消鼠标事件会影响浏览器的默认行为

只有在同一个元素上相继触发 mousedown 和 mouseup 事件才会触发click 事件,若两者中有一者被取消,那么就不会触发click事件。

类似地,只有触发两次 click 事件才会触发一次dbclick事件(并且两次地间隔在一定时间范围内),若中途被代码取消则不会触发该事件

以上四个事件的触发顺序如下:

  1. mousedown
  2. mouseup
  3. click
  4. mousedown
  5. mouseup
  6. click
  7. dbclick

显然 click、dbclick都依赖于其它先行事件的触发,而 mousedown 和 mouseup则不受其它事件的影响

检测浏览器是否支持以上事件可使用以下代码:

var isSupported = document.implementation.hasFeature("MouseEvent","3.0");

鼠标事件中还有一类滚轮事件,说是一类事件实际上就是 mousewheel 事件。该事件跟踪鼠标滚轮,以及Mac的触控面板等相似设备

客户区坐标位置

鼠标事件都是在浏览器视口的特定位置发生的

该位置信息保存在鼠标事件对象的 clientX 和 clientY 属性中

他们的值分别表示事件触发时鼠标指针在浏览器窗口中的水平坐标和垂直坐标

注意该坐标不包括浏览的的工具栏等,也就是说该坐标是浏览器可视窗口内部的坐标(相对于浏览器窗口而非文档,也就是并不表示该元素在页面中的位置)

如:

var div = document.getElementByTagName("div")[0];
div.onclick = function(event){// 此处没有对 event 对象进行兼容处理,详见之前的文章
alert("Client coordinates:"+ event.clientX +","+event.clientY);
}

页面坐标位置

通过客户区坐标可以知道鼠标事件在视口中的发生位置

而页面坐标的信息则保存在 事件对象的 pageX 和 pageY 属性中

该属性可以告知我们是事件是在页面中的什么位置发生的

因此该属性是以页面本身的左边和顶边作为参照计算的

var div = document.getElementByTagName("div")[0];
div.onclick = function(event){// 此处没有对 event 对象进行兼容处理,详见之前的文章
alert("Client coordinates:"+ event.pageX +","+event.pageY);
}

在页面没有经过滚动的情况下,页面坐标和客户区坐标是相等的

IE8及更低版本的IE不支持事件对象上的页面坐标的属性

不过我们可以通过计算的方式来获取

代码如下:

var div = document.getElementByTagName("div")[0];
div.onclick = function(event){// 此处没有对 event 对象进行兼容处理,详见之前的文章
var pageX = event.pageX;
var pageY = event.pageY;
if(pageX === undefined){
pageX = event.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft);
}
if(pageY===undefined){
pageY = event.clientY + (document.body.scrollTop || document.documentElement.scrollTop);
}
alert("Page coordinates:"+pageX+","+pageY);
}

屏幕坐标位置

鼠标事件发生时,不仅会有相对于浏览器窗口的位置,还有一个相对于整个电脑屏幕的位置

而相对于电脑屏幕的位置信息保存在事件对象的 screenX 和 screenY 属性上

代码如下:

var div = document.getElementByTagName("div")[0];
div.onclick = function(event){// 此处没有对 event 对象进行兼容处理,详见之前的文章
alert("Screen coordinates:"+ event.screenX+","+event.screenY);
}

修改键

虽然鼠标事件主要是由鼠标来触发的,但在按下鼠标时键盘上某些键的状态也可以影响到索要采取的操作

这些键为:

  • shift
  • ctrl
  • alt
  • Meta(windows是win键苹果是CMD键)

他们经常被用于修改鼠标事件的行为

DOM为此规定了四个属性,用于表示这些修改键的状态

  1. shiftKey
  2. ctrlKey
  3. altKey
  4. metaKey

这四个属性都保存着布尔值,以表示鼠标事件触发时这些修改键的状态(true 表示按下 false 表示没有按下)

通过检测这些事件属性,我们可以更加灵活地使用鼠标事件

相关元素

在发生 mouseover 和 mouseout 事件时,除了触发元素外还会涉及更多元素

因为这两个事件都涉及从一个元素的边界之内移入另一个元素的边界之内

对mouseover 事件而言事件的主目标是 获得光标的元素 而相关元素就是那个失去光标的元素

类似的,对于mouseout 事件而言 失去光标的是主目标,而相关元素则是获得光标的元素

DOM 通过 event 对象的 relatedTarget 属性提供相关元素的信息

该属性只对 mouseout 和 mouseover 事件存在,其它事件该属性的值为 null

IE8以下不支持该属性但提供了类似的实现

兼容处理如下:

function eventFunction(e){
var events;
if(e.relatedTarget){
events.relatedTarget = e.relatedTarget;
}else if(e.toElement){
events.relatedTarget = e.toElement;
}else if(e.fromElement){
events.relatedTarget = e.fromElement;
}else{
events.relatedTarget = null;
}// 相关元素兼容
}

鼠标按钮

只有在主鼠标按钮被单击的时候才会触发click

因此检测按钮的信息不是必要的

但是对于 mousedown 和 mouseup 事件来说用户点击的是鼠标的哪一个按钮是一个比较重要的信息

所以 在其 event 对象存在一个 button 属性,表示按下或者释放的按钮

DOM中的 button 属性可能有以下3个值:

  1. 0 表示主鼠标按钮
  2. 1 表示中间鼠标按钮
  3. 2 表示次鼠标按钮

在常规设置中,主鼠标按钮一般是指鼠标左键 中鼠标按钮指鼠标滚轮,次鼠标按钮则指的是鼠标右键

需要注意的是在低版本IE中的button与DOM标准中的 button 属性存在很大差异:

  • 0:没有按下按钮
  • 1:按下鼠标主按钮
  • 2:按下鼠标次按钮
  • 3:同时按下主次按钮
  • 4:按下鼠标中键按钮
  • 5:同时按下主按钮和中间按钮
  • 6:同时按下中间按钮和次按钮
  • 7:同时按下三个按钮

两者差异的兼容可通过以下代码实现:

function getButton(event){
if(document.implementation.hasFeature("MouseEvents","2.0")){
return event.button;
}else{
switch(event.button){
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 2:
case 6:
return 2;
case 4:
return 1;
}
}
}

更多事件信息

”DOM2级事件“规范在 event 对象中还提供了 detail 属性,用于给出有关事件的更多信息

对于鼠标事件来说,detail 包含了一个数值,表示在给定位置上发生了多少次单击

在同一个元素上相继发生一次mousedown 和 mouseup 算作发生一次单击

detail属性从1开始计数,每次单击发生后都会递增,若在mousedown和mouseup之间鼠标移动了位置则 detail 会被重置为0

鼠标滚轮事件

鼠标滚轮事件由IE6.0首先实现,此后其它浏览器也相继实现了该事件

与 mousewheel 事件对应的 event 对象除了包含鼠标事件的所有标准信息之外还包含一个特殊的 wheelDelta 属性

当用户向前(远离自己)的方向滚动滚轮时该值是120的倍数

当用户向后(靠近自己)的方向滚动滚轮时该值是-120的倍数

需要注意的是在 opera 9.5版本之前,正负号是反的

除了 opera 之外作妖的还有火狐

火狐支持一个名为 DOMMouseScroll 的类似事件,该事件也在鼠标滚轮滚动时触发

与DOM不同的地方在于,该事件的 wheelDelta的相关对应信息保存在 detail 属性中

向前滚动时该值是-3的倍数

向后滚动时是3的倍数

该事件会冒泡到window

对于滚轮事件的跨浏览器粗略实现如下:

function getWheelDelta(e){
var clients = getClient();//该方法用于获取浏览器的特性信息,详见之前的文章 https://www.cnblogs.com/lhyxq/p/10227375.html
if(e.wheelDelta){
events.wheelDelta = (clients.engine.opera && clients.engine.opera < 9.5 ? -e.wheelDelta:e.wheelDelta)
}else{
return -e.detail * 40;
}// 滚轮事件兼容
}

触摸设备

IOS和Android设备实现非常特别,因为这些设备没有鼠标

需要注意以下几点:

  • 不支持dbclick,双击会放大画面且无法修改该行为
  • 轻击可单击元素会触发mousemove事件,该操作导致内容变化则不再发生其它事件,若没有变化则会依次发生 mousedown mouseup click 事件
  • mousemove 会触发 mouseover 和 mouseout
  • 两个手指放在屏幕上滑动页面会mousewheel事件

无障碍问题

若web应用需要确保残疾人或者使用屏幕阅读器的人能够访问,使用鼠标事件就需要特别小心

因此不建议使用 click 之外的其他鼠标事件来展示功能或者引发代码执行

需注意以下三点:

  1. 不要为了加快速度而使用mousedown事件代替 click 事件,因为在屏幕阅读器无法触发该事件
  2. 不要使用 mouseover 向用户展示新选项,原因同上,无法触发
  3. 不要使用 dbclick 执行重要操作,因为键盘无法触发该事件

以上可以提升web应用对残疾人的易访问性

Javascript高级编程学习笔记(63)—— 事件(7)鼠标及滚轮事件的更多相关文章

  1. Javascript高级编程学习笔记(57)—— 事件(1)事件流

    事件 JS与HTML的交互是通过事件实现的 而事件指的就是:文档或浏览器窗口特定的交互瞬间 可以通过侦听器来预定事件,以便在事件发生时执行相应的代码 这种模式也是设计模式中的观察者模式 事件流 有了事 ...

  2. Javascript高级编程学习笔记(72)—— 模拟事件(2)IE事件模拟

    IE中的事件模拟 低版本的IE浏览器作为前端开发的一股清流,想避过都不行 虽然低版本IE正在逐步被市场淘汰,不得不承认IE8以下的浏览器依然占了不小的份额 所以这里大概介绍IE8以下的低版本IE中的事 ...

  3. Javascript高级编程学习笔记(71)—— 模拟事件(1)DOM事件模拟

    事件,指的是网页中某个特定的交互时刻 一般来说事件由浏览器厂商负责提供,一般由用户操作或者其它浏览器功能来触发 但是有一类特殊的事件,那就是由我们开发人员通过JS触发的事件 这些事件和浏览器创建的事件 ...

  4. Javascript高级编程学习笔记(70)—— 事件(14)内存和性能

    由于事件处理程序是现代的web程序交互能力的提供者 所以在日常实践中,我们免不了要向页面中添加大量的事件处理程序(不管是用于用户交互还是用于统计用户数据) 在创建GUI(图形用户界面)的语言(如C#) ...

  5. Javascript高级编程学习笔记(69)—— 事件(13)触摸与手势事件

    触摸与手势事件 由于移动设备既没有鼠标也没有键盘,所以在为移动浏览器开发交互性网页时,常规的鼠标键盘事件根本不够用 所以早期的苹果为Safari 添加了一些与触摸相关的事件 随着后面Android的W ...

  6. Javascript高级编程学习笔记(67)—— 事件(11)HTML5事件

    DOM规范没有涵盖所有浏览器支持的所有事件 而许多浏览器出于满足用户需求,或解决特殊问题的目的,实现了一些自定义事件 HTML5列出了浏览器应该支持的所有事件,这里只讨论得到浏览器完善支持的事件(并非 ...

  7. Javascript高级编程学习笔记(66)—— 事件(10)变动事件

    变动事件 DOM2级的变动事件,能在DOM中的一部分发生变化时给出提示 变动事件是为XML或HTML DOM 设计的,并不特定于某种语言 DOM2级定义了如下变动事件: DOMSubtreeModif ...

  8. Javascript高级编程学习笔记(64)—— 事件(8)键盘与文本事件

    键盘与文本事件 用户在使用键盘时会触发键盘事件 “DOM2级事件”最初规定了键盘事件,但是最后在定稿时又删除了相应内容 所以键盘事件被放入了DOM3级事件的规范中 总的来说有三个键盘事件: keydo ...

  9. Javascript高级编程学习笔记(61)—— 事件(5)UI事件

    UI事件 UI事件是指那些不一定与用户操作有关的事件 这些事件在DOM规范出现之前,都是以各种不同的形式存在于不同的浏览器 而在DOM事件中为了保证向后兼容,现有的UI事件如下: DOMActivat ...

随机推荐

  1. Unity3D-RayMarch-几何图元-3添加阴影

    效果图: 在RayMarch渲染算法中计算阴影非常简单,当射线碰撞到物体,从碰撞点逆着光源方向再次执行射线步进算法,如果这一过程中碰撞到了其他物体,则碰撞点被其他物体遮挡,该处具有阴影. shader ...

  2. 输入ip和端口号python脚本py文件

    1.利用.py文件进行打开URL,编辑以下文件代码保存文件为login.py: # _*_ coding: cp936 _*__all_ = ['ip','port','root_id']ip='10 ...

  3. centos 7 安装vscode

    网上很多写的安装,会遇到一个问题,就是无法启动: sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc sudo sh ...

  4. HDU1060

    #include <bits/stdc++.h> using namespace std; int main() { int n; long long x; double t,ans; c ...

  5. HTML5学习路线导航

    一.基本标签元素 1.基础标签第一篇 2.基础标签第二篇 3.表单form的使用 4.新增表单验证 二.CSS样式表 4.CSS插入样式表的三种格式 5.六大选择器 6.样式内容详细讲解 7.背景渐进 ...

  6. vue项目运行

    共分为以下六步: 1.安装node.js2.安装cnpm3.安装vue-cli脚手架构建工具4.用vue-cli构建项目5.安装项目所需的依赖6.运行项目 第1步:从node.js官网下载node.j ...

  7. 搭建一个webpack微服务器

    [前言]:因为最近在vue2.0的时候用到了webpack的externals,才发现我之前都只是用webpack做一些搭建完项目后的“收尾工作”——即打包,而没有把它纳入到项目开发的“主体过程”中来 ...

  8. JSP·随笔

    1.简介 > HTML          - HTML擅长显示一个静态的网页,但是不能调用Java程序.       > Servlet   - Servlet擅长调用Java程序和后台进 ...

  9. jenkins 使用Git 报错:SSL certificate problem: self signed certificate in certificate chain

    在启动java的脚本上执行 增加参数: -Dorg.jenkinsci.plugins.gitclient.GitClient.untrustedSSL=true 即可!!

  10. Python Flask学习笔记之Hello World

    Python Flask学习笔记之Hello World 安装virtualenv,配置Flask开发环境 virtualenv 虚拟环境是Python解释器的一个私有副本,在这个环境中可以安装私有包 ...