纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

js中的位置计算 一篇文章让你彻底搞懂js中的位置计算

19组清风   2021-09-13 我要评论
想了解一篇文章让你彻底搞懂js中的位置计算的相关内容吗19组清风在本文为您仔细讲解js中的位置计算的相关知识和一些Code实例欢迎阅读和指正我们先划重点:js获取当前位置,js获取位置,js设置scroll的宽度下面大家一起来学习吧

引言

文章中涉及到的api列表:

  1. scroll相关Api
  2. client相关Api
  3. offset相关Api
  4. Element.getBoundingClientRectAPi
  5. Window.getComputedStyleApi

我们会结合api定义知名开源库中的应用场景来逐层分析这些api足以应对工作中关于元素位置计算的大部分场景

注意在使用位置计算api时要格外的小心不合理的使用他们可能会造成布局抖动Layout Thrashing影响页面渲染

scroll

首先我们先来看看scroll相关的属性和方法

Element.scroll()

Element.scroll()方法是用于在给定的元素中滚动到某个特定坐标的Element 接口

element.scroll(x-coord, y-coord)
element.scroll(options)
  • x-coord 是指在元素左上方区域横轴方向上想要显示的像素
  • y-coord 是指在元素左上方区域纵轴方向上想要显示的像素

也就是element.scroll(x,y)会将元素滚动条位置滚动到对应x,y的位置

同时也支持element.scroll(options)方式调用支持传入额外的配置:

{
    left: number, 
    top: number,
    behavior: 'smooth' | 'auto' // 平滑滚动还是默认直接滚动
}

Element.scrollHeight/scrollWidth

Element.scrollHeight 这个只读属性是一个元素内容高度的度量包括由于溢出导致的视图中不可见内容

scrollHeight 的值等于该元素在不使用滚动条的情况下为了适应视口中所用内容所需的最小高度 没有垂直滚动条的情况下scrollHeight值与元素视图填充所有内容所需要的最小值clientHeight相同包括元素的padding但不包括元素的border和marginscrollHeight也包括 ::before 和 ::after这样的伪元素

换句话说Element.scrollHeight在元素不存在滚动条的情况下是恒等于clientHeight的
但是如果出现了滚动条的话scrollHeight指的是包含元素不可以见内容的高度出现滚动条的情况下是scrollHeight恒大于clientHeight

  • Element.scrollWidth 这也是一个元素内容宽度的只读属性包含由于溢出导致视图中不可以见的内容

原理上和scrollHeight是同理的只不过这里是宽度而非高度

简单来说一个元素如果不存在滚动条那么他们的scroll和client都是相等的值如果存在了滚动条client只会计算出当前元素展示出来的高度/宽度而scroll不仅仅会计算当前元素展示出的还会包含当前元素的滚动条隐藏内容的高度/宽度

clientWidth/height + [滚动条被隐藏内容宽度/高度] = scrollWidth/Height

Element.scrollLeft/scrollTop

  • Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数.
  • Element.scrollLeft 属性可以读取或设置元素滚动条到元素左边的距离.

需要额外注意的是: 注意如果这个元素的内容排列方向(direction) 是rtl (right-to-left) 那么滚动条会位于最右侧(内容开始处)并且scrollLeft值为0此时当你从右到左拖动滚动条时scrollLeft会从0变为负数

scrollLeft/Top在日常工作中是比较频繁使用关于操作滚动条的相关api他们是一个可以设置的值根据不同的值对应可以控制滚动条的位置

其实这两个属性和上方的Element.scroll()可以达到相同的效果

在实际工作中如果对于滚动操作有很频繁的需求个人建议去使用better-scroll它是一个移动/web端的通用js滚动库内部是基于元素transform去操作的滚动并不会触发相关重塑/回流

判断当前元素是否存在滚动条

出现滚动条便意味着元素空间将大于其内容显示区域根据这个现象便可以得到判断是否出现滚动条的规则

export const hasScrolled = (element, direction) => {
  if (!element || element.nodeType !== 1) return;
  if (direction === "vertical") {
    return element.scrollHeight > element.clientHeight;
  } else if (direction === "horizontal") {
    return element.scrollWidth > element.clientWidth;
  }
};

