JS动态更改divs循环宽度

时间:2018-07-12 13:36:57

标签: javascript css charts setinterval

我想创建带有动画条形图(宽度从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 + '%'; 
      }
    }

  }

有人可以帮助我吗?

谢谢

5 个答案:

答案 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(立即调用函数表达式)中,该函数创建了一个新的作用域,其中您的elemwidth变量固定在该函数的作用域内。

朝着正确方向迈出的又一步是将您的frame函数拉出循环,使其仅创建一次,并接受elemwidth作为其参数,和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); 
   }

然后我给出如下所示的随机结果...

enter image description here

为什么?