我想创建带有动画条形图(宽度从0到最终大小)的简单条形图。
我从CSS转换开始,但是Opera和Chrome有时会出现问题。
现在,我尝试使用在这里看到的机制:
https://www.w3schools.com/w3css/w3css_progressbar.asp
使用JS。
我的“酒吧区域”很少:
<div id="chart-bars">
<div class="chart-bar-area">
<div class="chart-bar" data-percent="80" ></div>
</div>
<div class="chart-bar-area">
<div class="chart-bar" data-percent="60" ></div>
</div>
</div>
和JS代码可以在一个小节中正常工作,但是如果我尝试为所有循环实现该机制,则此脚本仅在最后一个小节中正确工作。其他条没有开槽。
下面的我的JS代码:
var foo = document.getElementById('chart-bars');
var width;
var elem;
var id;
for (var i = 0; i < foo.children.length; i++) {
elem = foo.children[i].children[0];
width = 1;
id = setInterval(frame, 10);
function frame() {
if (width >= elem.dataset.percent) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
}
}
}
有人可以帮助我吗?
谢谢
答案 0 :(得分:1)
这是因为i
的值超出了setInterval回调的范围,因为setInterval是window
方法,所以仅采用了迭代的最后一个值。因此,您必须使用这样的闭包或解决方案。
var foo = document.querySelectorAll(".chart-bar");
var width;
var elem;
var id;
for (var i = 0; i < foo.length; i++) {
var myElem = {
x: i
}
width = 1;
id = setInterval(function() {
if (width >= foo[this.x].dataset.percent) {
clearInterval(id);
} else {
width++;
foo[this.x].style.width = width + '%';
}
}.bind(myElem), 10);//Here you are binding that setInterval should run on the myElem object context not window context
}
答案 1 :(得分:1)
恭喜!今天将学习什么是“关闭”。
您遇到范围问题。之所以只能在最后一根柱上使用,是因为frame
函数只能看到elem
,因为它当前存在于范围内。也就是说,到您的setInterval
运行循环时,elem
将被牢固地设置为等于foo.children[foo.children.length - 1].children[0]
解决此问题的方法是创建一个新的闭包。也就是说,您可以“关闭”范围中的变量。
var foo = document.getElementById('chart-bars');
for (var i = 0; i < foo.children.length; i++) {
(function (elem, width) {
var id = setInterval(frame, 10);
function frame() {
if (width >= elem.dataset.percent) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
}
}
})(foo.children[i].children[0], 1)
}
现在,具体地说,这不是实现目标的完美方法,但是我以此方式编写它是为了保留尽可能多的代码,以减少特定示例的认知负担。 / p>
本质上,我正在做的是将代码包装在IIFE(立即调用函数表达式)中,该函数创建了一个新的作用域,其中您的elem
和width
变量固定在该函数的作用域内。
朝着正确方向迈出的又一步是将您的frame
函数拉出循环,使其仅创建一次,并接受elem
,width
作为其参数,和id
参数,但我将其留给读者练习:-)
答案 2 :(得分:0)
为什么不使用特定的jQuery库创建morrischart或chartjs之类的图表,它非常简单,而且效果很好 有文档 http://morrisjs.github.io/morris.js/ https://www.chartjs.org
答案 3 :(得分:0)
看起来像变量范围问题,您可以尝试这样的事情吗:
var foo = document.getElementById('chart-bars');
for (var i = 0; i < foo.children.length; i++) {
var elem = foo.children[i].children[0];
elem.style.width = '1%';
var id = setInterval(function() { frame(elem, id) }, 10);
}
function frame(elem, idInterval) {
var width = parseInt(elem.style.width);
if (width >= elem.dataset.percent) {
clearInterval(idInterval);
} else {
width++;
elem.style.width = width + '%';
}
}
基本上,在每个循环中删除之前的elem,width和id变量之前,因为它们是在for循环之外声明的。因此,行为很奇怪。
编辑:将框架功能放在外面,这样更清晰。
Edit2:由于不需要框架功能而删除宽度。
答案 4 :(得分:0)
非常感谢, AB Udhay的示例效果很好!但是....
当我有HTML时:
<div id="chart-bars">
<div class="chart-bar-area">
<div class="chart-bar" data-percent="80" data-toggle="tooltip" title="Hooray!" data-placement="right"></div><div class="chart-bar-percent"> 0%</div>
</div>
<div class="chart-bar-area">
<div class="chart-bar" data-percent="60" data-toggle="tooltip" title="Hooray!" data-placement="right"></div><div class="chart-bar-percent"> 0%</div>
</div>
<div class="chart-bar-area">
<div class="chart-bar" data-percent="30" data-toggle="tooltip" title="Hooray!" data-placement="right"></div><div class="chart-bar-percent"> 0%</div>
</div>
<div class="chart-bar-area">
<div class="chart-bar" data-percent="40" data-toggle="tooltip" title="Hooray!" data-placement="right"></div><div class="chart-bar-percent"> 0%</div>
</div>
<div class="chart-bar-area">
<div class="chart-bar" data-percent="10" data-toggle="tooltip" title="Hooray!" data-placement="right"></div><div class="chart-bar-percent"> 0%</div>
</div>
<div class="chart-bar-area">
<div class="chart-bar" data-percent="1" data-toggle="tooltip" title="Hooray!" data-placement="right"></div><div class="chart-bar-percent"> 0%</div>
</div>
</div>
像这样的JS:
var foo = document.querySelectorAll(".chart-bar");
var width;
var elem;
var id;
for (var i = 0; i < foo.length; i++) {
var myElem = {
x: i
}
width = 0;
id = setInterval(function() {
if (width >= foo[this.x].dataset.percent) {
clearInterval(id);
} else {
width++;
foo[this.x].style.width = width + '%';
foo[this.x].nextSibling.innerHTML = width + '%';
}
}.bind(myElem), 1);
}
然后我给出如下所示的随机结果...
为什么?