详解JavaScript中的坐标和距离


Posted in Javascript onMay 27, 2019

一 前言

在前端开发中总会遇到各种各样需要使用或计算坐标和距离的情况,但是这些属性和方法众多,全部熟练地记下来并非是一件易事,大多只能现查,耗费不少时间精力,于是便有了整理记录的想法,即加深了印象,又方便随时查阅。

二 window 对象

浏览器里面,window 对象(注意,w为小写)指当前的浏览器窗口。
它也是当前页面的顶层对象,即最高一层的对象,所有其他对象都是它的下属。一个变量如果未声明,那么默认就是顶层对象的属性。
摘自《阮一峰 JavaScript 教程》

位置大小属性

window.screenX , window.screenY

只读属性

返回浏览器窗口左上角相对于当前屏幕左上角的水平距离和垂直距离(单位像素)。

window.innerHeight , window.innerWidth

只读属性

返回网页在当前窗口中可见区域的高度和宽度,即「视口」(viewport)的大小(单位像素)。

注意,这两个属性包括滚动条的高度和宽度。

window.outerHeight , window.outerWidth

只读属性

返回浏览器窗口的高度和宽度,包括浏览器菜单和边框(单位像素)。

window.scrollX , window.scrollY

只读属性

别名: window.pageXOffset , window.pageYOffset

分别返回页面的水平滚动距离和垂直滚动距离,单位都是像素。

注意,这两个属性的返回值不是整数,而是双精度浮点数。如果页面没有滚动,它们的值就是0。

摘自《阮一峰 JavaScript 教程》

为了跨浏览器兼容性,请使用 window.pageXOffset 代替 window.scrollX。另外,旧版本的 IE(<9)两个属性都不支持,必须通过其他的非标准属性来解决此问题。

摘自 MDN :https://developer.mozilla.org/zh-CN/docs/Web/API/Window/scrollX

window 对象的方法

window.scrollTo() , window.scroll() , window.scrollBy()

window.scrollTo 方法 ---> 别名: window.scroll 方法

用于将文档滚动到指定位置。

它接受两个参数,表示滚动后位于窗口左上角的页面坐标。

也可以接受一个配置对象作为参数。

window.scrollTo(options)

配置对象 options 有三个属性。

  • top:滚动后页面左上角的垂直坐标,即 y 坐标。
  • left:滚动后页面左上角的水平坐标,即 x 坐标。
  • behavior:字符串,表示滚动的方式,有三个可能值(smooth、instant、auto),默认值为 auto。

window.scrollBy 方法用于将网页滚动指定距离(单位像素)。

它接受两个参数:水平向右滚动的像素,垂直向下滚动的像素。

注意:仔细体会这两者的差别。

三 Element 节点

Element节点对象对应网页的 HTML 元素。每一个 HTML 元素,在 DOM 树上都会转化成一个Element节点对象(简称元素节点)。

相关属性

Element.clientHeight,Element.clientWidth

分别返回元素的高度和宽度,始终是整数值。

如果该元素是内联元素(display: inline;),则返回值为 0。

从盒模型的概念上来讲,返回的数值计算包括元素的 content 和 padding ,不包括 border 和 margin 。

如果有滚动条,返回的数值会减去滚动条占据的宽度或高度。(即不包含滚动条在内)

// 浏览器视口高度
document.documentElement.clientHeight
// 网页总高度
document.body.clientHeight

Element.clientLeft,Element.clientTop

分别返回元素的左边框宽度和上边框宽度,没有边框则返回 0。

同样不支持内联元素。

(我没太明白这两个属性有啥作用……)

Element.scrollHeight,Element.scrollWidth

返回当前元素的总高度和总宽度,包括溢出容器、当前并不可见的部分。

包括 padding 区域。

包括伪元素的宽度和高度。

不包含滚动条的宽度和高度。

来个小 demo 辅助下理解:

<div class="box"> 666 </div>
.box {
width: 200px; height: 200px; overflow: hidden;
border: 1px solid red; padding: 10px; position: relative;
}
.box::after {
position: absolute; content: '';
width: 100px; height: 100px; left: 100%;
}
let box = document.querySelector('.box')
console.log(box.scrollWidth) // 320
console.log(box.scrollHeight) // 220

可以看到 box 元素的 scrollHeight 是 220,这个和我们提到的「包括 padding 区域」相符合。

那 box 元素的 scrollWidth 为啥是 320 ? 是因为伪元素的位置和宽度,虽然伪元素溢出被隐藏了,但是这个属性返回的数值依然包括它。

当然不仅仅包括它的宽度和高度,它所处的位置也会计算在内。

比如把伪元素的 css 改一下:

.box::after {
position: absolute; content: '';
width: 100px; height: 100px;
left: 120%; top: 120%;
}

现在你要不要猜一下 box 的 scrollWidth 和 scrollHeight 分别是多少?

Element.scrollLeft,Element.scrollTop

