使用纯JS动画最大高度? [英] Animating max-height with pure JS?

查看:81
本文介绍了使用纯JS动画最大高度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为div的高度设置动画。这通常通过动画 max-height 属性在CSS中完成。

I want to animate the height of a div. This is normally done in CSS by animating the max-height property.

但是我需要在JS中执行此操作。 div中填充了频繁更改的动态内容,因此事先不知道实际高度。

However I need to do this in JS. The div is populated with dynamic content that changes frequently so the actual height is not known ahead of time.

这是一个jsfiddle: https://jsfiddle.net/vpknxuk8/

Here is a jsfiddle: https://jsfiddle.net/vpknxuk8/

var box = document.getElementById("box");
var button = document.getElementById("button");
var expanded = true;

button.addEventListener('click', function() {
    if (expanded) {
        box.style.maxHeight = 0;
        expanded = false;
    } else {
        box.style.maxHeight = "";
        expanded = true;
    }
});

#box {
  margin-top: 20px;
  border: 1px solid black;
  background-color: #4f88ff;
  width: 200px;
  transition: max-height 0.25s linear;
  overflow: hidden;
}

<button id="button">Click</button>

<div id="box">
  Hello World<br>
  This is dynamic content<br>
  The actual height won't be known ahead of time
</div>

该框应在高度0和默认高度之间转换,但由于某种原因它不是动画。

The box should transition between a height of 0 and its default height, but for some reason it isn't animating.

StackOverflow上此问题的唯一其他版本属于仅CSS解决方案或jQuery解决方案。

The only other versions of this question on StackOverflow pertain to CSS-only solutions or jQuery solutions.

推荐答案

不要 使用 max-height ......好吧,除非您想采用仅限CSS 草率解决方案,否则会产生延迟差距问题 - ..这就是为什么你在第一时间再次使用JS ...

Don't use max-height ...well, unless you want to adopt the CSS-only sloppy solution that generates delay gap issues - ...that's why you recurred to JS in the first place...

所以使用 height 过渡:高度而不是

so use height and transition: height instead

首先是演示,而不是一些代码说明:)

First a demo, than some code explanation :)

function slidetoggle() {

  var EL = document.getElementById( this.dataset.slidetoggle ),
      ch = EL.clientHeight,
      sh = EL.scrollHeight,
      isCollapsed = !ch,
      noHeightSet = !EL.style.height;

  EL.style.height = (isCollapsed || noHeightSet ? sh : 0) +"px";
  if(noHeightSet) return slidetoggle.bind(this)();

}


document.querySelector("[data-slidetoggle]").addEventListener('click', slidetoggle);

#box {
  overflow: hidden;
  margin-top: 20px;
  border: 1px solid #000;
  background-color: #4f88ff;
  width: 200px;
  transition: height 0.5s;
}

<button data-slidetoggle="box">Click</button>

<div id="box">
  Hello World<br>
  This is dynamic content<br>
  The actual height won't be<br>
  known ahead of time
</div>

如果我们不设置初始高度,CSS高度转换不起作用。

所以基本上点击 - 如果这样的高度不存在我们需要通过JS设置它。

设置这样的高度后,转换仍然无法工作,因为浏览器没有时间计算此类元素的框模型 转换来自

CSS height-transition cannot work if we don't set an initial height.
So basically on click - if such height does not exists we need to set it via JS.
After such height is set the transition will still not work because the browser did not had the time to calculate the box model of such element - to transition-from:

// Say the element is expanded.
// We need a height to transition-from
EL.height = calculatedHeight +"px";  // set CSS height to the calculated value
// Transition to 0px height....
EL.height = 0 +"px";
// NO DEAL. our element just snapped to 0 without transition

因此我们需要驻留到某种回调

一种常见(通常是不准确的)回调是 setTimeout

therefore we need to reside to some kind of callback.
One type of common (often inaccurate) callback is setTimeout

// Say the element is expanded.
// We need a height to transition-from
EL.height = calculatedHeight +"px";  // set CSS height to the calculated value
// Transition to 0px height giving the browser some ready-state hack
setTimeout(function() {
    // Eventually the box model will be calculated 
    EL.height = 0 +"px";
}, 0);   // <<< PROBLEM: Should we use 0 ? 10? 100? 1000? 
// and our element beautifully transitioned to 0 height.
// Eventually :(

创建此类回调的一种更好方法是绑定相同的设置初始元素高度后的函数:

One better way to create such callback is by binding the same function after we set the initial element height:

function slidetoggle() {

      // Get the target ID element by reading the data attribute
  var EL = document.getElementById( this.dataset.slidetoggle ),
      // Calculate clientHeight. Even if element has no CSS height set,
      // clientHeight will hold the actual calculated height
      ch = EL.clientHeight,
      // Get scrollHeight - if element is collapsed, scrollHeight is the 
      // height we'll animate-to.
      sh = EL.scrollHeight,
      // isCollapsed if ch === 0 (or in other words !ch)
      isCollapsed = !ch,
      // If no CSS height set set a flag.
      noHeightSet = !EL.style.height;

  // set height!! CSS transition will do the animation job for us.
  // Just... hey, if initially we did not specified any CSS height,
  // we first need to set it in order to see the transition actually happen!
  EL.style.height = (isCollapsed || noHeightSet ? sh : 0) +"px";
  // if that was the case, we need to bind another slidetoggle, since the first 
  // was just used to set the initial CSS height.
  if(noHeightSet) return slidetoggle.bind(this)();

}

// Assign a click handler to any [data-slidetoggle] element
document.querySelector("[data-slidetoggle]").addEventListener('click', slidetoggle);

提示:如果您需要填充,我的建议是将你的内容包装到另一个子框中 - 使用填充。

TIP: if you need paddings, my suggestion is to wrap your content into another child box - with paddings.

上面的代码是概念性的和最小的 - 有很多改进空间,但希望你有这个想法。

The code above is a conceptual and minimal - with lots of room for improvements, but hopefully you got the idea.

这篇关于使用纯JS动画最大高度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