一、事件对象event

1.1 preventdefault()和returnValue阻止默认事件

通知浏览器不要执行与事件关联的默认动作。

preventdefault()  支持Chrome等高级浏览器

returnValue     支持IE6、7、8

var box = document.getElementById('box');
var i = 0;
//鼠标在box盒子滚动时触发
box.onmousewheel = function(event){
var event = event || window.event;
//能力检测,阻止默认事件
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue = true;
}
this.innerHTML = '你在我身上滚动了!' + i++;
}

1.2 stopPropagation()和cancelBubble阻止事件继续传播

stopPropagation()    支持Chrome等高级浏览器

cancelBubble       支持IE6、7、8

var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
var box3 = document.getElementById('box3');
box1.onclick = function(){
alert('box1');
}
box2.onclick = function(event){
alert('box2');
//阻止事件继续传播,能力检测
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
}
box3.onclick = function(){
alert('box3');
}

二、BOM

浏览器对象模型(browser object  model)

2.1卷动事件

当窗口无论向上向下卷动的时候,比如键盘↓了,滚动鼠标滚轮,拖拽滚动条,都会触发这个事件。

window.onscroll=function(){

}

2.2窗口的宽度和高度

认识一个对象:

document.documentElement

就是页面document,想要得到窗口的宽度和高度,不是window对象,而是document对象,所以:

document.documentElement.clientWidth

document.documentElement.clientHeight

但是去掉页面DTD,或IE678浏览器中,把下面的语句当做浏览器窗口的宽度和高度

document.body.clientWidth

document.body.clientWidth

所以兼容语法:

document.documentElement.clientWidth || document.body.clientWidth;

document.documentElement.clientHeight || document.body.clientWidth;


2.3窗口的卷动值

兼容语法:

document.documentElement.scrollTop || document.body.scrollTop

兼容所有浏览器

document.documentElement.scrollTop

兼容不写DTD的情况下:

document.body.scrollTop


三、鼠标位置

当我们给某一个盒子添加鼠标事件监听时(click、mouseover、mouseenter、mouseout等事件),都一定会有以下四组值:

event.pageX         event.pageY

event.screenX       event.screenY

event.clientX       event.clientY

event.offsetX       event.offsetY

event.pageY    表示鼠标指针,到页面顶端的距离。IE6、7、8不兼容

event.screenY  表示鼠标指针,到屏幕顶端的距离

event.clientY  表示鼠标指针,到视口顶端的距离(视口就是当前可视窗口)

event.offsetY  表示鼠标指针,到盒子顶端的距离

规律:

1、当页面没有卷动的时候,pageY一定等价于clientY。或换句话说pageY等价于clientY+页面卷动的值scrollTop。

2、IE678不兼容pageX、pageY

3、offsetX/Y会被儿子影响。

offsetX/Y指的不是距离你监听的那个盒子左上角的距离,而是指的你现在鼠标指针所在位置到此时最内层盒子左上角的距离。


四、盒子位置

任何一个元素都有offsetParent属性,和offsetLeft、offsetTop属性


4.1计算盒子在页面中的净位置

现在我们就可以用offsetParent和offsetTop/Left计算一个元素的净位置了,是一个迭代的过程。

xiaoming的净位置:xiaoming.offsetTop + xiaoming.offsetParent的xiaoming.offsetParent.borderTop ...

由于IE8很特殊,所以我们迫切的需要知道浏览器是不是IE8。所以使用:

window.navigator.userAgent

来检测浏览器的版本。

 

var ie8 = window.navigator.userAgent.indexOf("MSIE 8.0") != -1;

下面的函数就是得到一个元素在页面上的总净位置:

function offset(o){
//初始值
var result = {
"top" : o.offsetTop,
"left" : o.offsetLeft
}
//判断浏览器是不是IE8
var isIE8 = window.navigator.userAgent.indexOf("MSIE 8.0") != -1;
//循环迭代,寻找父亲
while(o = o.offsetParent){
//计算后的边框的值
if(window.getComputedStyle){
var borderTop = parseInt(getComputedStyle(o)['border-top-width']);
var borderLeft = parseInt(getComputedStyle(o)['border-left-width']);
}else{
var borderTop = parseInt(o.currentStyle['borderTopWidth']);
var borderLeft = parseInt(o.currentStyle['borderLeftWidth']);
} //验证一下,万一borderTop是undefined或NaN,此时修正为0
if(isNaN(borderTop)){
borderTop = 0;
}
if(isNaN(borderLeft)){
borderLeft = 0;
}
//如果浏览器版本不是IE8那么就加上边框,如果是IE8就不需要加边框,抛出自己
!isIE8 && (result.top += borderTop);
!isIE8 && (result.left += borderLeft);
result.top += o.offsetTop;
result.left += o.offsetLeft;
}
return result;
}

