8

视觉走查插件开发之深入ResizeObserver

 2 years ago
source link: https://jelly.jd.com/article/62bbe9522e72eb019c3fd24c
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

JELLY | 视觉走查插件开发之深入ResizeObserver

视觉走查插件开发之深入ResizeObserver
上传日期:2022.07.01
Pixeye是团队最近打造的一款视觉走查产品,PC端解决方案已推广使用,二期H5端已在开发内测中。本文主要介绍ResizeObserver在其中的深入使用经验。

最近团队在打造一款·还原度走查验收·产品,目的是弥补RELAAAY一站式设计协作平台最后一环,精准还原设计细节,提升体验设计全链路的协同效率,为设计师测试人员研发工程师三者在视觉走查流程工作中提供便利、高效、智能的协同走查工具。PC版体验地址请 猛击

在上一篇文章 视觉走查插件开发之深入MutationObserver 中使用 MutationObserver 实现了对DOM元素的属性或者节点变化的检测,从而实现走查缺陷锚点定位的动态渲染。

但是如果我们想要检测到DOM元素尺寸变化,在过去是没有专门的API的,多借助window对象上绑定resize事件。

但是DOM元素的尺寸变化,有时候窗体的尺寸没有变化也会触发。还有的时候窗体的尺寸变化了,但是DOM元素的尺寸并没有变化,window对象上绑定的resize事件就实现不了。

由于以上一些原因,一个全新的API就出来了,就是ResizeObserver对象,专门用来观察DOM元素的尺寸是否发生了变化。

API 介绍

先来看下 MDNResizeObserver的介绍

ResizeObserver 接口可以监听到 Element 的内容区域或 SVGElement的边界框改变。内容区域则需要减去内边距 padding。

ResizeObserver 避免了在自身回调中调整大小,从而触发的无限回调和循环依赖。它仅通过在后续帧中处理 DOM 中更深层次的元素来实现这一点。如果(浏览器)遵循规范,只会在绘制前或布局后触发调用。

该构造函数用于实例化一个新的 ResizeObserver ,同时指定触发 DOM 变动时的回调函数:

var observer = new ResizeObserver(callback);
    function callback(entries){}

callback,即回调函数接收一个参数,

  1. observe(target)

开始观察指定的 Element或 SVGElement。

  1. disconnect()

取消和结束目标对象上所有对 Element或 SVGElement 观察。

  1. unobserve()

结束观察指定的Element或 SVGElement。

假设页面上有个DOM元素,名叫emulator,则我们想要在emulator尺寸变化的时候做点什么事情,可以使用下面的JavaScript代码:

var ro = new ResizeObserver( entries => {
  for (let entry of entries) {
    const cr = entry.contentRect;
    console.log('Element:', entry.target);
    console.log(`Element size: ${cr.width}px x ${cr.height}px`);
    console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
  }
});

// 观察一个或多个元素
ro.observe(emulator);

此时我们在控制台就你呢个看到类似下图的结果:

11d36b920f7b79f2.png

contentRect指的是什么? entry.contentRect返回的是一个DOMRect对象,例如的属性包括:

{
    "x": 0,
    "y": 0,
    "width": 1771,
    "height": 0,
    "top": 0,
    "right": 1771,
    "bottom": 0,
    "left": 0
}

如果我们给DOM元素设置个padding:10px,则宽高都会变小,同时left和top属性值变成了10。

{
    "x": 10,
    "y": 10,
    "width": 1731,
    "height": 0,
    "top": 10,
    "right": 1741,
    "bottom": 10,
    "left": 10
}

这表明contentRect返回是content box,也就是内容区域的尺寸。

content box示意图,参见下图中间那部分:

11d36b920f7b79f2.png

同时也从侧面说明了,如果一个元素的content box的尺寸没有发生变化,那么也是不会触发ResizeObserver观察执行的,哪怕你改变了元素的padding值,或者改变了元素的border-width边框尺寸,都不会认为是DOM元素尺寸变化了。

实际应用案例

  1. 原生resize行为的检测

例如,有了ResizeObserver,我们就可以检测 模拟器外容器 的resize拉伸行为,重新绘制锚点的位置。

如下GIF录屏效果所示:

11d36b920f7b79f2.png
  1. 感知元素显示或隐藏动态渲染锚点

在上篇文章中使用MutationObserver实现了对动态插入节点的探测,当类似模态框插入时,动态渲染模态框内的走查锚点。但是面对一个元素使用display:none进行隐藏和显示的时候,通过MutationObserver观察图片属性或节点的变化是没有任何用的。此时应该使用ResizeObserver。因为display:none也是会触发尺寸变化的,于是也能够被观测到。

11d36b920f7b79f2.png

Polyfill

项目地址: https://github.com/juggle/resize-observer

理论上可以兼容到IE9浏览器,不过还需要引入其他Polyfill,IE11+以及其他现代浏览器直接引入项目JS就可以了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK