ResizeObserver - 元素resize监听API

Motivation

响应式网站/Web应用程序 根据视口大小调整内容展示方式。这通常通过CSS和media查询来完成。当CSS表现不好我们会使用Javascript。

比如document.addEventListener("resize",fun)或者Element的onresize属性。通过监听window.resize事件,Javascript DOM操作与视口大小保持同步。

但你会意识到,这甚至不包括在窗口未被调整大小但元素改变其大小的情况。例如,添加新的子元素,设置元素的display样式none或类似的操作会改变元素,其兄弟或祖先的大小。

随着响应式Web应用程序的普及,对响应式组件的需求也会增加。这些组件也需要有对resize事件做出响应。不幸的是,Web平台目前不提供组件跟踪其大小的方法。

Current workarounds

一些应用程序实施自制的调整大小通知框架(例如:Polymer)。这种方法容易出错,难以维护,并且需要每个组件都实施自制方法。

其他人巧妙的通过可以代替调整事件的事件来调整内容(例如:<a href="https://github.com/wnr/element-resize-detector">element-resize-detector</a>)。目前最优秀的方法都使用类似的技巧:

在组件中插入一个绝对定位的子项,并且以发出滚动事件的方式制作子项,或者在父项大小更改时制作window.resize。

绝对定位的子项方法在ShadowDOM或React等框架中不起作用。

这些方法都不可取。它们在正确性,代码复杂性和性能方面都失败了。

在当今的Web平台上无法复制ResizeObserver功能。

这就是为什么ResizeObserver是一个有用的原始API。它对任何观察到的元素的大小的变化作出反应,与导致变化的原因无关。它还为您提供访问观察元素的新大小。

API

提到的“Observer”后缀的API共享一个简单的API设计。ResizeObserver也不例外。