判断用户是否滚动到底部

本质上就是当元素出现滚动条时判断当前元素出现的高度 + 滚动条高度 = 元素本身的高度(包含隐藏部分)

element.scrollHeight - element.scrollTop === element.clientHeight

client

MouseEvent.clientX/Y

MounseEvent.clientX/Y同样也是只读属性它提供事件发生时的应用客户端区域的水平坐标

例如不论页面是否有垂直/水平滚动当你点击客户端区域的左上角时鼠标事件的 clientX/Y 值都将为 0 

其实MouseEvent.clientX/Y也就是相对于当前视口(浏览器可视区)进行位置计算

转载一张非常直白的图:

Element.clientHeight/clientWidth

Element.clientWidth/clinetHeight 属性表示元素的内部宽度以像素计该属性包括内边距 padding但不包括边框 border、外边距 margin 和垂直滚动条(如果有的话)

内联元素以及没有 CSS 样式的元素的 clientWidth 属性值为 0

在不出现滚动条时候Element.clientWidth/Height === Element.scrollWidth/Height

Element.clientTop/clientLeft

Element.clientLeft表示一个元素的左边框的宽度以像素表示如果元素的文本方向是从右向左(RTL, right-to-left)并且由于内容溢出导致左边出现了一个垂直滚动条则该属性包括滚动条的宽度clientLeft 不包括左外边距和左内边距clientLeft 是只读的

同样的Element.clientTop表示元素上边框的宽度也是一个只读属性

这两个属性日常使用会比较少但是也应该了解以避免搞混这些看似名称都类似的属性

offset

MouseEvent.offsetX/offsetY

MouseEvent 接口的只读属性 offsetX/Y 规定了事件对象与目标节点的内填充边(padding edge)在 X/Y 轴方向上的偏移量

相信使用过offest的同学对这个属性深有体会它是相对于父元素的左边/上方的偏移量

注意是触发元素也就是 e.target额外小心如果事件对象中存在从一个子元素当移动到子元素内部时e.offsetX/Y 此时相对于子元素的左上角偏移量

offsetWidth/offsetHeight

HTMLElement.offsetWidth/Height 是一个只读属性返回一个元素的布局宽度/高度

所谓的布局宽度也就是相对于我们上边说到的clientHeight/Width,offsetHeight/Width,他们都是不包含border以及滚动条的宽/高(如果存在的话)

而offsetWidth/offsetHeight返回元素的布局宽度/高度包含元素的边框(border)、水平线/垂直线上的内边距(padding)、竖直/水平方向滚动条(scrollbar)(如果存在的话)、以及CSS设置的宽度(width)的值

offsetTop/left

HTMLElement.offsetLeft 是一个只读属性返回当前元素左上角相对于 HTMLElement.offsetParent 节点的左边界偏移的像素值

注意返回的是相对于 HTMLElement.offsetParent 节点左边边界的偏移量

何为HTMLElement.offsetParent?

HTMLElement.offsetParent 是一个只读属性返回一个指向最近的(指包含层级上的最近)包含该元素的定位元素或者最近的 table,td,th,body 元素当元素的 style.display 设置为 "none" 时offsetParent 返回 nulloffsetParent 很有用因为 offsetTop 和 offsetLeft 都是相对于其内边距边界的  -- MDN

讲讲人话当前元素的祖先组件节点如果不存在任何 table,td,th 以及 position 属性为 relative,absolute 等为定位元素时,offsetLeft/offsetTop 返回的是距离 body 左/上角的偏移量

当祖先元素中有定位元素(或者上述标签元素)时它就可以被称为元素的offsetParent元素的 offsetLeft/offsetTop 的值等于它的左边框左侧/顶边框顶部到它的 offsetParent 元素左边框的距离

我们来看看这张图:

计算元素距离 body 的偏移量

