0
点赞
收藏
分享

微信扫一扫

event.pageX/Y 属性

event.pageX 和 event.pageY 属性表示鼠标到网页的左边和上边的距离。当浏览器没有卷动的时候,它们

的数值等于 event.clientX 和 event.clientY 值。我们进行验证:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Document</title>

<style type="text/css">

*{

margin: 0;

padding: 0;

}

.box{

width:200px;

height:200px;

background-color: orange;

margin-top: 100px;

margin-left:200px;

}

</style>

</head>

<body>

<div class="box" id="box"></div>

<script type="text/javascript">

var oBox = document.getElementById("box");

oBox.onmousemove = function(event){

console.log(event.clientX , event.clientY , event.pageX , event.pageY);

}

</script>

</body>

</html>

打开网页,鼠标指针在盒子内自由移动,可以看到 event.clientX 始终等于 event.pageX 值,

event.clientY 始终等于 event.pageY 值。

当网页非常长,产生了滚动条,我们滚动了滚动条时,event.pageY 和 event.clientY 值产生了区别。例

如:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Document</title>

<style type="text/css">

*{

margin: 0;

padding: 0;

}

.box{

width:200px;

height:200px;

background-color: orange;

margin-top: 600px;

margin-left:200px;

}

</style>

</head>

<body>

<div class="box" id="box"></div>

<script type="text/javascript">

var oBox = document.getElementById("box");

oBox.onmousemove = function(event){

console.log(event.clientY , event.pageY);

}

</script>

</body>

</html>

为了使网页产生滚动条,我们给盒子设置了非常大的 margin-top 值,网页被“撑”长了。打开浏览器查看

网页,故意卷动一些浏览器的滚动条,将鼠标指针随便在盒子内部自由自动,此时可以看出 event.pageY 大于

event.clientY 值,这个因为前者表示鼠标指针到页面顶端的距离;而后者表示鼠标指针到浏览器视口顶端的

距离

嵌套盒模型的鼠标位置 offsetX/Y 的问题

 问题引出

我们知道鼠标事件中,event.offsetX/Y 表示鼠标指针到盒子的左边、顶边的距离。如果是单一盒模型,

这没有任何问题。但是如果盒子有内部子盒子,即盒模型为嵌套状态时,就会产生一定的问题。我们通过案例代

码来演示。

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Document</title>

<style type="text/css">

*{

margin: 0;

padding: 0;

}

.box{

width:200px;

height:200px;

background-color: orange;

margin-top: 200px;

margin-left:200px;

border:1px solid #eee;

}

p{

width:80px;

height:80px;

background-color: blue;

margin: 30px;

}

</style>

</head>

<body>

<div class="box" id="box">

<p></p>

</div>

<script type="text/javascript">

var oBox = document.getElementById("box");

oBox.onmousemove = function(event){

console.log(event.offsetX , event.offsetY);

}

</script>

</body>

</html>

我们在 div 盒子内部添加了 p 标签,并且给 p 设置了外边距,此时 p 和 div 之间有一定的距离。我们监听

div 盒子的鼠标移动事件,输出 event.offsetX 和 event.offsetY。打开浏览器,鼠标指针在盒子内部自由移

动,发现当鼠标指针移动到 p 标签的左上角的时候两个数值均区域 0

这个演示可以说明,event.offsetX 和 event.offsetY 的参考点是最内层盒子的左上角,而不是添加事件

监听的盒子的左上角。

 问题解决方案

那如何得到鼠标指针距离 div 盒子左上角的位置呢?你可能会回答,将鼠标指针此时的 event.offsetX 值

加上 p 距离 div 盒子左边的距离,event.offsetY 值加上 p 距离 div 盒子上边的距离不就行了。

你的回答是正确的,但是不实用。比如我们下小节将学习拖拽效果,拖拽效果的实现原理就是用 JavaScript

根据鼠标指针来设置 p 标签的位置。即,现在我们要根据鼠标指针的位置来“设置”p 标签的位置,但是鼠标指

针的位置此时还要根据 p 标签和 div 盒子的位置来计算,这就非常矛盾。好比一个人又当运动员也当裁判员,

这是不合适的。