可读写,设置该属性的值,会导致浏览器将当前元素自动滚动到相应的位置。

分别返回当前元素的水平滚动距离和垂直滚动距离。

对于那些没有滚动条的网页元素,这两个属性总是等于 0。

如果要查看整张网页的水平的和垂直的滚动距离,要从 document.documentElement 元素上读取。

document.documentElement.scrollLeft
document.documentElement.scrollTop

Element.offsetHeight,Element.offsetWidth

分别返回元素的高度和宽度,包括元素本身的高和宽、padding 和 border ,以及滚动条的高和宽。

如果元素的 display 为 none,则返回 0。

与 clientHeight 和 clientWidth 相比,我想这对属性用的更多一点,因为更多的时候我们需要获取的是元素的完整宽高。

Element.offsetLeft,Element.offsetTop

返回当前元素左上角相对于 Element.offsetParent 节点的水平和垂直位移。

说到这个我们来了解下 Element.offsetParent:

Element.offsetParent 属性返回最靠近当前元素的、并且 CSS 的 position 属性不等于 static 的上层元素。

如果该元素是不可见的(display属性为none),或者位置是固定的(position属性为fixed),则offsetParent属性返回null。

如果某个元素的所有上层节点的position属性都是static,则Element.offsetParent属性指向元素。

摘自《阮一峰 JavaScript 教程》

相关方法

Element.getBoundingClientRect()

返回一个对象,提供当前元素的大小、位置等信息。

我常用来它获取元素的宽高和坐标。

该对象有如下属性:

  • width
  • height
  • x 元素左上角相对于 视口 的横坐标
  • y
  • left
  • right
  • top
  • bottom

由于元素相对于视口(viewport)的位置,会随着页面滚动变化,因此表示位置的四个属性值,都不是固定不变的。如果想得到绝对位置,可以将 left 属性加上 window.scrollX , top 属性加上 window.scrollY。

摘自《阮一峰 JavaScript 教程》

四 鼠标事件

MouseEvent 接口

let event = new MouseEvent('click', {
// ...
})

通过 addEventListener 添加的 click 事件所产生的事件对象也是 MouseEvent 实例。

let box = document.querySelector('.box')
box.addEventListener('click', (e) => {
console.log(e) // 事件对象
})

这个事件对象,也就是 MouseEvent 实例,有很多属性,这里来简单分析一下。

MouseEvent.clientX 和 MouseEvent.clientY

只读属性

分别返回鼠标位置相对于 浏览器窗口 左上角的水平坐标和垂直坐标。(不受滚动距离的影响)

可以这样理解:

client 本来就是客户端的意思,web 中的客户端就是浏览器,那 clientX 和 clientY 自然就是相对于浏览器的位置了。

这两个属性还分别有一个别名 MouseEvent.x 和 MouseEvent.y 。

MouseEvent.screenX,MouseEvent.screenY

只读属性

分别返回鼠标位置相对于 屏幕(显示器屏幕区域) 左上角的水平坐标和垂直坐标。

screen 是屏幕的意思,所以,你懂的。

MouseEvent.offsetX,MouseEvent.offsetY

只读属性

分别返回鼠标位置相对于 目标节点(即当前元素) 左上角 padding 边缘 的 水平距离和垂直距离。

offset 有偏移的意思,所以这里也可以理解为鼠标位置相对于目标元素内部左上角的偏移值,和目标元素本身以及外部的元素都无关。

那 「padding 边缘」是什么意思呢?

我们拿图说话:

详解JavaScript中的坐标和距离

上图中三个元素分别有红蓝绿三种边框来区分,红蓝边框宽度为 1px , 绿边框为 30px 。每个元素都有 padding 值。具体代码如下:

<!-- HTML -->
<body>
<div class="parent">
<div class="hello">Hello</div>
</div>
</body>
/* css */
body {
border: 1px solid red; margin: 0; padding: 20px;
}
.parent {
border: 1px solid blue; padding-top: 50px;
}
.hello {
width: 100px; height: 100px; padding: 100px; border: 30px solid green;
}

我们给 hello 元素添加一个 click 时间监听函数:

// js
let hello = document.querySelector('.hello')
hello.addEventListener('click', (e) => {
console.log(e)
console.log(e.offsetX)
console.log(e.offsetY)
})

分别点击 hello 元素的绿色边框和空白区域,会发现前者的值为负数,后者的值为整数,且都是相对空白区域的左上角开始计算的。

这就是我们一开始提到的 「鼠标位置相对于 目标节点(即当前元素) 左上角 padding 边缘 的 水平距离和垂直距离」 这句话的意思。

MouseEvent.pageX,MouseEvent.pageY

只读属性

分别返回鼠标位置相对于文档左上角的距离。(包括滚动距离)

MouseEvent.movementX,MouseEvent.movementY

只读属性

返回当前位置与上一个 mousemove 事件之间的水平距离和垂直距离。

