在JS中使用Animate Animate to/trom高度自动 - 如何使其清洁和简洁?

发布于 2025-02-03 00:11:27 字数 4830 浏览 1 评论 0原文

我是编码的新手,并在JS/CSS/HTML中发现了此问题,并从“自动”高度或宽度中进行了动画。我想出了一种解决方案,我认为该解决方案按预期工作!但是我不确定这是否是一个非常优雅的解决方案。有人对如何使它更简洁/更简单有想法吗?

这是笔:

https://codepen.io/wyrez/wyrez/pen/pen/ojqqlgw

// --------- IMPORTANT BITS:

let originalHeight = "";
let originalPadding = "";
let expanded = true;

function resizeBox(elementID, minHeight, transitionTime){
  const expandableDiv = document.getElementById(elementID);
  
  if (expandableDiv !== null){
    const currentHeight = getElementHeight(expandableDiv)
    
    if (expanded) {
      originalHeight = currentHeight;
      originalPadding = getComputedStyle(expandableDiv).padding;

      // Set the transition time
      expandableDiv.style.setProperty("--transition-time", transitionTime+"s");

      // Set the height from "auto" to the exact pixel height.
      expandableDiv.style.height = currentHeight;

      // Setting this to start 1ms later ensured that it animated smoothly on my machine.
      setTimeout(()=> {
        expandableDiv.style.padding = minHeight > 0 ? originalPadding : "0px";
        expandableDiv.style.height = minHeight+"px";
      }, 1);

      expanded = false;
    
   } else if (!expanded){
     // Quickly set the original padding before the rest of the animation happens.
     expandableDiv.style.setProperty("--transition-time", "0.1s");
     expandableDiv.style.padding = originalPadding;
     expandableDiv.style.setProperty("--transition-time", transitionTime+"s");
     
      // Set the height to the original height before animation.
      expandableDiv.style.height = originalHeight;

      // Set the height to auto after the transition is finished. Without this timeout,
      // the height is set to 'auto' before the transition is complete, forcing 
      // the animation to 'snap back' to the original position.
      // The -100 accommodates for the 0.1s from setting the original padding above.
      // This way the total transition time is stil as desired.
      setTimeout(() => {
        expandableDiv.style.height = "auto";
      }, (transitionTime*1000)-100)

      expanded = true;
    }
  
  }
}

 function getElementHeight(elem){
    const paddingDeduction = Number(getComputedStyle(elem).padding.split("px")[0])*2;
    return (elem.clientHeight - paddingDeduction) + "px";  
  }

// --------- UNIMPORTANT BITS:

function setBoxText(){
  document.getElementById("boxText").innerHTML = document.getElementById("textForTheBox").value;
}

function boxTransition(){
  // Get values from inputs
  let minHeight = document.getElementById("minHeight").value;
  let animationTime = document.getElementById("animationTime").value;
  
  // Make sure they're numbers
  try {
    minHeight = parseFloat(document.getElementById("minHeight").value);
    animationTime = parseFloat(document.getElementById("animationTime").value);
  } catch (e){
    
  }
  
  // Correct them if they're not numbers
  if (isNaN(minHeight) || isNaN(animationTime)){
    alert("minHeight or animationTime was not a number. Setting values to 0 and 0.5");
    minHeight = 0;
    animationTime = 0.5;
  }
  
  // Start the box transition
  resizeBox("myBox", minHeight, animationTime);
}

CSS:

.box1{
   /* Important bits: */
  height: auto;
  transition: all var(--transition-time, 0.5s);
  padding: 2px;

  /* Unimportant bits: */
  display: flex; 
  flex-direction: column;
  text-align: center;
  margin: 1em;
  color: white;
  background-color: #B43E8F;
  width: 200px;
  border-radius: 30px;
  overflow:hidden;
}

HTML:

<div className="main">
  <center>
  <div><h1>How to animate to/from auto height.</h1></div>
    <div class="box1" id="myBox">
      <h2>Resizable Box!</h2>
      <div id="boxText">
      Hi! How's it going?
        Here's a box that you can minimise to any height from auto, and will eventually grow back to its original height (and set to auto) after re-expanding.
      </div>
    </div>
    <button onClick="boxTransition()">Shrink/Expand</button>
    <br>
    <br>
     Type in some text to change the size of the box while it's expanded (auto height).
    <br>
    <textarea id="textForTheBox" cols="50" rows="4"></textarea> 
  <br>
  <button onClick="setBoxText()">Update Box Text</button>
  <br>
    <div>
      Height to shrink to in px (eg 30): <input type="text" id="minHeight" value="30"></input>
      <br>
      Animation time (in seconds): <input type="text" id="animationTime" value="0.5"></input>
    </div>
