我有短代码,在这些轨道上绘制圆(轨道)点(卫星)。卫星在轨道上移动。事实上代码并不是我的,但我被要求解决问题。
根据chrome和firefox中的分析器,函数drawSatellite
吃了50%-100%的cpu,我想知道原因。
Canvas与您的窗口相同(1920x1080)。有大约160个轨道(随着时间页增加在线)。
这是drawSatellite
:
OrbitBackground.prototype.drawSatellite = function(ctx, satellite) {
ctx.fillStyle = satellite.satellite.fill;
ctx.beginPath();
if (++satellite.satellite.angularPosition == 360)
satellite.satellite.angularPosition = 0;
// 1 FPS = 60 calls => 180 / 6 (6-times faster @ 60 FPS) = 30
var radians = satellite.satellite.angularPosition * Math.PI / 30 / satellite.rps;
if (satellite.backward)
radians = -radians;
ctx.arc(
satellite.satellite.x + satellite.orbit.radius * Math.cos(radians),
satellite.satellite.y + satellite.orbit.radius * Math.sin(radians),
satellite.satellite.radius,
0,
Math.PI*2,
true
);
ctx.closePath();
ctx.fill();
};
调用它的函数:
OrbitBackground.prototype.drawFrame = function() {
if (this.running)
requestAnimationFrame(this.drawFrame.bind(this));
this.dynamicStageCtx.clearRect(0, 0, this.pageWidth, this.pageHeight);
for (var i=0; i < this.orbits.length; i++) {
this.drawSatellite(this.dynamicStageCtx, this.orbits[i]);
}
};
答案 0 :(得分:4)
你这样做:
Loop:
set fill style
begin path
make path
end path
fill
这样做会更快:
set fill style (just once, before loop)
begin path (just one path, with loop-number of subpaths)
Loop:
moveTo (start of subpath)
make path
close path
fill (just once, after loop)
但这需要每个卫星上的填充样式相同。如果只有几种颜色,你可以尝试按颜色将它们捆在一起。
另请注意,计算余弦和正弦的速度很慢(所有三角函数和平方根调用都很慢),如果你可以避免使用它们,那么你会更好。
画布的大小(像素数)也很重要。考虑将画布制作为半尺寸或四分之一尺寸(960x540或480x270)并使用CSS进行缩放。
答案 1 :(得分:3)
可能有问题:
我在ctx.arc命令之前没有看到ctx.beginPath。
如果没有ctx.beginPath,您之前的所有弧都将与当前弧一起重绘。
小优化
将Math.PI * 2分配给变量,因为它经常使用
var PI2=Math.PI*2;
如何消除代码中最慢的部分(Math.cos和Math.sin)。
由于您的节点正在重复轨道运行,因此您可以预先计算所有未翻译的[x,y]以获得完整的轨道。
var statellite.orbitTrig=[];
for(var i=0;i<360;i++){
var radians=PI2/360*i;
var x=satellite.orbit.radius * Math.cos(radians)
var y=satellite.orbit.radius * Math.sin(radians)
satellite.orbitTrig.push({x:x,y:y});
}
然后您可以参考动画循环中的预先计算的值。
var trig=satellite.orbitTrig[satellite.satellite.angularPosition];
var x=satellite.satellite.x + trig.x;
var y=satellite.satellite.y + trig.y;
ctx.beginPath();
ctx.arc(x,y,satellite.satellite.radius,0,PI2);
ctx.closePath();
ctx.fill();