4.2曲线救国得到鼠标在盒子中的位置

var box = document.getElementById("box");
var result = document.getElementById("result");
//监听父亲鼠标移动的时候,鼠标指针的offsetX值和offsetY值
box.onmousemove = function(event){
var event = event || window.event;
var x = event.pageX - getAllOffset(box).left;
var y = event.pageY - getAllOffset(box).top;
result.innerHTML = x + "," + y;
}

由于IE低版本不兼容pageX和pageY,所以用clientX/Y加上卷动值

var box = document.getElementById("box");
var result = document.getElementById("result");
//监听父亲鼠标移动的时候,鼠标指针的offsetX值和offsetY值
box.onmousemove = function(event){
var event = event || window.event;
//曲线救国!!!!得到窗口卷动的值
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
//鼠标的offsetX、offsetY等于视口的值,加上卷动值减去净位置。
var x = event.clientX + scrollTop - getAllOffset(box).left;
var y = event.clientY + scrollLeft - getAllOffset(box).top;
result.innerHTML = x + "," + y;
}

五、拖拽

5.1 在页面上拖拽

页面上的元素,能够被鼠标拖拽。整体思路:

① 当鼠标在img上按下去的时候,注册document的鼠标移动事件监听;反之,当鼠标在屏幕任何位置抬起的时候,剥夺document的鼠标移动事件监听。

② 为了让鼠标能够一直按住图片的同一个位置,所以要在mousedown的一瞬间记录误差(见下图)。

var img = document.getElementsByTagName('img')[0];
//鼠标指针在图片上按下的时候
img.onmousedown = function(event){
var event = event || window.event;
//记录误差,目的是当我按住baby的脑门子拖拽的时候,鼠标指针一直在脑门子上。
var dx = event.offsetX;
var dy = event.offsetY;
//注册新的事件
//在document上移动的时候,让img跟随鼠标
document.onmousemove = function(event){
var event = event || window.event;
//移动的时候top值等于当前的鼠标指针位置减去开始的时候的误差
var x = event.clientX - dx;
var y = event.clientY - dy; img.style.left = x + "px";
img.style.top = y + "px";
//这个return false可以解决IE8的内置事件
return false;
}
//这个return false可以解决IE8的内置事件
return false;
}
//鼠标指针在任何位置抬起的时候,删除document上的move监听
document.onmouseup = function(){
document.onmousemove = null;
}

5.2在容器中拖拽

图片在父级容器中拖拽的时候,不仅仅是给图片加了一个限制区域,图片的top、left参考点是父盒子左上角,鼠标指针的位置点就不一致。图片的top、left起点是A,而鼠标指针clinetX、Y参考点是B点。

大家参考点就不一样了。

方法:只要把它们的坐标统一就可以了,所以我们需要得到鼠标指针相对于盒子的坐标位置,此时需要使用曲线救国,因为offsetX/Y会被儿子影响。

var img = document.getElementsByTagName('img')[0];
var box = document.getElementById('box');
//得到盒子的净位置
var boxoft = offset(box).top;
var boxofl = offset(box).left;
console.log(boxoft,boxofl)
//鼠标指针在图片上按下的时候
img.onmousedown = function(event){
var event = event || window.event;
//记录误差,目的是让我按住baby的脑门拖拽的时候,鼠标指针一直在脑门上
var dx = event.offsetX;
var dy = event.offsetY;
//鼠标按下,然后执行鼠标移动时间,接着在document上移动,让img跟着移动
document.onmousemove = function(event){
var event = event || window.event;
//曲线救国!!!!得到窗口卷动的值
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft|| document.body.scrollLeft;
//鼠标的offsetX、offsetY等于视口的值,加上卷动值减去净位置
//移动的时候top值等价于鼠标指针位置减去开始按下的误差
var X = event.clientX + scrollLeft - boxofl - dx;
var Y = event.clientY + scrollTop- boxoft - dy;
console.log(X,Y)
//验收
if(X > 300){
X = 300;
}else if(X < 0){
X = 0;
}
if(Y > 300){
Y = 300;
}else if(Y < 0){
Y = 0;
}
img.style.left = X+'px';
img.style.top = Y+'px';
//这个return false可以解决浏览器内置事件
return false;
}
}
//在鼠标指针任何位置抬起的时候,移除document上的move事件监听
document.onmouseup = function(){
document.onmousemove = null;
}

