• ResizeObserver


    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="10%;height:10%"></canvas>
    <canvas style="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",
     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

  • 相关阅读:
    MIFARE Classic S50技术详解
    windown 使用python 自动切换网络
    CPU封装技术介绍
    openssl unicode编译以及VC++2015环境下的问题
    重新开启此博
    Mifare简介
    python全栈(中国历史天气可视化系统)
    cnblog优化指南
    Mysql日志详解
    scrapy抓取所有网站域名
  • 原文地址:https://www.cnblogs.com/thinkingthigh/p/11604021.html
Copyright © 2020-2023  润新知