</div>

I'm new to coding, and found this issue with animating to and from 'auto' height or width in js/css/html. I came up with a solution which I believe works as intended! But I'm not sure if it's a very elegant solution. Does anyone have ideas on how I can make this more concise/simpler?

Here's the pen:
https://codepen.io/WyreZ/pen/OJQQLgw

Otherwise, here's the code:

Javascript:

// --------- IMPORTANT BITS:

let originalHeight = "";
let originalPadding = "";
let expanded = true;

function resizeBox(elementID, minHeight, transitionTime){
  const expandableDiv = document.getElementById(elementID);
  
  if (expandableDiv !== null){
    const currentHeight = getElementHeight(expandableDiv)
    
    if (expanded) {
      originalHeight = currentHeight;
      originalPadding = getComputedStyle(expandableDiv).padding;

      // Set the transition time
      expandableDiv.style.setProperty("--transition-time", transitionTime+"s");

      // Set the height from "auto" to the exact pixel height.
      expandableDiv.style.height = currentHeight;

      // Setting this to start 1ms later ensured that it animated smoothly on my machine.
      setTimeout(()=> {
        expandableDiv.style.padding = minHeight > 0 ? originalPadding : "0px";
        expandableDiv.style.height = minHeight+"px";
      }, 1);

      expanded = false;
    
   } else if (!expanded){
     // Quickly set the original padding before the rest of the animation happens.
     expandableDiv.style.setProperty("--transition-time", "0.1s");
     expandableDiv.style.padding = originalPadding;
     expandableDiv.style.setProperty("--transition-time", transitionTime+"s");
     
      // Set the height to the original height before animation.
      expandableDiv.style.height = originalHeight;

      // Set the height to auto after the transition is finished. Without this timeout,
      // the height is set to 'auto' before the transition is complete, forcing 
      // the animation to 'snap back' to the original position.
      // The -100 accommodates for the 0.1s from setting the original padding above.
      // This way the total transition time is stil as desired.
      setTimeout(() => {
        expandableDiv.style.height = "auto";
      }, (transitionTime*1000)-100)

      expanded = true;
    }
  
  }
}

 function getElementHeight(elem){
    const paddingDeduction = Number(getComputedStyle(elem).padding.split("px")[0])*2;
    return (elem.clientHeight - paddingDeduction) + "px";  
  }

// --------- UNIMPORTANT BITS:

function setBoxText(){
  document.getElementById("boxText").innerHTML = document.getElementById("textForTheBox").value;
}

function boxTransition(){
  // Get values from inputs
  let minHeight = document.getElementById("minHeight").value;
  let animationTime = document.getElementById("animationTime").value;
  
  // Make sure they're numbers
  try {
    minHeight = parseFloat(document.getElementById("minHeight").value);
    animationTime = parseFloat(document.getElementById("animationTime").value);
  } catch (e){
    
  }
  
  // Correct them if they're not numbers
  if (isNaN(minHeight) || isNaN(animationTime)){
    alert("minHeight or animationTime was not a number. Setting values to 0 and 0.5");
    minHeight = 0;
    animationTime = 0.5;
  }
  
  // Start the box transition
  resizeBox("myBox", minHeight, animationTime);
}

CSS:

.box1{
   /* Important bits: */
  height: auto;
  transition: all var(--transition-time, 0.5s);
  padding: 2px;

  /* Unimportant bits: */
  display: flex; 
  flex-direction: column;
  text-align: center;
  margin: 1em;
  color: white;
  background-color: #B43E8F;
  width: 200px;
  border-radius: 30px;
  overflow:hidden;
}

HTML:

<div className="main">
  <center>
  <div><h1>How to animate to/from auto height.</h1></div>
    <div class="box1" id="myBox">
      <h2>Resizable Box!</h2>
      <div id="boxText">
      Hi! How's it going?
        Here's a box that you can minimise to any height from auto, and will eventually grow back to its original height (and set to auto) after re-expanding.
      </div>
    </div>
    <button onClick="boxTransition()">Shrink/Expand</button>
    <br>
    <br>
     Type in some text to change the size of the box while it's expanded (auto height).
    <br>
    <textarea id="textForTheBox" cols="50" rows="4"></textarea> 
  <br>
  <button onClick="setBoxText()">Update Box Text</button>
  <br>
    <div>
      Height to shrink to in px (eg 30): <input type="text" id="minHeight" value="30"></input>
      <br>
      Animation time (in seconds): <input type="text" id="animationTime" value="0.5"></input>
    </div>
</div>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文