在JS中使用Animate Animate to/trom高度自动 - 如何使其清洁和简洁?
我是编码的新手,并在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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论