文档章节

前端笔记之JavaScript(十一)event&BOM&鼠标/盒子位置&拖拽/滚轮

o
 osc_a22drz29
发布于 2019/03/29 19:49
字数 2416
阅读 7
收藏 0

精选30+云产品,助力企业轻松上云!>>>

一、事件对象event

1.1 preventdefault()returnValue阻止默认事件

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

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

returnValue     支持IE678

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       支持IE678

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

 


三、鼠标位置

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

 event.pageX         event.pageY

 event.screenX       event.screenY

 event.clientX       event.clientY

 event.offsetX       event.offsetY

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

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

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

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

规律:

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

2IE678不兼容pageXpageY

3offsetX/Y会被儿子影响。

 

 

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

 


四、盒子位置

任何一个元素都有offsetParent属性,和offsetLeftoffsetTop属性

 


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

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

xiaoming的净位置:xiaoming.offsetTop + xiaoming.offsetParentxiaoming.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低版本不兼容pageXpageY,所以用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在容器中拖拽

图片在父级容器中拖拽的时候,不仅仅是给图片加了一个限制区域,图片的topleft参考点是父盒子左上角,鼠标指针的位置点就不一致。图片的topleft起点是A,而鼠标指针clinetXY参考点是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,比例一定要相同,如果比例不相同,放大镜放大感觉就不一样了,无法看全。

 


六、鼠标滚轮事件

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

ChromeIE各个版本浏览器都支持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

 


 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
前端笔记之jQuery(下)事件&节点操作&净位置&拖拽&页面卷动值&遍历JSON

一、监听事件大全 1.1 JavaScript事件 onblur 元素失去焦点onchange 用户改变域的内容onclick 鼠标点击某个对象ondblclick 鼠标双击某个对象onfocus 元素获得焦点onkeydown 某个键盘的键被按...

osc_w9s1w4o0
2019/04/02
3
0
js拖拽效果的原理及实现

1. 原理 JS 拖拽一个元素的原理: 首先要明白三个值 鼠标的位置A = {x, y} 盒子的位置B = {x, y} 鼠标在盒子内的距离C = {A.x - B.x, A.y - B.y} 涉及到三个鼠标事件 鼠标按下时,mousedown...

下个村
04/06
0
0
Cesium入门4 - 创建Cesium Viewer

Cesium入门4 - 创建Cesium Viewer Cesium中文网:http://cesiumcn.org/ 国内快速访问:http://cesium.coinidea.com/ 任何Cesium应用程序的基础都是Viewer。Viewer是一个带有多种功能的可交互...

CoinIdea
2018/08/22
719
0
div拖拽的问题

今天看到一篇写的很好的文章,摘抄如下: 思路 父盒子相对定位,子元素,也就是被拖拽的元素绝对定位 当鼠标在子元素中按下时,绑定鼠标移动事件,根据鼠标位置改变元素位置 设置鼠标当前位置...

osc_9wny6wso
2019/09/16
0
0
javascript鼠标及键盘事件总结及案例

一、鼠标事件 1、单击事件 2、双击事件(双击时也会触发单击) 3、鼠标右键 4、按下|移动|抬起|鼠标悬浮|鼠标移开|鼠标右键 总结: 将父集和自己分开考虑盒子的悬浮离开事件,用over | out组合...

osc_t8hom09j
2019/06/18
1
0

没有更多内容

加载失败,请刷新页面

加载更多

如何在控制器中使用过滤器? - How to use a filter in a controller?

问题: I have written a filter function which will return data based on the argument you are passing. 我编写了一个过滤函数,它将根据您传递的参数返回数据。 I want the same functi......

富含淀粉
今天
26
0
android:layout_weight是什么意思? - What does android:layout_weight mean?

问题: I don't understand how to use this attribute. 我不明白如何使用这个属性。 Can anyone tell me more about it? 谁能告诉我更多关于它的事情? 解决方案: 参考一: https://stacko...

javail
今天
17
0
CSS背景不透明度[重复] - CSS Background Opacity [duplicate]

问题: This question already has an answer here: 这个问题已经在这里有了答案: How do I give text or an image a transparent background using CSS? 如何使用CSS为文本或图像提供透明背...

fyin1314
今天
27
0
node http 获取gb2312网页如何转为utf8

最初,我想当然认为是下述做法,但被证明是错误的 const http = require('http'), iconv = require('iconv-lite');const url = 'http://xxx';http.get(url, function(res) { var bo......

高延
今天
24
0
动态规划:LC198.打家劫舍

题目描述: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入...

曦鱼violet
今天
30
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部