我正在尝试用JavaScript设计正弦波,但是设计看起来很慢。主要瓶颈是清除画布的clearRect()
。
我该如何解决?
我也用ctx.fillRect(x, y,1,1)
绘制像素,但是当我使用clearRect(x, y,1,1)
清除时,它会留下一些足迹。相反,我必须执行clearRect(x, y,5,5)
才能进行适当的清除。可以解决什么问题?
/******************************/
var x = 0;
var sineval = [];
var offset = 0;
var animFlag;
function init() {
for(var i=0; i<=1000; ++i){
sineval[i] = Math.sin(i*Math.PI/180);
}
// Call the sineWave() function repeatedly every 1 microseconds
animFlag = setInterval(sineWave, 1);
//sineWave();
}
function sineWave()
{ //console.log('Drawing Sine');
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
}
for(x=0 ; x<1000 ;++x){
// Find the sine of the angle
//var i = x % 361;
var y = sineval[x+offset];
// If the sine value is positive, map it above y = 100 and change the colour to blue
if(y >= 0)
{
y = 100 - (y-0) * 70;
ctx.fillStyle = "green";
}
// If the sine value is negative, map it below y = 100 and change the colour to red
if( y < 0 )
{
y = 100 + (0-y) * 70;
ctx.fillStyle = "green";
}
// We will use the fillRect method to draw the actual wave. The length and breath of the
if(x == 0) ctx.clearRect(0,y-1,5,5);
else ctx.clearRect(x,y,5,5);
ctx.fillRect(x, y,1,1 /*Math.sin(x * Math.PI/180) * 5, Math.sin(x * Math.PI/180 * 5)*/);
}
offset = (offset > 360) ? 0 : ++offset ;
}
最佳答案
您需要重构一下代码:
将所有全局变量(例如canvas和context)移到循环函数之外
在循环内部,开始时清除整个画布,重新绘制正弦
使用requestAnimationFrame
代替setInterval
将fillRect()
替换为rect()
,并在内部for循环之外执行单个fill()
使用1毫秒的超时值可能会导致浏览器阻塞,或者至少使其运行速度显着降低。考虑到监视器更新仅每16.7ms发生一次,这当然会浪费周期。如果要降低/增加正弦的速度,可以改为降低/增加增量步长。
在本质上:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var sineval = [];
var offset = 0;
init();
function init() {
for (var i = 0; i <= 1000; ++i) {
sineval.push(Math.sin(i * Math.PI / 180));
}
// Call the sineWave() function
sineWave();
}
function sineWave() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.beginPath();
ctx.fillStyle = "green";
// draw positive part of sine wave here
for (var x = 0; x < 1000; x++) {
var y = sineval[x + offset];
if (y >= 0) {
y = 100 - (y - 0) * 70;
ctx.rect(x, y, 2, 2);
}
}
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "red";
// draw negative part of sine wave here
for (var x = 0; x < 1000; x++) {
var y = sineval[x + offset];
if (y < 0) {
y = 100 - (y - 0) * 70;
ctx.rect(x, y, 2, 2);
}
}
ctx.fill();
offset = (offset > 360) ? 0 : ++offset;
requestAnimationFrame(sineWave);
}
<canvas id="canvas" width=800 height=500></canvas>
当然,如果将脚本加载到
<head>
中,则需要将其包装在window.onload
块中,以便canvas元素可用。或者,如果您还没有的话,只需将脚本放在页面底部。关于javascript - 使canvas的clearRect()更快地工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27287732/