5.3放大镜效果

和刚刚的拖拽不一样,鼠标指针不需要按下了,所以逻辑变得简单了。

放大镜的放大原理:不是真的放大,只是当左边小放大镜移动的时候,右边的大图按比例移动,形成放大的感觉。

比例问题:

小图盒子350宽高,放大镜175宽高

大图盒子400宽高,图片800宽高

这里暗含了两个1:2,比例一定要相同,如果比例不相同,放大镜放大感觉就不一样了,无法看全。


六、鼠标滚轮事件

页面中经常有鼠标滚轮事件,比如做一个内置有纵向滚动条的盒子

Chrome和IE各个版本浏览器都支持onmousewheel事件,表示鼠标滚轮滚动的时候触发,火狐不支持这个事件,它支持的是自己的DOMMouseScroll事件,我们不需要进行能力检测,因为所有的浏览器遇见别人添加监听的方法都不报错(静默)。

var box = document.getElementById('box');
//除了火狐浏览器之外,都支持以下这种监听滚轮事件
box.onmousewheel = mousewheel;
//火狐独有的,必须用DOM2级添加监听
box.addEventListener('DOMMouseScroll',mousewheel,true);
//事件处理函数
function mousewheel(){
alert('滚动了!!!');
}

鼠标滚轮事件的event对象有属性wheelDelta,火狐是detail属性,可以反映你的滚轮方向和力度

非火狐向上120(力度越大数字越大),火狐向上是-3

非火狐向下-120(力度越大数字越大),火狐向上是3

所以要进行兼容性处理,把它们的值统一为:1和-1

box.onmousewheel = mousewheel;
//火狐独有的,必须用DOM2级添加监听
box.addEventListener('DOMMouseScroll',mousewheel,true);
//事件处理函数
function mousewheel(event){
//进行方向的能力检测,由于火狐和大家不一样,用if分开判断
if(event.wheelDelta){
//非火狐
// if(event.wheelDelta > 0){
// var direction = 1;
// }else{
// var direction = -1;
// }
var direction = event.wheelDelta > 0 ? 1 : -1;
}else{
//火狐
// if(event.detail > 0){
// var direction = -1;
// }else{
// var direction = 1;
// }
var direction = event.detail > 0 ? -1 : 1;
}
console.log(direction)
}

上一篇文章DOM2级小测试的正确答案:EFGHIBCD

解释:

1、DOM0级只能添加到冒泡阶段

2、DOM0级事件同名的会覆盖

3、true表示捕获,false表示冒泡,先捕获,后冒泡

4、DOM2级的不会覆盖,先写的先执行

5、DOM2级最内层的不区分冒泡和捕获,谁先写谁执行,无论是DOM0还是DOM2。


