Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 删除HTML5画布上先前绘制的线条_Javascript_Html_Html5 Canvas - Fatal编程技术网

Javascript 删除HTML5画布上先前绘制的线条

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(

为了使用HTML5画布,我决定制作一个绘制模拟时钟面的应用程序。一切都很好,只是旧台词不会像我期望的那样被删除。我已经包含了下面的部分代码-DrawHands()每秒调用一次:

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将始终将您带回空白画布。因为这个原因,我投了更高的票……你可以选夏娃