JavaScript焦点事件、鼠标事件和滚轮事件使用详解


Posted in Javascript onJanuary 15, 2016

焦点事件

一般利用这些事件与document.hasFocus()方法和document.activeElement属性配合。主要有:

blur:元素失去焦点,不会冒泡;
DOMFocusIn:同HTML事件focus,于DOM3遭废弃,选用focusin;
DOMFocusOut:同HTML事件blur,于DOM3遭废弃,选用focusout;
focus:元素获得焦点,不回冒泡;
focusin:获得焦点,与HTML事件focus等价,但会冒泡;
focusout:失去焦点,与HTML事件blur等价;
如:

window.onfocus = function () {
  console.log('focus'); //focus
  console.log(document.hasFocus()); //True
}
window.onblur = function () {
  console.log('blur'); //blur
  console.log(document.hasFocus()); //False
}

当焦点从页面中的一个元素转移到另一个元素会触发下面的事件:

focusout --> focusin --> blur --> DOMFocusOut --> focus --> DOMFocusIn

鼠标事件

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

click
dblclick
mousedown:用户按下任意鼠标按钮时触发,不能通过键盘触发这个事件;
mouseup:用户释放鼠标按钮时触发,不能通过键盘触发这个事件;
mousemove:不能通过键盘触发这个事件;
mouseenter:不冒泡,且光标移动到后代元素上不会触发;
mouseleave:不冒泡,且光标移动到后代元素上不会触发;
mouseover:光标移动到后代元素上会触发;
mouseout:光标移动到后代元素上会触发;

举例如下:

div.onmouseover = function() {
  console.log('mouseover'); //在子元素上会触发
}
div.onmouseout = function() {
  console.log('mouseout'); //在子元素上会触发
}
div.onmouseenter = function() {
  console.log('mouseenter'); //在子元素上不会触发
}
div.onmouseleave = function() {
  console.log('mouseleave'); //在子元素上不会触发
}

只有在同一个元素上相继除法mousedown和mouseup事件,才会触发click事件;只有触发两次click事件,才会触发依次dblclick事件。

顺序如下:

mousedown --> mouseup --> click --> mousedown --> mouseup --> click --> dblclick

IE8之前的版本中有一个bug,在双击事件中,会跳过第二个mousedown和click事件

滚轮事件

客户区坐标位置clientX和clientY属性

如:

window.onmousemove = function() {
    clickX = event.clientX;
    clickY = event.clientY;
    var div = document.createElement("img");
    div.src = "hhh.gif"
    div.style.position = "absolute";
    div.style.width = '100px';
    div.style.left = clickX + "px";
    div.style.top = clickY + "px";
    document.body.appendChild(div);
};

页面坐标位置pageX与pageY;

window.onclick = function() {
    clickX = event.pageX;
    clickY = event.pageY;
    var div = document.createElement("img");
    div.src = "ppp.png"
    div.style.position = "absolute";
    div.style.width = '100px';
    div.style.left = clickX + "px";
    div.style.top = clickY + "px";
    document.body.appendChild(div);
};

在IE8及更早版本中不支持这个页面坐标位置,可以计算出来,需要用到混合模式下的document.body和标准模式下的document.documentElement中的scrollLeft和scrollTop属性:

if (clickX === undefined) {
  clickX = event.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft);
};
if (clickY === undefined) {
  clickY = event.clientY + (document.body.scrollTop || document.documentElement.scrollTop);
};

屏幕坐标位置screenX和screenY;

通过该属性可以获得相对于屏幕的坐标。

修改键

修改键有Shift、Ctrl、Alt、Meta(window上的Windows键,苹果机上的Cmd键);对应的修改键的状态是shiftKey、ctrlKey、altKey、metaKey,这些属性包含的都是布尔值,如果相应的键被按下了,则为true,否则为false。如:

var array = [];
var timing = setTimeout(showArray, 100);

window.onclick = function() {
  if (event.shiftKey) {
    array.push("shift");
  };
  if (event.ctrlKey) {
    array.push("ctrl");
  };
  if (event.altKey) {
    array.push("alt");
  };
  if (event.metaKey) {
    array.push("meta");
  };
};