很明显这两个属性和 mousemove 事件肯定有着密切的关系,所以我们再了解一下 mousemove 事件:

当鼠标在一个节点内部移动时触发。当鼠标持续移动时,该事件会连续触发。为了避免性能问题,建议对该事件的监听函数做一些限定,比如限定一段时间内只能运行一次。

说到这个应该会牵扯到「节流」,暂不深入了。

这两个属性还是很有用的,我虽然没咋用过,不过目前想来可以用来判断鼠标的移动方向等。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
测试JavaScript字符串处理性能的代码
Dec 07 Javascript
javascript从右边截取指定字符串的三种实现方法
Nov 29 Javascript
JS判断表单输入是否为空(示例代码)
Dec 23 Javascript
在AngularJS中使用AJAX的方法
Jun 17 Javascript
深入分析Javascript事件代理
Jan 30 Javascript
jquery中validate与form插件提交的方式小结
Mar 26 Javascript
js实现千分符和保留几位小数的简单实例
Aug 01 Javascript
详解Angular中的自定义服务Service、Provider以及Factory
Apr 22 Javascript
JS 使用 window对象的print方法实现分页打印功能
May 16 Javascript
详解mpvue小程序中怎么引入iconfont字体图标
Oct 01 Javascript
vue实现的请求服务器端API接口示例
May 25 Javascript
JavaScript判断浏览器运行环境的详细方法
Jun 30 Javascript
优化Vue项目编译文件大小的方法步骤
May 27 #Javascript
了解JavaScript表单操作和表单域
May 27 #Javascript
分享一个vue项目“脚手架”项目的实现步骤
May 26 #Javascript
使用JS判断页面是首次被加载还是刷新
May 26 #Javascript
Node.js 多进程处理CPU密集任务的实现
May 26 #Javascript
小程序封装路由文件和路由方法(5种全解析)
May 26 #Javascript
vue2.0 实现富文本编辑器功能
May 26 #Javascript
You might like
晶体管来复再生式二管收音机
2021/03/02 无线电
apache+codeigniter 通过.htcaccess做动态二级域名解析
2012/07/01 PHP
PHP使用GD库输出汉字的方法【测试可用】
2016/11/10 PHP
php中preg_replace正则替换用法分析【一次替换多个值】
2017/01/17 PHP
php删除二维数组中的重复值方法
2018/03/12 PHP
实例讲解PHP表单处理
2019/02/15 PHP
对laravel的csrf 防御机制详解,及form中csrf_token()的存在介绍
2019/10/24 PHP
IE8 兼容性问题(属性名区分大小写)
2009/06/04 Javascript
jquery的ajax请求全面了解
2013/03/20 Javascript
javaScript 计算两个日期的天数相差(示例代码)
2013/12/27 Javascript
基于JavaScript实现Json数据根据某个字段进行排序
2015/11/24 Javascript
jQuery动画显示和隐藏效果实例演示(附demo源码下载)
2015/12/31 Javascript
Javascript将数值转换为金额格式(分隔千分位和自动增加小数点)
2016/06/22 Javascript
AngularJS 应用身份认证的技巧总结
2016/11/07 Javascript
Bootstrap3 多个模态对话框无法显示的解决方案
2017/02/23 Javascript
vue监听滚动事件实现滚动监听
2017/04/11 Javascript
详解Vue.js组件可复用性的混合(mixin)方式和自定义指令
2017/09/06 Javascript
JS库之Three.js 简易入门教程(详解之一)
2017/09/13 Javascript
JS实现的视频弹幕效果示例
2018/08/17 Javascript
浅谈小程序globalData的那些事儿
2019/11/01 Javascript
JS自定义对象创建与简单使用方法示例
2020/01/15 Javascript
vue实现防抖的实例代码
2021/01/11 Vue.js
Python 列表(List)操作方法详解
2014/03/11 Python
数据挖掘之Apriori算法详解和Python实现代码分享
2014/11/07 Python
多版本python的pip 升级后, pip2 pip3 与python版本失配解决方法
2019/09/11 Python
python中pdb模块实例用法
2021/01/15 Python
浅谈基于HTML5的在线视频播放方案
2016/02/18 HTML / CSS
瑞士图书网站:Weltbild.ch
2019/09/17 全球购物
Elizabeth Gage官网:英国最好的珠宝设计之一
2020/09/26 全球购物
大专生简历的自我评价
2013/11/26 职场文书
社区优秀志愿者先进事迹
2014/05/09 职场文书
党员学习群众路线教育实践活动对照检查材料
2014/09/23 职场文书
幼儿园老师工作总结2015
2015/05/22 职场文书
2015年支教教师工作总结
2015/07/22 职场文书
事业单位工作人员2015年度思想工作总结
2015/10/15 职场文书
忘记Grafana不要紧2种Grafana重置admin密码方法详细步骤
2022/04/07 Servers