当我们需要获得元素距离 body 的距离时但是又无法确定父元素是否存在定位元素时(大多数时候在组件开发中并不清楚父节点是否存在定位)此时需要实现类似 jqery 的 offset()方法:获得当前元素对于 body 的偏移量

  • 无法直接使用 offsetLeft/offsetTop 获取因为并不确定父元素是否存在定位元素
  • 使用递归解决累加偏移量 offset当前 offsetParent 不为 body 时
  • 继续递归向上超着 offsetParent 累加 offset直到遇到 body 元素停止
const getOffsetSize = function(Node: any, offset?: any): any {
  if (!offset) {
    offset = {
      x: 0,
      y: 0
    };
  }
  if (Node === document.body) return offset;
  offset.x = offset.x + Node.offsetLeft;
  offset.y = offset.y + Node.offsetTop;
  return getOffsetSize(Node.offsetParent, offset);
};

注意:这里不可以使用 parentNode 上文已经讲过 offsetLeft/top 针对的是 HTMLElement.offsetParent 的偏移量而非 parentNode 的偏移量

Element.getBoundingClientRect

用法讲解

Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置

element.getBoundingClientRect()返回的相对于视口左上角的位置

element.getBoundingClientRect()返回的 height 和 width 是针对元素可见区域的宽和高(具体尺寸根据 box-sizing 决定)并不包含滚动条被隐藏的内容

TIP: 如果是标准盒子模型元素的尺寸等于 width/height + padding + border-width 的总和如果 box-sizing: border-box元素的的尺寸等于 width/height

rectObject = object.getBoundingClientRect();

返回值是一个 DOMRect 对象这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合就是该元素的 CSS 边框大小返回的结果是包含完整元素的最小矩形并且拥有 left, top, right, bottom, x, y, width, 和 height 这几个以像素为单位的只读属性用于描述整个边框除了 width 和 height 以外的属性是相对于视图窗口的左上角来计算的

width和height是计算元素的大小其他属性都是相对于视口左上角来说的

当计算边界矩形时会考虑视口区域(或其他可滚动元素)内的滚动操作也就是说当滚动位置发生了改变top 和 left 属性值就会随之立即发生变化(因此它们的值是相对于视口的而不是绝对的) 如果你需要获得相对于整个网页左上角定位的属性值那么只要给 top、left 属性值加上当前的滚动位置(通过 window.scrollX 和 window.scrollY)这样就可以获取与当前的滚动位置无关的值

计算元素是否出现在视口内

利用的还是元素距离视口的位置小于视口的大小

注意即便变成了负值那么也表示元素曾经出现过在屏幕中只是现在不显示了而已(就比如滑动过)

vue-lazy图片懒加载库源码就是这么判断的

 isInView (): boolean {
    const rect = this.el.getBoundingClientRect()
    return rect.top < window.innerHeight && rect.left < window.innerWidth
  }

如果rect.top < window.innerHeight表示当前元素已经已经出现在(过)页面中left同理

window.getComputedStyle

用法讲解

Window.getComputedStyle()方法返回一个对象该对象在应用活动样式表并解析这些值可能包含的任何基本计算后报告元素的所有CSS属性的值 私有的CSS属性值可以通过对象提供的API或通过简单地使用CSS属性名称进行索引来访问

let style = window.getComputedStyle(element, [pseudoElt]);

element

  •  用于获取计算样式的Element

pseudoElt 可选

  • 指定一个要匹配的伪元素的字符串必须对普通元素省略(或null)

返回的style是一个实时的 CSSStyleDeclaration 对象当元素的样式更改时它会自动更新本身

总结


相关文章

猜您喜欢

  • Java Map 深入浅出讲解Java集合之Map接口

    想了解深入浅出讲解Java集合之Map接口的相关内容吗威斯布鲁克.猩猩在本文为您仔细讲解Java Map的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Java,Map,Java,Map接口下面大家一起来学习吧..
  • 整体认知Spring体系结构 Spring IOC源码剖析_怎样整体认知Spring体系结构

    想了解Spring IOC源码剖析_怎样整体认知Spring体系结构的相关内容吗我要大芒果在本文为您仔细讲解整体认知Spring体系结构的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Spring,IOC,IOC源码剖析,Spring体系结构下面大家一起来学习吧..

网友评论

Copyright 2020 www.sopisoft.net 【绿软下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式