我正在尝试构建此图形实用程序并使用 setInterval 来制作条形高度的动画。
我不知道如何使用 CSS Transition 实现这一点,但我也不确定使用 javascript 的效率如何。
虽然代码工作正常(至少在我这边),但它似乎非常占用 CPU。
let scaleFrag = new DocumentFragment();
for(let i = 100; i > -1; i-=5){
let div = document.createElement('div');
div.innerHTML = i;
scaleFrag.append(div);
}
document.getElementsByClassName('scale')[0].append(scaleFrag);
let graph = getComputedStyle(document.getElementsByClassName('graph')[0]);
let arblenth = Math.floor(Math.random()*50);
let array = [];
for(let i=0; i < arblenth; i++){
array.push(Math.floor(Math.random()*101));
}
let gw = parseInt(graph.width, 10);
let gh = parseInt(graph.height, 10);
gw = gw - 2*arblenth;
console.log(graph.width)
let barFrag = new DocumentFragment();
for(let i=0; i < array.length ; i++){
let cl = document.createElement('div');
cl.innerHTML = array[i];
cl.className = i%2 == 0 ? 'cl-o' : 'cl-e';
cl.style.width = gw + 'px';
barFrag.append(cl);
}
document.getElementsByClassName('graph')[0].append(barFrag);
function animateHeight(cls) {
let cl = document.getElementsByClassName(cls);
for(let i = 0; i < cl.length; i++){
let maxHeight = Math.floor(gh*(parseInt(cl[i].innerHTML)/100));
let h = 0;
let si = setInterval(() => {
if(h == maxHeight){
clearInterval(si);
}
cl[i].style.height = h++ + 'px';
},0.1)
}
}
animateHeight('cl-o');
animateHeight('cl-e');
html, body {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
font-family: sans-serif;
}
* {
box-sizing: border-box ;
}
body {
padding-top: 5vh;
}
.grid {
height: 90vh;
width: 70vw;
margin: 0 auto;
text-align: center;
box-shadow: 3px 4px 15px -2px rgba(49,41,41,0.9);
padding: 1rem;
display: flex;
justify-content: center;
align-items: center;
}
.scale {
width: 5%;
height: 90%;
display: flex;
flex-direction: column;
justify-content: space-between;
border-right: 1px solid grey;
}
.graph {
width: 90%;
height: 90%;
border-left: none;
display: flex;
align-items: flex-end;
}
.cl-o{
background-color: limegreen;
transition: height;
}
.cl-e{
background-color: lightslategray;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Portfolio</title>
<link rel='stylesheet' href="./style.css">
</head>
<body>
<div class="grid">
<div class="scale"></div>
<div class="graph">
</div>
</div>
</body>
</html>
我已经尝试了这 500 个高度随机设置的条形图,但它似乎仍然有效。 我应该这样做还是可以改进?
答案 0 :(得分:0)
在这种情况下最好使用 CSS 过渡。
这里是css的样子:
.cl-o{
background-color: limegreen;
height: 0px;
transition: 1s all;
}
.cl-e{
background-color: lightslategray;
height: 0px;
transition: 1s all;
}
所以这里的高度最初是 0,如果你立即在 JavaScript 中设置高度,没有动画(我只在 CodePen 上尝试过),所以你可以使用非常小的超时。这是新的 animateHeight 函数。
function animateHeight(cls) {
let cl = document.getElementsByClassName(cls);
for(let i = 0; i < cl.length; i++){
let maxHeight = Math.floor(gh*(parseInt(cl[i].innerHTML)/100));
setTimeout(() => {
cl[i].style.height = maxHeight + "px"
}, 10)
}
}
答案 1 :(得分:0)
我对代码做了一些小改动:
将代码重构为方法,因此更易于阅读。
将 document.getElementsByClassName
替换为 document.getElementById
和 document.querySelectorAll('#graph > div')
。
function createScaleFrag() {
let scaleFrag = new DocumentFragment();
for (let i = 100; i > -1; i -= 5) {
let div = document.createElement('div');
div.innerHTML = i;
scaleFrag.append(div);
}
return scaleFrag;
}
function createBarFrag() {
let arblenth = Math.floor(Math.random() * 50);
let array = [];
for (let i = 0; i < arblenth; i++) {
array.push(Math.floor(Math.random() * 101));
}
gw = gw - 2 * arblenth;
let barFrag = new DocumentFragment();
for (let i = 0; i < array.length; i++) {
let cl = document.createElement('div');
cl.innerHTML = array[i];
cl.className = i % 2 == 0 ? 'cl-o' : 'cl-e';
cl.style.width = gw + 'px';
barFrag.append(cl);
}
return barFrag;
}
document.getElementById('scale').append(createScaleFrag());
const grafElement = document.getElementById('graph');
let graph = getComputedStyle(grafElement);
let gw = parseInt(graph.width, 10);
let gh = parseInt(graph.height, 10);
grafElement.append(createBarFrag());
function animateHeight(cl) {
for (let i = 0; i < cl.length; i++) {
let maxHeight = Math.floor(gh * (parseInt(cl[i].innerHTML) / 100));
let h = 0;
let si = setInterval(() => {
if (h == maxHeight) {
clearInterval(si);
}
cl[i].style.height = h++ + 'px';
}, 0.1)
}
}
animateHeight(document.querySelectorAll('#graph > div'));
html,
body {
margin: 0px;
padding: 0px;
font-family: sans-serif;
}
* {
box-sizing: border-box;
}
.grid {
height: 90vh;
width: 70vw;
margin: 0 auto;
text-align: center;
box-shadow: 3px 4px 15px -2px rgba(49, 41, 41, 0.9);
padding: 1rem;
display: flex;
justify-content: center;
align-items: center;
}
#scale {
width: 5%;
height: 90%;
display: flex;
flex-direction: column;
justify-content: space-between;
border-right: 1px solid grey;
}
#graph {
width: 90%;
height: 90%;
border-left: none;
display: flex;
align-items: flex-end;
}
.cl-o {
background-color: limegreen;
transition: height;
}
.cl-e {
background-color: lightslategray;
}
<div class="grid">
<div id="scale"></div>
<div id="graph">
</div>
</div>
您的代码的问题在于,您执行的时间间隔与图中的列数一样多,(我认为)这会强制对每次更新进行重绘。你应该做的是做所有的计算,然后然后更新屏幕一次。您可以通过使用 requestAnimationFrame 来做到这一点。
我希望代码是不言自明的。
function createScaleFrag() {
let scaleFrag = new DocumentFragment();
for (let i = 100; i > -1; i -= 5) {
let div = document.createElement('div');
div.innerHTML = i;
scaleFrag.append(div);
}
return scaleFrag;
}
function createBarFrag() {
let arblenth = Math.floor(Math.random() * 50);
let array = [];
for (let i = 0; i < arblenth; i++) {
array.push(Math.floor(Math.random() * MAX_COLUMN_HEIGHT));
}
gw = gw - 2 * arblenth;
let barFrag = new DocumentFragment();
for (let i = 0; i < array.length; i++) {
let cl = document.createElement('div');
cl.innerHTML = array[i];
cl.className = i % 2 == 0 ? 'cl-o' : 'cl-e';
cl.style.width = gw + 'px';
barFrag.append(cl);
}
return barFrag;
}
const MAX_COLUMN_HEIGHT = 101;
document.getElementById('scale').append(createScaleFrag());
const grafElement = document.getElementById('graph');
let graph = getComputedStyle(grafElement);
let gw = parseInt(graph.width, 10);
let gh = parseInt(graph.height, 10);
grafElement.append(createBarFrag());
function animateHeight(cl) {
const ANIMATION_DURATION = 2000;
let start;
function updateHeight(timestamp) {
if (start === undefined) { start = timestamp; }
let elapsed = timestamp - start;
let progress = elapsed / ANIMATION_DURATION;
let globalHeight = progress * MAX_COLUMN_HEIGHT;
let maxHeight, shouldContinueGrow;
for (let i = 0; i < cl.length; i++) {
maxHeight = parseInt(cl[i].innerHTML);
shouldContinueGrow = globalHeight <= maxHeight;
if (shouldContinueGrow) {
cl[i].style.height = gh * progress + 'px';
}
}
if (elapsed < ANIMATION_DURATION) {
requestAnimationFrame(updateHeight);
}
}
requestAnimationFrame(updateHeight);
}
animateHeight(document.querySelectorAll('#graph > div'));
html,
body {
margin: 0px;
padding: 0px;
font-family: sans-serif;
}
* {
box-sizing: border-box;
}
.grid {
height: 90vh;
width: 70vw;
margin: 0 auto;
text-align: center;
box-shadow: 3px 4px 15px -2px rgba(49, 41, 41, 0.9);
padding: 1rem;
display: flex;
justify-content: center;
align-items: center;
}
#scale {
width: 5%;
height: 90%;
display: flex;
flex-direction: column;
justify-content: space-between;
border-right: 1px solid grey;
}
#graph {
width: 90%;
height: 90%;
border-left: none;
display: flex;
align-items: flex-end;
}
.cl-o {
background-color: limegreen;
transition: height;
}
.cl-e {
background-color: lightslategray;
}
<div class="grid">
<div id="scale"></div>
<div id="graph"></div>
</div>