Javascript 删除HTML5画布上先前绘制的线条
为了使用HTML5画布,我决定制作一个绘制模拟时钟面的应用程序。一切都很好,只是旧台词不会像我期望的那样被删除。我已经包含了下面的部分代码-DrawHands()每秒调用一次:Javascript 删除HTML5画布上先前绘制的线条,javascript,html,html5-canvas,Javascript,Html,Html5 Canvas,为了使用HTML5画布,我决定制作一个绘制模拟时钟面的应用程序。一切都很好,只是旧台词不会像我期望的那样被删除。我已经包含了下面的部分代码-DrawHands()每秒调用一次: var hoursPoint = new Object(); var minutesPoint = new Object(); var secondsPoint = new Object(); function drawHands() { var now = new Date(); drawLine(
var hoursPoint = new Object();
var minutesPoint = new Object();
var secondsPoint = new Object();
function drawHands()
{
var now = new Date();
drawLine(centerX, centerY, secondsPoint.X, secondsPoint.Y, "white", 1);
var seconds = now.getSeconds();
secondsPoint = getOtherEndOfLine(centerX, centerY, 2 * Math.PI / 60 * seconds, 0.75 * radius);
drawLine(centerX, centerY, secondsPoint.X, secondsPoint.Y, "black", 1);
drawLine(centerX, centerY, minutesPoint.X, minutesPoint.Y, "white", 3);
var minutes = now.getMinutes();
minutesPoint = getOtherEndOfLine(centerX, centerY, 2 * Math.PI / 60 * minutes, 0.75 * radius);
drawLine(centerX, centerY, minutesPoint.X, minutesPoint.Y, "black", 3);
drawLine(centerX, centerY, hoursPoint.X, hoursPoint.Y, "white", 3);
var hours = now.getHours();
if (hours >= 12) { hours -= 12; } // Hours are 0-11
hoursPoint = getOtherEndOfLine(centerX, centerY, (2 * Math.PI / 12 * hours) + (2 * Math.PI / 12 / 60 * minutes), 0.6 * radius);
drawLine(centerX, centerY, hoursPoint.X, hoursPoint.Y, "black", 3);
}
为了理解上述内容,有两个助手函数:
- 抽绳(x1、y1、x2、y2、颜色、厚度)
- getOtherEndOfLine(x,y,角度,长度)
<>我错过了什么原因?你应该考虑清理你的画布,重新画它,除非有性能或合成原因不。 你想要这样的东西:
//clear the canvas so we can draw a fresh clock
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
//redraw your clock here
/* ... */
你不能仅仅用白色重绘这一行,希望它能擦除旧的那一行,这是因为可能会有一些抗锯齿/出血。您还会注意到,由于这个原因,在一个像素和半个像素上绘制的水平直线看起来非常不同 当您执行白色“擦除”操作时,请尝试使用大约3或4倍的
线宽来绘制它们。这对你的案子应该有用
您还应先绘制所有白线,然后绘制所有黑线,以防它们相交。清除画布的快捷方法是设置宽度:
context.canvas.width = context.canvas.width;
你可以:
保存画布的状态
画出你不想要的东西
将画布恢复到保存状态以“擦除”它们
使用ImageData
可以非常轻松地完成此操作:
var canvas=document.querySelector('canvas'),
context=canvas.getContext('2d');
context.fillStyle='blue';
context.fillRect(0,0200200);
//在此处保存画布的状态
var imageData=context.getImageData(0,0,canvas.width,canvas.height);
//画一个红色的长方形,我们马上就把它去掉
context.fillStyle='red';
context.fillRect(50,50100100);
setTimeout(函数(){
//在我们绘制蓝色矩形后立即将画布返回到状态
putImageData(imageData,0,0);
}, 1000);代码>
我的解决方案是双缓冲:
var形状=
[{类型:“圆形”,x:50,y:50,radious:40,线宽:2,笔划样式:#FF0000,填充样式:#800000”}
,{类型:“矩形”,x:50,y:50,宽度:100,高度:100,线宽:2,笔划样式:“#00FF00”,填充样式:“#008000”}
,{类型:“线”,x1:75,y1:100,x2:170,y2:75,线宽:3,笔画样式:“#0000FF”}
];
步骤1();
setTimeout(函数(){
步骤2();
setTimeout(函数(){
步骤3();
}, 1000);
}, 1000);
函数step1(){
clearCanvas(“myCanvas1”);
forEach((sh)=>{drawShape('myCanvas1',sh);});
};
函数step2(){
clearCanvas(“myCanvas2”);
shapes.pop();
forEach((sh)=>{drawShape('myCanvas2',sh);});
showOtherCanvas(“myCanvas2”、“myCanvas1”);
};
函数step3(){
clearCanvas(“myCanvas1”);
shapes.pop();
forEach((sh)=>{drawShape('myCanvas1',sh);});
showOtherCanvas(“myCanvas1”、“myCanvas2”);
};
函数showOtherCanvas(cnv1、cnv2){
var c1=document.getElementById(cnv1);
var c2=document.getElementById(cnv2);
c1.风格['z-指数']=3;
c2.风格['z-指数']=1;
c1.风格['z-指数']=2;
}
函数clearCanvas(canvasID){
var canvas=document.getElementById(canvasID);
var ctx=canvas.getContext('2d');
ctx.fillStyle=“#FFFFFF”;
ctx.fillRect(0,0480320);
}
函数drawShape(canvasID,info){
开关(信息类型){
案例“线”:抽绳(canvasID,info);
案例“矩形”:drawRectangle(canvasID,info);
案例“圈”:drawCircle(canvasID,info);
}
}
功能抽绳(canvasID,info){
var canvas=document.getElementById(canvasID);
var ctx=canvas.getContext('2d');
ctx.strokeStyle=info.strokeStyle;
ctx.lineWidth=info.lineWidth
ctx.beginPath();
ctx.moveTo(信息x1,信息y1);
ctx.lineTo(info.x2,info.y2);
ctx.stroke();
}
函数drawRectangle(canvasID,info){
var canvas=document.getElementById(canvasID);
var ctx=canvas.getContext('2d');
ctx.fillStyle=info.fillStyle;
ctx.strokeStyle=info.strokeStyle;
ctx.lineWidth=info.lineWidth
ctx.fillRect(信息x、信息y、信息宽度、信息高度);
ctx.strokeRect(信息x、信息y、信息宽度、信息高度);
}
函数drawCircle(canvasID,info){
var canvas=document.getElementById(canvasID);
var ctx=canvas.getContext('2d');
ctx.fillStyle=info.fillStyle;
ctx.strokeStyle=info.strokeStyle;
ctx.lineWidth=info.lineWidth
ctx.beginPath();
ctx.arc(info.x,info.y,info.radious,0,2*Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(info.x,info.y,info.radious,0,2*Math.PI);
ctx.stroke();
}
如果想清除特定的线条或形状(如我所做的),而不是清除矩形区域,则设置ctx.globalCompositeOperation=“destination out”
——正如andrewmu对a的解决方案中所述——将使填充/笔划操作像橡皮擦工具一样工作。完成后,请记住将合成模式更改回原来的状态。有关详细信息,请参阅。不必总是完全清除画布。请参阅Simon Sarris使用getImageData/putImageData的回答,这允许您将图形恢复到图形的任何先前阶段。更正上述注释-应阅读mrmcgreg的回答。此方法比使用clearRectangle具有优势,因为您可以在图形的任何阶段获取图像数据并恢复到该级别,而clearRectangle将始终将您带回空白画布。因为这个原因,我投了更高的票……你可以选夏娃