前端笔记之JavaScript(十一)event&BOM&鼠标/盒子位置&拖拽/滚轮的更多相关文章

  1. (Demo分享)利用JavaScript(JS)实现一个九宫格拖拽功能

    利用JavaScript(JS)实现一个九宫格拖拽功能   Demo实现了对任意方格进行拖拽,可以交换位置,其中Demo-1利用了勾股定理判断距离! Demo-1整体思路: 1.首先div实现自由移动 ...

  2. 超强的纯 CSS 鼠标点击拖拽效果

    背景 鼠标拖拽元素移动,算是一个稍微有点点复杂的交互. 而在本文,我们就将打破常规,向大家介绍一种超强的仅仅使用纯 CSS 就能够实现的鼠标点击拖拽效果. 在之前的这篇文章中 -- 不可思议的纯 CS ...

  3. CSharpGL(21)用鼠标拾取、拖拽VBO图元内的点、线或本身

    CSharpGL(21)用鼠标拾取.拖拽VBO图元内的点.线或本身 效果图 以最常见的三角形网格(用GL_TRIANGLES方式进行渲染)为例. 在拾取模式为GeometryType.Point时,你 ...

  4. 前端笔记之JavaScript(十)深入JavaScript节点&DOM&事件

    一.DOM JavaScript语言核心.变量的定义.变量的类型.运算符.表达式.函数.if语句.for循环.算法等等.这些东西都属于语言核心,下次继续学习语言核心就是面向对象了.JavaScript ...

  5. 前端笔记之jQuery(下)事件&节点操作&净位置&拖拽&页面卷动值&遍历JSON

    一.监听事件大全 1.1 JavaScript事件 onblur 元素失去焦点 onchange 用户改变域的内容 onclick 鼠标点击某个对象 ondblclick 鼠标双击某个对象 onfoc ...

  6. HTML5深入学习之鼠标跟随,拖拽事件

    知识点(鼠标跟随): mousedown: 当用户用鼠标点击在某一元素上就会触发该事件 mouseover:  当鼠标指针在某一元素上移动就会触发改事件 下面这个例子的效果就是鼠标点击元素后,元素跟着 ...

  7. Javascript 事件对象进阶(二)拖拽的应用 - 登录框的拖拽

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  8. Javascript 事件对象进阶(一)拖拽的原理

    拖拽原理 鼠标和Div的相对距离不变 三大事件 把拖拽加到document上 拖拽简单点来说就是不停的更改物体到页面左边&顶部的距离! 那么如何计算出物体到页面左端的距离呢? 当鼠标按下的时候 ...

  9. JAVA鼠标屏幕绘制拖拽删除矩形

    import java.awt.Cursor; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; ...

随机推荐

  1. JavaOOP笔记

    http://note.youdao.com/noteshare?id=bbdc0b970721e40d327db983a2f96371

  2. Docker容器跨主机通信

    默认情况下Docker容器需要跨主机通信两个主机节点都需要在同一个网段下,这时只要两个Docker容器的宿主机能相互通信并且该容器使用net网络模式,改实现方式为网桥模式通信: 除此之外我们还可以通过 ...

  3. [LeetCode] Backspace String Compare 退格字符串比较

    Given two strings S and T, return if they are equal when both are typed into empty text editors. # m ...

  4. Best Cow Line---POJ 3617(贪心)

    FJ is about to take his N (1 ≤ N ≤ 2,000) cows to the annual"Farmer of the Year" competiti ...

  5. java简单的双色球摇号程序

    import java.util.HashSet; import java.util.Random; import java.util.Set; /** * LotteryClient * @auth ...

  6. js中的观察者模式

    什么事观察者模式: 这是一种创建松散耦合代码的技术.它定义对象间 一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.由主体和观察者组成,主体负责发布事件,同时观察者通过 ...

  7. 图片转web字体库,如何制作web字体库

    最近项目上用到了很多svg图,设计师经常频繁改版,苦不堪言,于是就想到了把图片转成字体库来使用. 使用图片的缺点: 1. 图片加载速度慢 2. 图片大小固定,无法调节 3. 当代码重构或者图片目录位置 ...

  8. 【RL-TCPnet网络教程】第17章 RL-TCPnet之UDP通信

    第17章      RL-TCPnet之UDP通信 本章节为大家讲解RL-TCPnet的UDP通信实现,学习本章节前,务必要优先学习第16章UDP用户数据报协议基础知识.有了这些基础知识之后,再搞本章 ...

  9. OSGi解决的问题

    osgi最明显的缺陷 bundle尽管可以为隔离的服务建立独立生命周期管理的热部署方式,以及明确的服务导出和导入依赖能力,但是其最终基于jvm,无法对bundle对应的服务实现计算资源的隔离,一个服务 ...

  10. Android单元测试之三:使用模拟框架模拟依赖

    Android单元测试之三:使用模拟框架模拟依赖 基本描述 如果是一些工具类方法的测试,如计算两数之和的方法,本地 JVM 虚拟机就能提供足够的运行环境,但如果要测试的单元依赖了 Android 框架 ...