那如何解决这个问题呢?我们可以使用间接的方法来得到鼠标指针距离 div 盒子左上角的位置:

鼠标指针距离 div 上边的距离 = 鼠标指针距离网页顶端的距离 - div 上边距离网页顶端的距离

这个公式的含义如图 11-19 所示。在图 11-19 中,线段 y 就是要求的鼠标指针距离 div 盒子上边的距离,

线段 y1 就是 div 上边距离网页顶端的距离,线段 y2 就是鼠标指针距离网页顶端的距离。

所以上述公式可以简化为 y = y2 - y1。

y1 的值是 event.pageY,但是 y1 的值用 JavaScript 怎么表达呢?即一个盒子距离页面顶端的距离应该

如何得到呢?我们把一个盒子的顶边(或左边)距离网页顶边(或左边)的距离,称为这个盒子的“竖直净位置”

(或水平净位置)。

 净位置的计算

JavaScript 中任何一个 DOM 元素,都有一个 offsetTop 属性,表示这个盒子顶边到自己的“定位参考祖

先元素”顶边的距离。

“定位参考祖先元素”是什么呢?我们把一个盒子的祖先盒子中,离自己最近的已经定位的祖先元素称为“定

位参考祖先元素”,JavaScript 中用 oDiv.offsetParent 属性表示。

比如:

<div id="box1"> → 绝对定位

<div id="box2"> → 相对定位

<div id="box3"> → 没有定位

<p id="para"></p>

</div>

</div>

</div>

最内层的 id 为 para 的 p 标签有 3 个 div 祖先,box3 离 para 最近,但是它没有定位,所以它不是

para.offsetParent。而 box2 是距离 b 最近的已经定位的元素,不管它是相对定位还是绝对定位,只要定位就

行,它就是 para.offsetParent。

我们做实验来验证。HTML 和 CSS 如下:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Document</title>

<style type="text/css">

*{

margin: 0;

padding: 0;

}

.box1{

position: absolute;

width:500px;

height: 400px;

border:3px solid red;

padding:40px;

}

.box2{

position: relative;

width:400px;

height: 300px;

border:3px solid red;

padding:40px;

}

.box3{

width:200px;

height: 200px;

border:3px solid red;

padding:50px;

}

#para{

width: 60px;

height: 60px;

background-color: orange;

}

</style>

</head>

<body>

<div class="box1">

<div class="box2">

<div class="box3">

<p id="para"></p>

</div>

</div>

</div>

</body>

</html>

页面布局完毕,网页如图 11-20 所示。最内层的方形盒子是 p 标签,包裹它的是 3 个 div 盒子。从内层到

外层的 div 盒子的定位情况分别是:没有定位、相对定位、绝对定位。根据我们已经学习过的知识,box2 就是p 标签的“定位参考祖先元素”即 para.offsetParent。而 p 标签到 box2 的距离就是 para.offsetTop。

我们书写程序来测试:

<script type="text/javascript">

var para = document.getElementById("para");

alert(para.offsetTop);

alert(para.offsetParent.className);

</script>

可见,box2 的确是 para 的定位参考祖先盒子。并且弹出的 93 就是 para 到这个盒子的距离,如图 11-22

所示。

我们得到了 para 到 box2 的距离,那 para 到页面顶端的距离呢?

容易想到,box2 也有自己的 offsetTop 值,也就是 box2 到它的定位参考盒子 box1 的距离。而 box1 也有

自己的 offsetTop 值,也就是 box1 到它的定位参考盒子 body 的距离。

即,一个盒子的净位置等于它的 offsetTop 加上它的 offsetParent 的 offsetTop,在加上它的

offsetParent 的 offsetParent 的 offsetTop……当然,不要忘记将这些盒子的上边框的宽度加上,因为

offsetTop 值不包括边框。根据这个原理,我们可以写出函数:

function getAllY(o){

var allY = o.offsetTop; //累加器

//一层一层迭代上去,记得补边框

while(o = o.offsetParent){

allY += o.offsetTop + Number(getComputedStyle(o)["border-top-width"]);

}

return allY;

}

程序中的 getComputedStyle(o)["border-top-width"]表示得到这个盒子的上边框的计算后宽度。

举报

相关推荐

0 条评论