我正在绘制一个渐渐增加的圆弧,然后变成圆形。完成动画(圆弧变成圆形)后,我想绘制另一个半径增大的圆,前一个圆持续存在,第二个动画继续。
绘制圆圈后,它会被淘汰掉,这是我不想要的东西并继续第二个动画。 完成后会出现一些不必要的动画。
我该怎么办?
mycode的:
setInterval(function(){
context.save();
context.clearRect(0,0,500,400);
context.beginPath();
increase_end_angle=increase_end_angle+11/500;
dynamic_end_angle=end_angle+increase_end_angle;
context.arc(x,y,radius,start_angle,dynamic_end_angle,false);
context.lineWidth=6;
context.lineCap = "round";
context.stroke();
context.restore();
if(dynamic_end_angle>3.5*Math.PI){ //condition for if circle completion
draw(radius+10);//draw from same origin and increasd radius
}
},66);
window.onload=draw(30);
UPDATE :我什么时候应该清除间隔以保存一些cpu周期?为什么动画会在第三圈减慢?
答案 0 :(得分:4)
您的代码中的代码段存在一些缺陷。
if(dynamic_end_angle>3.5*Math.PI){ //condition for if circle completion
draw(radius+10);//draw from same origin and increased radius
}
在完全绘制第一个圆圈后,对draw()
的递归调用将继续运行。这就是为什么性能会立即降低的原因。你需要以某种方式阻止它。
我做了一个简单的修复,你可以根据自己的喜好进行修饰。的 FIDDLE DEMO 强>
我的解决方法是删除context.clearRect(0, 0, 500, 400);
并将新的圆绘图逻辑更改为:
if (dynamic_end_angle > 3.5 * Math.PI) { //condition for if circle completion
increase_end_angle = 0; // this will prevent the draw() from triggering multiple times.
draw(radius + 10); //draw from same origin.
}
在此stackoverflow thread中,它提到如何使其更顺畅。你最好使用一些绘图框架,因为优化需要很多工作。
答案 1 :(得分:2)
首先,关于闪烁:您正在使用setInterval
而不是为下一个draw()
清除它。就是这样。
但我会使用completely different approach;只需检查自开始以来经过的时间,并使用循环绘制适当数量的圆圈。
var start = new Date().getTime();
var timePerCircle = 2;
var x = 190, y = 140;
function draw() {
requestAnimationFrame(draw);
g.clearRect(0, 0, canvas.width, canvas.height);
var t = (new Date().getTime() - start) / 1000;
var circles = t / timePerCircle;
var r = 30;
do {
g.beginPath();
g.arc(x, y, r, 0, Math.PI * 2 * Math.min(circles, 1));
g.stroke();
r += 10;
circles--;
} while(circles > 0);
}
draw();
答案 2 :(得分:1)
何时应该清除间隔以节省一些cpu周期?
最好不要使用间隔,原因有两个:
一种更好的方法是你可能已经知道使用requestAnimationFrame
。如果当前标签/窗口不活动,它可以减少CPU占用,并且能够同步监视并使用更少的资源,甚至更少。
为什么动画在第三圈减速?
您的绘图调用正在累积,这会减慢所有内容(setInterval
未清除)。
这是一种不同的方法。这是一种简化的方式,并使用差异绘画。
<强> ONLINE DEMO 强>
这里的主要绘制函数有两个参数,圆形索引和当前角度。圆半径存储在一个数组中:
...,
sa = 0, // start angle
ea = 359, // end angle
angle = sa, // current angle
oldAngle = sa, // old angle
steps = 2, // number of degrees per step
current = 0, // current circle index
circles = [70, 80, 90], // the circle radius
numOfCircles = circles.length, ...
该函数存储旧角度,仅在旧角度和新角度之间绘制一个新的段,添加0.5以补偿由于抗锯齿,舍入误差等引起的毛刺。
function drawCircle(circle, angle) {
angle *= deg2rad; // here: convert to radians
/// draw arc from old angle to new angle
ctx.beginPath();
ctx.arc(0, 0, circles[circle], oldAngle, angle + 0.5);
ctx.stroke();
/// store angle as old angle for next round
oldAngle = angle;
}
循环增加角度,如果大于或等于结束角度,它将重置角度并增加当前圆形计数器。当当前计数器到达最后一个圆圈时,循环结束:
function loop() {
angle += steps;
/// check angle and reset, move to next circle
if (angle >= ea - steps) {
current++;
angle = sa;
oldAngle = angle;
}
drawCircle(current, angle);
if (current < numOfCircles)
requestAnimationFrame(loop);
}