【问题标题】:Ignore transitions when measuring an elements dimensions测量元素尺寸时忽略过渡
【发布时间】:2014-06-17 01:25:30
【问题描述】:

有没有一种优雅的方法可以预测元素的尺寸在元素转换完成后完成?

例子:

HTML:

<div id="demo">...</div>

CSS:

#demo {
  max-height: 0;
  overflow:hidden;
  transition: 2s max-height;
}

#demo.expand {
  max-height: 1000px;
}

JS:

 var demo = document.getElementById('demo');
 demo.className = 'expand';
 // Unfortunately the result will be 0px 
 // because the current height is measured
 alert(demo.offsetHeight);

演示:

codepen

【问题讨论】:

  • 我并不完全清楚您要做什么。为什么max-height
  • 是的,我知道这是一种解决方法,但您实际上想做什么?所以,我想我是在问“你为什么需要高度?”
  • 我想知道这是否是 element.getBoundingClientRect() 的工作。你能在我们可以测试的地方做一个小提琴吗?
  • 我想我现在明白你的问题了。我猜你不想“测量尺寸”,但你想在元素放置在屏幕上之前“预测尺寸”。对吗?
  • 好的,所以这会有点困难 - 你必须知道 div 的特性,做一些计算,并希望 div 在位置时不会改变大小.昨晚我正在考虑在很短的时间内打开 div(在页面的位置或不同的较远部分),进行测量,然后在隐藏它后移动到正确的位置。也许如果您在加载之前告诉我们为什么需要测量,我们或许可以想出不同的策略。

标签: javascript jquery html css


【解决方案1】:

有没有一种优雅的方法来衡量元素转换完成后元素的尺寸?

您可以使用transitionend 事件在过渡完成后查看元素的高度:

$('#demo').on("transitionend", function(e) { 
    console.log($('#demo').height());
}).addClass('expand');

这将为您提供 20 的值,我认为这就是您要查找的内容?
jsFiddle

【讨论】:

  • 很遗憾我需要动画完成前的信息。
  • 那么你必须在之前首先限制元素的高度——即,删除max-heightoverflow,然后检查元素方面。如果在执行此操作时无法显示元素内容,请在屏幕外执行此操作(例如使用绝对定位)。
【解决方案2】:

您可以通过scrollHeightscrollWidth 属性查看请求的内容渲染高度/宽度。

例如尝试将alert(demo.scrollHeight); 添加到 JS 窗格中。

【讨论】:

  • 我找不到任何表明scrollHeight 返回transition-invariant 值的信息。 scrollHeight 上的 MDN 文章根本没有提到转换。
【解决方案3】:

BlakeGru 的回答非常适合 OP 的问题,但不适用于我遇到的类似问题。为了完整性,如果它对其他人有用,这里有一个通用策略,用于在任何转换完成后,在所述转换实际开始之前找到元素将具有的最终尺寸。

此示例更改元素的宽度(带有过渡)并获取过渡完成后元素将具有的高度(由内容自动确定)。

function resize(element, endingWidth) {
  // First, save any set transitions for later.
  var transitions = window.getComputedStyle(element).transition;
  // Now, disable any transitions so that our calculations will work properly.
  element.style.transition = 'none';
  // Get our current width.
  var startingWidth = element.offsetWidth + 'px';

  // Set a new width.
  element.style.width = endingWidth;
  // And get the element height. Because there are no transitions set, this will be the same height as at the end of any transitions.
  var endingHeight = element.offsetHeight;

  /*
   * Now do whatever calculations we want with the ending height.
   */
  alert(endingHeight);

  // Set the element's width back to when we started, so we have a start point for our transition.
  element.style.width = startingWidth;
  // Force the browser to recalculate the element's dimensions. This seemingly pointless call is absolutely critical for the transition to work.
  element.offsetWidth;

  // Now, we can set our desired transitions and the ending width again, and we're away.
  element.style.transition = transitions;
  element.style.width = endingWidth;
}

Fiddle

大体思路是:

  • 删除所有转换。
  • 对元素的尺寸进行所需的更改。
  • 测量所需的最终尺寸。
  • 将元素的尺寸重置为初始值。
  • 恢复过渡。
  • 再次进行所需的更改。

【讨论】:

  • 您的解决方案非常缓慢,因为您触发了多次渲染回流。
  • 不能争辩;这个解决方案绝对是浪费。虽然我会说我在测试中没有看到屏幕上的明显性能影响。
  • 感谢您在恢复过渡之前的强制回流!
【解决方案4】:

如果我试图做这样的事情,我只会得到包含元素的高度。如果那是窗户,那就去吧。这应该让您每次在动画之前找到您要寻找的数字。

【讨论】:

    【解决方案5】:

    您可以将#demo 放入带有height: 0 的包装器中,这将允许计算自动高度,然后转换包装器以匹配#demo 的高度,然后在转换结束时,将包装器高度更改为自动所以它会像平常一样流动。

    Here is a JSFiddle to demonstrate.

    (感谢@CBroe 我不知道的on("transitionend", function)

    HTML

    <div id="demoWrapper">
        <div id="demo">
            // content
        </div>
    </div>
    

    CSS

    #demoWrapper {
        height: 0;
        overflow:hidden;
        background:red;
        transition: 2s height;
    }
    
    #demo {
        max-height: 1000px;
    }
    

    JavaScript

    alert("Calculated height of #demo before transition: " + $('#demo').height());
    
    $('#demoWrapper').height($('#demo').height()).on("transitionend", function(e) {
        $('#demoWrapper').css('height', 'auto');
    });
    

    【讨论】:

    • transitionend 为时已晚 - 在动画开始之前我需要正确的高度
    • @Jantimon 如果您查看演示,您会看到它告诉您#demo 过渡之前的高度。我使用transitionend#demoWrapper 的高度更改回auto,因此它会像#demo 没有包装器的情况下一样对调整窗口大小作出反应。
    • 现在我明白了——这个技巧真的很酷,但它需要我更改标记和 css 才能获得高度
    • 如果您无法更改 HTML 中的标记,您可以在 JavaScript 中进行。只需将内容移动到新的div 并将其放在父级中即可。 Here is a new fiddle.
    【解决方案6】:

    内容也有一个高度,如果它被包装成一个标签,你可以很容易地检索它。

    这里的文字用&lt;p&gt; 包裹,这对我来说似乎很公平:DEMO

    【讨论】:

      猜你喜欢
      • 2019-01-13
      • 2017-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      相关资源
      最近更新 更多