function showArray() {
  var str = array.toString();
  var newP = document.createElement("p");
  newP.appendChild(document.createTextNode(str));
  document.body.appendChild(newP);
  timing = setTimeout(showArray, 1000);
}

相关元素

event.relatedTarget与event.target;

relatedTarget属性提供了相关元素的信息。这个属性只对于mouseover和mouseout事件才包含值;对于其他事件的值则是null;IE8之前的版本不支持relatedTarget属性,在mouseover事件触发时,IE的fromElement属性中保存了相关元素;在mouseout事件触发时,IE的toElement属性中保存着相关元素。

如:

var dot = document.getElementById("dot");
dot.onmouseout = function (){
  console.log("mouse out from" + event.target.tagName + "to" + event.relatedTarget.tagName);
};

如:

function getRelatedTarget() {
  if (event.ralatedTarget) {
    return event.relatedTarget;
  } else if (event.toElement) {
    return event.toElement;
  } else if (event.fromElement) {
    return event.fromElement;
  } else {
    return null;
  }
}

鼠标按钮

button属性

DOM的event.button属性有三个值:0为主鼠标按钮、1为中间鼠标按钮、2为次鼠标按钮。在常规设置中,主鼠标按钮就是鼠标左键;次鼠标按钮就是鼠标右键。

IE8及之前的版本也提供了button属性,但这个属性的值与DOM的button属性有很大差异:

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

兼容版:

function getButton() {
  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;
    }
  }
}

另外,如果要屏蔽鼠标右键,应该使用:

document.oncontextmenu = function(event) {
  // if (window.event) {
  //   event = window.event;
  // }
  // try {
  //   var the = event.srcElement;
  //   if (!((the.tagName == "INPUT" && the.type.toLowerCase() == "text") || the.tagName == "TEXTAREA")) {
  //     return false;
  //   }
  //   return true;
  // } catch (e) {
  //   return false;
  // }
  return false;
}

这个事件是HTML5定义的,以后再讨论

更多的事件信息

detail属性

对于鼠标事件来说,detail包含了一个数值,表示在给定位置上发生了多少次单击(一次mousedown和一次mouseup),次数从1开始计数,如果mousedown和mouseup之间移动了位置,detail会被重置0,如果单击间隔太长也会被重置为0.

鼠标滚轮事件

mousewheel事件和wheelDelta属性

在垂直放向上滚动页面时,就会触发mousewheel,event对象里面的wheelDelta属性则表示当用户向前滚动滚轮时,wheelDelta是120的倍数;当向后滚动滚轮时,wheelDelta是-120的倍数。如:

var clientHeight = document.documentElement.clientHeight;
var divs = document.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++) {
  divs[i].style.height = clientHeight + "px";
};

window.onmousewheel = function () {
  if (event.wheelDelta <= -120) {
    window.scrollBy(0,clientHeight);
  }else if(event.wheelDelta >= 120){
    window.scrollBy(0,-clientHeight);
  };
}

另外,在Opera 9.5之前的版本中,wheelDelta值的正负号是颠倒的。

此外,Firefox支持一个名为DOMMouseScroll的类似事件,也是在鼠标滚动滚轮时除法。有关鼠标滚轮的信息保存在detail属性中。向前滚动这个属性的值为-3的倍数,向后滚动,这个属性的值是3的倍数。

通用版:

function getWheelDelta() {
  if (event.wheelDelta) {
    return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
  } else {
    return -event.detail * 40;
  };
}

触摸设备

iOS和Android设备中:

不支持dblclick;
轻击可单击元素会触发mousemove;如果此操作会导致内容变化,将不再有其他事件发声;如果屏幕没有发生变化,那么依次发生mousedown、mouseup和click事件;
mousemove事件也会触发mouseover和mouseout事件;
两个手指操作会触发mousewheel和scroll;

无障碍性问题

使用click事件执行代码;

不要使用onmouseover向用户显示新的信息;
不要使用dblclick执行重要的操作;

