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)
})();
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)
})();