2011-09-09 34 views
12

Để phát xung quanh với canvas HTML5, tôi quyết định tạo một ứng dụng vẽ một mặt đồng hồ tương tự. Mọi thứ đều tốt, ngoại trừ những dòng cũ không bị xóa theo cách mà tôi mong đợi. Tôi đã bao gồm một phần của mã dưới đây - DrawHands() được gọi một lần thứ hai:Xóa các đường kẻ được vẽ trước đây trên canvas HTML5

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); 
} 

Để làm cho tinh thần của các bên trên, có hai chức năng helper:

  • DrawLine (x1, y1 , x2, y2, màu sắc, độ dày)
  • getOtherEndOfLine (x, y, góc, chiều dài)

vấn đề là trong khi tất cả các tay được rút ra như mong đợi trong màu đen, họ không bao giờ bị xóa. Tôi hy vọng rằng kể từ khi cùng một dòng được vẽ bằng màu trắng (màu nền) nó có hiệu quả sẽ xóa những gì đã được rút ra tại thời điểm đó. Nhưng điều này dường như không đúng.

Mọi thứ tôi bị thiếu?

Trả lời

13

Vì lý do mà tôi có thể mở rộng, bạn nên xem xét xóa khung hình và vẽ lại hoàn toàn trừ khi có lý do hiệu suất hoặc tổng hợp không.

Bạn muốn clearRect, một cái gì đó như thế này:

//clear the canvas so we can draw a fresh clock 
ctx.clearRect(0, 0, canvasWidth, canvasHeight); 

//redraw your clock here 
/* ... */ 
+3

Nếu một người muốn xóa một dòng hoặc hình dạng cụ thể (như tôi đã làm), chứ không phải thanh toán bù trừ một khu vực hình chữ nhật, thiết lập 'ctx.globalCompositeOperation =" destination-out "' - như đã đề cập trong giải pháp andrewmu cho một [câu hỏi tương tự] (http://stackoverflow.com/questions/3328906/erasing-in-html5-canvas) - sẽ đẹp nhiều thao tác fill/stroke của bạn hoạt động giống như một công cụ tẩy. Hãy nhớ thay đổi chế độ tổng hợp lại khi bạn hoàn tất. Xem [tổng hợp và cắt của Mozilla] (https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing) để biết chi tiết đầy đủ. – TheMadDeveloper

+0

Không nhất thiết phải luôn xóa hoàn toàn canvas.Xem câu trả lời của Simon Sarris bằng cách sử dụng getImageData/putImageData, cho phép bạn khôi phục bản vẽ cho bất kỳ (các) giai đoạn trước nào của bản vẽ. – Allasso

+0

Chỉnh sửa ở trên chú thích - nên đọc câu trả lời của mrmcgreg. – Allasso

4

Lý do bạn không thể chỉ vẽ lại dòng trong trắng và hy vọng cho nó để xóa dòng cũ là bởi vì có thể có một số anti-aliasing/sự chảy máu. Bạn cũng sẽ nhận thấy rằng một đường thẳng nằm ngang được vẽ trên một pixel so với một nửa pixel trông rất khác nhau vì điều này.

Khi bạn thực hiện các dòng "xóa" màu trắng của mình, hãy thử vẽ chúng bằng một lớn hơn lineWidth khoảng 3 hoặc 4. Điều đó sẽ phù hợp với trường hợp của bạn.

Bạn cũng nên vẽ tất cả các vạch trắng trước, sau đó là tất cả các đường màu đen, trong trường hợp chúng giao nhau.

4

Một cách nhanh chóng và dễ dàng để xóa một canvas là để thiết lập chiều rộng:

context.canvas.width = context.canvas.width; 
+1

Mùi giống như tùy thuộc vào một số triển khai cụ thể trong một trình duyệt cụ thể, đây là cách dễ dàng để xác định hành vi trong các trình duyệt khác. – BarbaraKwarc

10

Thay vì xóa những điều bạn không muốn bạn có thể lưu trạng thái của vải vào thời điểm đó trước khi bạn đã vẽ những thứ bạn không muốn và sau đó khôi phục lại khung thành trạng thái đó để 'xóa' chúng.

Điều này có thể được thực hiện khá dễ dàng sử dụng ImageData:

var canvas = document.querySelector('canvas'), 
 
    context = canvas.getContext('2d'); 
 

 
context.fillStyle = 'blue'; 
 
context.fillRect(0,0,10,10); 
 

 
// save the state of the canvas here 
 
var imageData = context.getImageData(0,0,canvas.width,canvas.height); 
 

 
// draw a red rectangle that we'll get rid of in a second 
 
context.strokeStyle = 'red'; 
 
context.strokeRect(70,70,20,20); 
 

 
setTimeout(function() { 
 
    // return the canvas to the state right after we drew the blue rect 
 
    context.putImageData(imageData, 0, 0); 
 
}, 1000);
<canvas width=100 height=100>

+1

Phương thức này có lợi thế hơn khi sử dụng clearRectangle, trong đó bạn có thể getImageData ở bất kỳ giai đoạn nào của bản vẽ và khôi phục về mức đó, trong khi clearRectangle sẽ luôn đưa bạn trở lại một khung trống. Vì lý do này, tôi đã bỏ phiếu. – Allasso

+1

... Bạn thậm chí có thể chụp nhanh ở một vài điểm trong quá trình vẽ nếu cần để khôi phục. – Allasso

+0

Điều này cũng có thể giúp bạn không phải tải lại hình ảnh nếu bạn đang sử dụng hình ảnh cho phông nền. – Allasso

Các vấn đề liên quan