Javascript 相关文章推荐
分析 JavaScript 中令人困惑的变量赋值
Aug 13 Javascript
非常漂亮的JS代码经典广告
Oct 21 Javascript
javascript的parseFloat()方法精度问题探讨
Nov 26 Javascript
javascript获取浏览器类型和版本的方法(js获取浏览器版本)
Mar 13 Javascript
浅析Javascript中bind()方法的使用与实现
Apr 29 Javascript
BOM系列第二篇之定时器requestAnimationFrame
Aug 17 Javascript
JS 拦截全局ajax请求实例解析
Nov 29 Javascript
JS中的作用域链
Mar 01 Javascript
利用jqprint插件打印页面内容的实现方法
Jan 09 Javascript
jQuery使用ajax传递json对象到服务端及contentType的用法示例
Mar 12 jQuery
js实现飞机大战游戏
Aug 26 Javascript
JavaScript中isPrototypeOf函数
Nov 07 Javascript
JavaScript提高性能知识点汇总
Jan 15 #Javascript
学习JavaScript设计模式之中介者模式
Jan 14 #Javascript
轻松实现jquery手风琴效果
Jan 14 #Javascript
jQuery取得iframe中元素的常用方法详解
Jan 14 #Javascript
js实现prototype扩展的方法(字符串,日期,数组扩展)
Jan 14 #Javascript
分享网页检测摇一摇实例代码
Jan 14 #Javascript
jquery淡入淡出效果简单实例
Jan 14 #Javascript
You might like
如何将一个String和多个String值进行比较思路分析
2013/04/22 Javascript
JavaScript的漂亮的代码片段
2013/06/05 Javascript
ExtJS4利根据登录后不同的角色分配不同的树形菜单
2014/05/02 Javascript
Node.js实现批量去除BOM文件头
2014/12/20 Javascript
javascript中定义类的方法汇总
2014/12/28 Javascript
JavaScript实现图片轮播的方法
2015/07/31 Javascript
浅谈EasyUI常用控件的禁用方法
2016/11/09 Javascript
easy ui datagrid 从编辑框中获取值的方法
2017/02/22 Javascript
在Vue项目中使用jsencrypt.js对数据进行加密传输的方法
2019/04/17 Javascript
JS实现单张或多张图片持续无缝滚动的示例代码
2020/05/10 Javascript
vue-列表下详情的展开与折叠案例
2020/07/28 Javascript
vue使用video插件vue-video-player详解
2020/10/23 Javascript
几个提升Python运行效率的方法之间的对比
2015/04/03 Python
在Python中使用模块的教程
2015/04/27 Python
MAC中PyCharm设置python3解释器
2017/12/15 Python
用于业余项目的8个优秀Python库
2018/09/21 Python
使用11行Python代码盗取了室友的U盘内容
2018/10/23 Python
python的常用模块之collections模块详解
2018/12/06 Python
Pycharm 实现下一个文件引用另外一个文件的方法
2019/01/17 Python
Python 安装第三方库 pip install 安装慢安装不上的解决办法
2019/06/18 Python
PyCharm下载和安装详细步骤
2019/12/17 Python
python求最大公约数和最小公倍数的简单方法
2020/02/13 Python
pycharm软件实现设置自动保存操作
2020/06/08 Python
Python实例教程之检索输出月份日历表
2020/12/16 Python
详解win10下pytorch-gpu安装以及CUDA详细安装过程
2021/01/28 Python
thinkphp5 路由分发原理
2021/03/18 PHP
莫斯科绝对前卫最秘密的商店:SVMoscow
2017/10/23 全球购物
Stutterheim瑞典:瑞典高级外套时装品牌
2019/06/24 全球购物
怎样写留学自荐信
2013/11/11 职场文书
晚会邀请函范文
2014/01/24 职场文书
护理专科自荐书范文
2014/02/18 职场文书
综治维稳工作汇报
2014/10/27 职场文书
亚布力滑雪场导游词
2015/02/09 职场文书
办公室岗位职责范本
2015/04/11 职场文书
如何拟写通知正文?
2019/04/02 职场文书
idea编译器vue缩进报错问题场景分析
2021/07/04 Vue.js