如何使用调整观察者大小 JavaScript API

介绍

Resize Observer是一个新的JavaScript API,非常类似于其他观察器API,如Intersection Observer API

元素的大小更改的最常见原因是,当观看端口被更大或设备的方向在肖像和景观之间发生变化时。到目前为止,我们不得不依赖全球window.resize事件来收听重大的事件,并检查某些元素是否改变了大小。

Resize Observer API 还有另一个用例,窗口的调整大小事件无法帮助我们:当元素被动态地添加或从 DOM 中移除时,这会影响主元素的大小。

在本教程中,您将了解React Observer的基本使用方法,您还将在自己的前端代码中实施React Observer,并测试浏览器支持。

前提条件

要成功完成本教程,您将需要以下内容:

使用 HTML 系列构建网站( 可以帮助你实现这一目标( ( )( ( ( )( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( )( ( ( ( )( ( ( ( )(

步骤 1 – 了解 Resize Observe 的基本用途

使用 Resize Observer 是通过实例化一个新的ResizeObserver对象,并通过接收被观察到的条目的回调函数:

1const myObserver = new ResizeObserver(entries => {
2
3});

在回调函数中,你可能会重复输入. 通过ResizeObserver实例化,在实例中调用观察函数,并将要观察的元素传递到:

1const someEl = document.querySelector('.some-element');
2const someOtherEl = document.querySelector('.some-other-element');
3
4myObserver.observe(someEl);
5myObserver.observe(someOtherEl);

每个输入都分配一个具有contentRecttarget属性的对象,而target是 DOM 元素本身,而contentRect是具有以下属性的对象:宽度、高度、x、y、顶部、右部、底部和左侧。

与元素的getBoundingClientRect不同,宽度和高度的contentRect值不包括叠加值,而contentRect.top是元素的顶部叠加,而contentRect.left是元素的左侧叠加。

例如,如果要在元素的大小发生变化时记录被观察到的元素的宽度和高度,请开始创建一个名为myObserver的恒定变量,然后实例化一个新的ResizeObserver:

1const myObserver = new ResizeObserver(entries => {
2
3});

在回调函数中,使用forEach重复每个输入:

1const myObserver = new ResizeObserver(entries => {
2  entries.forEach(entry => {
3
4  });
5});

forEach循环中,console.log是每个输入的宽度和高度,分别使用entry.contentRect.widthentry.contentRect.height:

1const myObserver = new ResizeObserver(entries => {
2  entries.forEach(entry => {
3    console.log('width', entry.contentRect.width);
4    console.log('height', entry.contentRect.height);
5  });
6});

要使用myObserver,使用 DOM 选择器创建一个名为someEl的元素,将someEl作为myObserver.observe的参数输入:

1const myObserver = new ResizeObserver(entries => {
2  entries.forEach(entry => {
3    console.log('width', entry.contentRect.width);
4    console.log('height', entry.contentRect.height);
5  });
6});
7
8const someEl = document.querySelector('.some-element');
9myObserver.observe(someEl);

了解 Resize Observer 是如何使用的,您现在可以继续使用 Resize Observer 用于现实世界的使用案例。

步骤 2 — 展示如何使用 Resize Observer

下面是一個演示,讓您看到Rezize Observer API在動作中,試試試改變瀏覽器窗口,並注意傾斜角度和文本內容只有當元素的大小實際上受到影響時才會改變:

在使用 Resize Observer API 之前,您首先需要创建一个 index.html 文件:

1touch index.html

在您的HTML文件中,添加以下代码:

1[label index.html]
2<div class="box">
3  <h3 class="info"></h3>
4</div>
5<div class="box small">
6  <h3 class="info"></h3>
7</div>

您还需要为您的 HTML 添加一些风格,创建一个 styles.css 文件,并将以下 CSS 代码添加到该文件中:

 1[label styles.css]
 2.box {
 3  text-align: center;
 4  height: 20vh;
 5  border-radius: 8px;
 6  box-shadow: 0 0 4px var(--subtle);
 7
 8  display: flex;
 9  justify-content: center;
10  align-items: center;
11}
12
13.box h3 {
14  color: #fff;
15  margin: 0;
16  font-size: 5vmin;
17  text-shadow: 0 0 10px rgba(0,0,0,0.4);
18}
19
20.box.small {
21  max-width: 550px;
22  margin: 1rem auto;
23}

注意如何不需要将降级背景应用到 .box 元素.当页面首先加载时,将调用一次调整大小观察器,然后将应用降级。

现在是时候转到JavaScript代码了,你可以创建一个外部JavaScript文件,或者你可以将<script>标签添加到你的HTML文件中,首先,为所有.box元素创建一个DOM选择器:

1const boxes = document.querySelectorAll('.box');

现在将一个新的ResizeObserver实例化,该函数采用一个名为entries的参数:

1const boxes = document.querySelectorAll('.box');
2
3const myObserver = new ResizeObserver(entries => {
4
5});

创建一个for...of循环,它会在entries中的每个entry中迭代。在循环中,创建一个与entry.target.querySelector('.info)等同的恒定变量infoEl

1const boxes = document.querySelectorAll('.box');
2
3const myObserver = new ResizeObserver(entries => {
4  for (let entry of entries) {
5    const infoEl = entry.target.querySelector('.info');
6  }
7});

创建常态变量widthheight,将分别设置为entry.contentRect.widthentry.contentRect.height

1const boxes = document.querySelectorAll('.box');
2
3const myObserver = new ResizeObserver(entries => {
4  for (let entry of entries) {
5    const infoEl = entry.target.querySelector('.info');
6    const width = Math.floor(entry.contentRect.width);
7    const height = Math.floor(entry.contentRect.height);
8  }
9});

由于您将以与屏幕宽度变化的角度创建梯度,请创建一个角度变量,将设置为宽度 / 360 * 100

 1const boxes = document.querySelectorAll('.box');
 2
 3const myObserver = new ResizeObserver(entries => {
 4  for (let entry of entries) {
 5    const infoEl = entry.target.querySelector('.info');
 6    const width = Math.floor(entry.contentRect.width);
 7    const height = Math.floor(entry.contentRect.height);
 8
 9    const angle = Math.floor(width / 360 * 100);
10  }
11});

创建一个称为梯度的常数,它将持有线性梯度的代码:

 1const boxes = document.querySelectorAll('.box');
 2
 3const myObserver = new ResizeObserver(entries => {
 4  for (let entry of entries) {
 5    const infoEl = entry.target.querySelector('.info');
 6    const width = Math.floor(entry.contentRect.width);
 7    const height = Math.floor(entry.contentRect.height);
 8
 9    const angle = Math.floor(width / 360 * 100);
10    const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;
11  }
12});

有了这个梯度,您需要将目标输入的背景设置为梯度,使用entry.target.style.background:

 1const boxes = document.querySelectorAll('.box');
 2
 3const myObserver = new ResizeObserver(entries => {
 4  for (let entry of entries) {
 5    const infoEl = entry.target.querySelector('.info');
 6    const width = Math.floor(entry.contentRect.width);
 7    const height = Math.floor(entry.contentRect.height);
 8
 9    const angle = Math.floor(width / 360 * 100);
10    const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;
11
12    entry.target.style.background = gradient;
13  }
14});

将屏幕上的宽度高度值视为更改是有帮助的. 使用infoElinnerText并将其设置为I’m ${width}px and ${height}px tall:

 1const boxes = document.querySelectorAll('.box');
 2
 3const myObserver = new ResizeObserver(entries => {
 4  for (let entry of entries) {
 5    const infoEl = entry.target.querySelector('.info');
 6    const width = Math.floor(entry.contentRect.width);
 7    const height = Math.floor(entry.contentRect.height);
 8
 9    const angle = Math.floor(width / 360 * 100);
10    const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;
11
12    entry.target.style.background = gradient;
13
14    infoEl.innerText = `I'm ${width}px and ${height}px tall`;
15  }
16});

ResizeObserver的回调已经完成,现在可以使用forEach循环将myObserver函数应用到盒子:

 1const boxes = document.querySelectorAll('.box');
 2
 3const myObserver = new ResizeObserver(entries => {
 4  for (let entry of entries) {
 5    const infoEl = entry.target.querySelector('.info');
 6    const width = Math.floor(entry.contentRect.width);
 7    const height = Math.floor(entry.contentRect.height);
 8
 9    const angle = Math.floor(width / 360 * 100);
10    const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;
11
12    entry.target.style.background = gradient;
13
14    infoEl.innerText = `I'm ${width}px and ${height}px tall`;
15  }
16});
17
18boxes.forEach(box => {
19  myObserver.observe(box);
20});

注意,你还必须重复你可以观察的元素,并在每个元素上称呼观察

这是一个如何使用Resize Observer用于响应式设计的工作示例,但是,要知道浏览器支持这样的JavaScript功能很重要。

步骤 3 – 评估浏览器支持

Resize Observer的浏览器支持目前不太广泛,幸运的是,可以在中间使用的 polyfill(https://github.com/que-etc/resize-observer-polyfill)是基于MutationObserver API(https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)。

您可以访问 Can I Use resizeobserver?以跟踪主要浏览器中的此功能的支持。

结论

在本教程中,您可以了解Reserve Observer可以做什么,在您的JavaScript代码中使用它,并测试浏览器支持。

对于接下来的步骤,您可能有兴趣学习如何使用 JavaScript 框架来解决响应性设计,例如 ReactVue

Published At
Categories with 技术
Tagged with
comments powered by Disqus