Snap.svg & JavaScript:在 For 循环内创建形状并在延迟时为每个形状设置动画

Snap.svg & JavaScript: Creating Shapes and Animating Each on Delay inside a For Loop

first-time/long-time(庸医,庸医)。

我有点沮丧,几乎被难住了,这个谜语我在 Snap.svg 中无法完全解决。这可能是一个疏忽,我会因为错过而自责,但我现在没有看到它。

我有从 DOM 元素中提取并存储到一系列数组中的 x 和 y 数据,根据某些列中的某些值进行过滤,并最终在 js 中创建 ChartLine 对象的多个实例.基本上,它按数量对特定列进行排序,从 RainbowVis.js 对象中为每个值的行分配颜色,将每行中的所有相关值推送到 y 的数组中,并在折线图上绘制一条路径,其中 y 是value 和 x 是 For 循环中稳定增加的整数。

我目前在 draw() 函数中所做的是:对于每个相关列,使用对象的 x 和 y 变量的变量 "dot" 创建一个 <circle>,分配属性,在四分之一秒内将半径从 0 设置为 8,并将 i 的 x 和 y 值添加到要在 <path> 中使用的字符串,我在 [=] 之后创建16=] 循环。然后我为路径等设置动画

没有 setTimeout(),效果很好。圆圈和路径都在加载时同时动画。但是,我想为每个 .animate 添加一个延迟,在每次迭代中增加 polyDelayInterval 的毫秒数,因此每个 "dot" 都会在行到达时进行动画处理。至少,我想在路径完成动画后为所有 "dots" 设置动画。

问题是,无论我到目前为止尝试了什么,我只能得到最后一组 "dots" (每行的最高 x 值)来制作动画;其余留在 r:0。我在这里和其他地方都读过几篇有点相似的文章;我在 Snap.svg 的网站上搜索了文档。我只是找不到我做错了什么。提前致谢!

var svgMFLC = Snap('svg#ElementID');


function ChartLine(x, y, color, row) {  
  this.x = x;
  this.y = y;
  this.color = color;
  this.row = row;
  var propNames = Object.keys(this.row);
  var yAdjust;
  var resetX = this.x;

  for (var i = 0; i < propNames.length; i++) { //  get only the calculated score columns and their values
    if (propNames[i].toLowerCase().includes(calcKeyword)) {
      yAdjustedToChartArea = chartBottom - (this.row[propNames[i]] * yInterval);
      this.y.push(yAdjustedToChartArea);    //  returns the value of that score column and pushes it to the y array
    }
  }

  this.draw = function () {
    var points = "M";   //  the string that will determine the coordinates of each line
    var dotShadow = svgMFLC.filter(Snap.filter.shadow(0, 0, 2, "#000000", 0.4));
    var polyTime = 1500;    //  in milliseconds
    var dot;
    var polyDelayInterval = polyTime / (semesterCols.length - 1);
    for (var i = 0; i < semesterCols.length; i++) { //  for each data point, create a "dot"
      dot = svgMFLC.circle(this.x, this.y[i], 0);
      dot.attr({
        fill: this.color,
        stroke: "none",
        filter: dotShadow,
        class: "chartPointMFLC"
      });
      setTimeout(function () {
        dot.animate({ r: 8 }, 250, mina.easeout);
      }, polyDelayInterval * i);
      points += this.x + " " + this.y[i] + " L";
      this.x = this.x + xInterval;
    }
    points = points.slice(0, -2);   //  take away the excessive " L" from the end of the points string
    var poly = svgMFLC.path(points);    
    var polyLength = poly.getTotalLength(); 
    poly.attr({
      fill: "none",
      stroke: this.color,
      class: "chartLineMFLC",
      strokeDasharray: polyLength + " " + polyLength, //  setting the strokeDash attributes will help create the "drawing the line" effect when animated
      strokeDashoffset: polyLength
    });
    poly.animate({ strokeDashoffset: 0.00 }, polyTime);
    this.x = resetX;
  }
}

如果没有完整的代码进行测试,我无法提出经过测试的解决方案,但问题几乎可以肯定,您至少需要为 'dot' 元素获取一个闭包。

所以这一行...

setTimeout(function () {
    dot.animate({ r: 8 }, 250, mina.easeout);
}, polyDelayInterval * i);

调用该函数时,'dot' 将是循环中的最后一个 'dot'。所以你需要创建一个闭包(create functional scope for dot)。

有点像...

(function() {
    var laterDot = dot;
    setTimeout(function () {
        laterDot.animate({ r: 8 }, 250, mina.easeout);
    }, polyDelayInterval * i)
})();