您创建一个ResizeObserver 对象并将回调传递给构造函数。回调将被赋予一个数组ResizeOberverEntries- 每个观察元素一个条目 - 包含元素的大小

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`);
}
});

// Observe one or multiple elements
ro.observe(someElement);

Usage examples

以下是使用ResizeObserver在画布内绘制椭圆的示例。

<canvas style="width:10%;height:10%"></canvas>
<canvas style="width:20%;height:20%"></canvas>
function drawEllipse(entry) {
let ctx = entry.target.getContext(‘2d‘);
let rx = Math.floor(entry.contentRect.width / 2);
let ry = Math.floor(entry.contentRect.height / 2);
ctx.beginPath();
ctx.clearRect(0,0, entry.contentRect.width,entry.contentRect.height);
ctx.ellipse(rx, ry, rx, ry, 0, 0, 2 * Math.PI);
ctx.stroke();
}
// ResizeObserver delegates action to Element‘s handleResize method
let ro = new ResizeObserver( entries => {
for (let entry of entries) {
if (entry.target.handleResize)
entry.target.handleResize(entry);
}
});
// Set up observations
var canvases = document.querySelectorAll(‘canvas‘);
for (let canvas of canvases) {
canvas.handleResize = drawEllipse;
ro.observe(canvas);
}

内联框架可以检测其大小何时发生变化,并通知父窗口。

let ro = new ResizeObserver(entries => {
let idealSize = computeIdealSize();
window.parent.postMessage({
name: "iframeResize",
width: idealSize.width,
height: idealSize.height
}, ‘*‘);
});
ro.observe(document.body);

当新消息到达时,我们如何让聊天窗口滚动到底部?ResizeObserver解决方案将所有消息保存在不断增长的中div,并观察其大小。当新消息到达时,滚动到底部。
完整的例子 详细讨论了用户滚动的处理。

.chat {
overflow: scroll;
}
<div class="chat"> <!-- chat has the scrollbar -->
<div class="chat-text"> <!-- chat-text contains chat text -->
<div>jack: hi </div>
<div>jill: hi </div>
</div>
</div
let ro = new ResizeObserver( entries => {
for (let e of entries) {
let chat = e.target.parentNode;
chat.scrollTop = chat.scrollHeight - chat.clientHeight;
}
});
ro.observe(document.querySelector(‘.chat-text‘))

How

Performance

调整通知的大小可以有很高的频率。Observer API避免了事件捕获/泡泡的开销。

框架作者可以在ResizeObserver之上提供一个开发友好的“基于事件”的API,以避免注册太多的观察者。

Notice

通知传送顺序

当多个ResizeObservers注册时,通知应按注册顺序传送。

回调变更集应按注册顺序列出元素。

内联元素

内联元素不应该生成调整大小通知。

怎么样变换?

转换不会影响内容大小。他们不应该触发通知。

动画怎么样?

影响内容大小的动画应该会触发通知。

如果工作成本很高,开发人员可能会希望在动画期间跳过工作。

调整大小和可视性

当元素不可见时,内容大小变为0。这将生成一个调整大小的通知。开发人员将能够使用ResizeObserver观察可见性。

本文参考:

ResizeObserver: It’s Like document.onresize for Elements ----- https://developers.google.com/web/updates/2016/10/resizeobserver

WICG/ResizeObserver ----- https://github.com/WICG/ResizeObserver/blob/master/explainer.md

原文地址:https://www.cnblogs.com/CrossGod/p/ResizeObserver.html

时间: 2024-08-29 22:42:20

ResizeObserver - 元素resize监听API的相关文章

avalon子孙元素属性监听

HTML正文: <body ms-controller="ex"> <div class="ms-hover" ms-click="change('array')"> <div ms-repeat="array">{{el}}</div> </div> </body> Javascript操作代码: //对象数组子元素的监听 var vm=avalon.d

使用jQuery动态调整iframe高度,以及jQuery对dom元素的监听

大家可能会遇到子页面内容较多但iframe高度不够的情况.给iframe设置scrolling="no"的话子页面内容显示不全,不设置又会出现滚动条从而影响美观.当我们点击不同的菜单让iframe加载不同的html文件时,iframe的高度就需要做相应的调整. 主题思路:子页面加载完成后根据具体body的高度给iframe设置一个适合的高度 情况1:各个子页面内容与高度比较固定 <script> $(function(){ $("#Frame_Content&qu

jquery resize监听dom

添加如下代码即可(function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){i

dom元素改变监听

function domChange(domId, callback) { // select the target node var target = document.getElementById(domId); // create an observer instance var observer = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { callback();

监听div的resize

简单点说,就是: 在被监听的 div 中添加 iframe 标签,设置其高宽均为 100%: 在 iframe 的 resize 被触发时,则表明 div 的大小正在改变! 参考 Resize on div element 来源于stackoverflow 的回答 历程 日常开发中,遇到元素宽高改变时需要广播事件,由于此时窗口大小并未改变,故添加resize回调没用:而且该元素是因为某些dom隐藏,其高宽自适应所导致,而不是通过js设置,故 MutationObserver 也无法监听到.上网找

PIE SDK元素事件的监听

1功能简介 元素在操作的过程中,如添加,删除,选中等操作都需要有事件的监听,PIE SDK支持对元素操作事件的监听,下面对元素事件的监听进行介绍. 2功能实现说明 2.1.1 实现思路及原理说明 第一步 地图初始化进行窗体绑定,声明元素的监听事件 第二步 当触发监听事件时进行事件操作 2.1.2 核心接口与方法 接口/类 方法/属性 说明 IGraphicsContainer DeleteElement(IElement element) 删除指定元素 AddElement () 添加元素 Se

jQuery中的事件监听小记

一,一个事件监听的简便写法 最近发现一个jQuery中事件监听的简洁写法,感觉方便好多.同时也深感自己基础薄弱,好多东西竟然都模棱两可.因此,记录的同时,也对jQuery事件监听做个小的总结 原文链接:http://blog.csdn.net/luyinchangdejiqing/article/details/52413368 //鼠标拖拽触发动画 $(".item-wrap").on({ mousedown: function(e) { var el = $(this); var

Android之监听手机软键盘弹起与关闭

背景: 在很多App开发过程中需要在Activity中监听Android设备的软键盘弹起与关闭,但是Android似乎没有提供相关的的监听API给我们来调用,本文提供了一个可行的办法来监听软键盘的弹起与关闭. 预备知识: 在manifest文件中可以设置Activity的android:windowSoftInputMode属性,这个属性值常见的设置如下: android:windowSoftInputMode="stateAlwaysHidden|adjustPan" 那么这里值的含

移动端软键盘收起监听

在移动端进行表单操作时,时常需要监听键盘的收起,从而完成输入的处理.但浏览器并没有提供直接监听软键盘收起的接口,那该如何进行监听能?这里提供监听的兼容方案. 在安卓下,大部分浏览器在软键盘收起时,会触发resize事件,可以以此来监听:但ios操作系统并不会触发该事件,但大部分浏览器会触发表单的blur事件,所以可以以此为监听点.浏览器的软件盘监听状况如下表所示:   软键盘收起事件监听表 所以,通过监听onResize.onBlur可以实现移动端主流浏览器的软键盘收起操作:无法即时监听到的,可