使用RaphaelJS,我修改了几个脚本来创建我想要组合的两个动画:
首先,将虚线绘制到坐标http://jsfiddle.net/jbirthler/CvhKx/2/
var canvas = Raphael('canvas_container', 322, 273);
var set = canvas.set(canvas.circle(110, 265, 7), canvas.circle(110, 7, 7), canvas.circle(7, 151, 7)).attr({
stroke: "none",
fill: "#666" });
var pathstr = "M 109 255 l 0 -245 l -103 141 l 265 0";
var path = dashline(canvas, pathstr, 4000, {
stroke: '#828282',
'stroke-dasharray': "--",
'stroke-linecap': "butt",
'stroke-width': 1,
'fill-opacity': 0 }, 1000);
function dashline(canvas, pathstr, duration, attr) {
var guide_path = canvas.path(pathstr).attr({
stroke: "none",
fill: "none"
});
var path = canvas.path(guide_path.getSubpath(0, 1)).attr(attr);
var total_length = guide_path.getTotalLength(guide_path);
var start_time = new Date().getTime();
var interval_length = 20;
var interval_id = setInterval(function() {
var elapsed_time = new Date().getTime() - start_time;
var this_length = elapsed_time / duration * total_length;
var subpathstr = guide_path.getSubpath(0, this_length);
attr.path = subpathstr;
path.animate(attr, interval_length);
}, interval_length);
return path;
};
并且,当到达坐标http://jsfiddle.net/jbirthler/KqjHh/1/
时,放宽路径并为圈子设置动画var canvas = Raphael("holder", 322, 273);
var set = canvas.set(canvas.circle(110, 265, 7),canvas.circle(110, 7, 7), canvas.circle(7, 151, 7)).attr({stroke:"none", fill: "#666"});
var c = canvas.circle(110, 265, 10).attr({stroke: "#ddd", "stroke-width": 4});
var fade = function (id) {
return function () {
set[id].attr({fill: "#fff", r: 12}).animate({fill: "#77bf00", r: 8}, 500);
};
};
var run = animateCirc();
function animateCirc() {
var easex = ">",
easey = ">";
c.stop().animate({
"0%": {cy: 265, easing: easey, callback: fade(0)},
"40%": {cy: 7, easing: easey, callback: fade(1)},
"60%": {cy: 151, easing: easey, callback: fade(2)},
"100%": {cy: 151, easing: easey, callback: fade(3)}
}, 3000).animate({
"0%": {cx: 110, easing: easex},
"40%": {cx: 110, easing: easex},
"60%": {cx: 7, easing: easex},
"100%": {cx: 300, easing: easex}
}, 3000);
return run;
};
我希望在虚线路径到达坐标时让圆圈具有动画效果。如果我能得到使用缓动的虚线路径,那将是一个加分,但大多数情况下,我只是想将两者合二为一。
我能够比我能编写自己的脚本更好地阅读javascript但是如果有人对如何分解虚线脚本和代码所采取的步骤有任何见解,那将非常有益我
我关于堆栈溢出的第一篇文章(是的,关于时间)希望我足够具体!
答案 0 :(得分:2)
我自己从未使用拉斐尔,但这是我发现的解决方案:
您的第一个动画在4(4000毫秒)秒内运行,您可以在此块中看到:
var path = dashline(canvas, pathstr, 4000, {
stroke: '#828282',
'stroke-dasharray': "--",
'stroke-linecap': "butt",
'stroke-width': 1,
'fill-opacity': 0
}, 1000);
下一步是识别渲染圈子的块,在这里你可以给它3秒钟,这可以通过将最后一个参数更改为4000来解决。接下来,你会注意到百分比。这些应该包括转换计算,将毫秒(4000)转换为每个动画点的百分比。
我看了动画点,但结尾代码看起来像这样:
function animateCirc() {
var easex = ">",
easey = ">";
c.stop().animate({
"0%": {cy: 265, easing: easey, callback: fade(0)},
"35%": {cy: 7, easing: easey, callback: fade(1)},
"60%": {cy: 151, easing: easey, callback: fade(2)},
"100%": {cy: 151, easing: easey, callback: fade(3)}
}, 4000).animate({
"0%": {cx: 110, easing: easex},
"35%": {cx: 110, easing: easex},
"60%": {cx: 7, easing: easex},
"100%": {cx: 300, easing: easex}
}, 4000);
return run;
};
您可以看到更新的(但不是100%同步)版本here。
var canvas = Raphael('canvas_container', 322, 273);
var set = canvas.set(canvas.circle(110, 265, 7), canvas.circle(110, 7, 7), canvas.circle(7, 151, 7)).attr({
stroke: "none",
fill: "#666"
});
var c = canvas.circle(110, 265, 10).attr({stroke: "#999", "stroke-width": 0});
var fade = function (id) {
return function () {
set[id].attr({fill: "#fff", r: 12}).animate({fill: "#77bf00", r: 8}, 500);
};
};
var pathstr = "M 109 255 l 0 -245 l -103 141 l 265 0";
var path = dashline(canvas, pathstr, 4000, {
stroke: '#828282',
'stroke-dasharray': "--",
'stroke-linecap': "butt",
'stroke-width': 1,
'fill-opacity': 0
}, 1000);
function dashline(canvas, pathstr, duration, attr) {
var guide_path = canvas.path(pathstr).attr({
stroke: "none",
fill: "none"
});
var path = canvas.path(guide_path.getSubpath(0, 1)).attr(attr);
var total_length = guide_path.getTotalLength(guide_path);
var start_time = new Date().getTime();
var interval_length = 20;
var interval_id = setInterval(function() {
var elapsed_time = new Date().getTime() - start_time;
var this_length = elapsed_time / duration * total_length;
var subpathstr = guide_path.getSubpath(0, this_length);
attr.path = subpathstr;
path.animate(attr, interval_length);
}, interval_length);
return path;
}
var run = animateCirc();
function animateCirc() {
var easex = ">",
easey = ">";
c.stop().animate({
"0%": {cy: 265, easing: easey, callback: fade(0)},
"35%": {cy: 7, easing: easey, callback: fade(1)},
"60%": {cy: 151, easing: easey, callback: fade(2)},
"100%": {cy: 151, easing: easey, callback: fade(3)}
}, 4000).animate({
"0%": {cx: 110, easing: easex},
"35%": {cx: 110, easing: easex},
"60%": {cx: 7, easing: easex},
"100%": {cx: 300, easing: easex}
}, 4000);
return run;
};
请注意,您可以使用Raphael,Easel,Kinetic或任何类型的Canvas / SVG渲染工具。
希望这有帮助!
答案 1 :(得分:1)
@ adamRenny's answer是简单的,非常简单的修改(他打败了我,我在提交他的时候仍在写我的答案)。但它似乎并不涉及真正的排队。必须手动计算时序以完全同步动画。但是,我在下面的回答将彻底更改代码。可能会或可能不会。
要做的第一件事是将虚线路径分成线(在您的情况下分成3个单独的线段)并在队列中设置它们的动画。可能会对单个(组合)路径进行排队,但我还没有尝试过。
为了简化这个过程,我提取了所有路径坐标,因为它们也被圆圈使用。这样我们就可以在循环中绘制所有元素。
var canvas = Raphael('canvas_container', 322, 273),
// here are the coordinates
points = [ [110,265], [110,7], [7,151], [300,151] ],
mCircle = canvas.circle(points[0][0],points[0][1],10).attr({stroke: "#999", "stroke-width": 4}),
path = [],
circles = [];
// draw the dots and (starting point of) lines
// note the lines are of 0 length so it's invisible, we only mark its starting point
for (var i = 0; i < points.length - 1; i++) {
circles[i] = canvas.circle(points[i][0],points[i][1],7).attr({stroke: "none", fill: "#666"});
path[i] = canvas.path('M'+points[i][0]+' '+points[i][1]).attr({
stroke: '#828282',
'stroke-dasharray': "--",
'stroke-linecap': "butt",
'stroke-width': 1,
'fill-opacity': 0
});
请注意,循环计数为points.length - 1
,因为最后一个坐标仅由移动圆使用,此时我们不会绘制任何内容。
然后我创建一个 factory 函数来生成每组动画
// function to generate each set of animation
var fn = function(index) {
var cPath = path[index], cCircle = circles[index],
x1 = points[index][0],
x2 = points[index+1][0],
y1 = points[index][1],
y2 = points[index+1][1];
return function(cb) {
cPath.animate({path:'M'+x1+' '+y1+' L'+x2+' '+y2},500,'easeOut');
mCircle.animate({cx:x2,cy:y2},500,'easeOut');
cCircle.attr({fill: "#fff", r: 12}).animate({fill: "#77bf00", r: 8}, 500, cb);
};
};
这是最难部分。管理动画队列。您实际上可以使用其他库,如jQuery Deferred。然而,经过几个小时的绝望,我决定编写自己的(非常简单的)队列系统。
// my custom Queue class
var Queue = function() {
this.actionCount = 0;
this.actions = [];
var self = this;
self._cb = function() {
if (++self.actionCount != self.actions.length) self.run();
};
};
Queue.prototype.run = function() {
this.actions[this.actionCount](this._cb);
};
Queue.prototype.add = function(fn) {
this.actions.push(fn);
};
在循环中,我们可以将每组生成的动画注册到队列中。并在循环结束后运行队列
for (var i = 0; i < points.length - 1; i++) {
circles[i] = canvas.circle(points[i][0],points[i][1],7).attr({stroke: "none", fill: "#666"});
path[i] = canvas.path(/*...*/);
queue.add(fn(i));
}
queue.run();
以下是jsFiddle
注意事项
points
数组中,其余内容自动完成 - jsFiddle fn
功能