2015-12-17 20 views
5

Tôi đã chơi với phần tử canvas và phát hiện ra rằng khi tôi cố gắng vẽ các ô màu đồng nhất NxN bên cạnh nhau, trong một số cấu hình chiều rộng/chiều cao, có các đường màu trắng mờ giữa chúng. Ví dụ:Weird HTML 5 Canvas Antialiasing

Ví dụ: canvas này có màu đen nhưng chứa một số loại lưới mà tôi phỏng đoán là kết quả của việc chống răng cưa bị lỗi trong trình duyệt.

The canvas demonstrating the issue.

đủ để nói, lỗi này chỉ xuất hiện trong một số cấu hình nhưng tôi muốn để thoát khỏi nó cho tốt. Có cách nào để phá vỡ điều này không? Bạn đã từng gặp vấn đề với khử răng cưa trong canvas chưa?

Tôi đã thực hiện this fiddle minh họa sự cố và cho phép bạn chơi với kích thước của canvas và số ô. Nó cũng chứa mã tôi sử dụng để vẽ các ô, để bạn có thể kiểm tra nó và cho tôi biết nếu tôi làm gì sai.

var ctx = canvas.getContext('2d'); 
ctx.clearRect(0, 0, canvasWidth, canvasHeight); 
for (var i = 0; i < numberOfCells; ++i) { 
    for (var j = 0; j < numberOfCells; ++j) { 
    ctx.fillStyle = '#000'; 
    ctx.fillRect(j * cellWidth, i * cellHeight, cellWidth, cellHeight); 
    } 
} 

Cảm ơn trước,

Petr.

+0

Xin chào Petr, nó sẽ có vẻ bạn quên cung cấp liên kết fiddle của bạn, bạn có thể vui lòng cập nhật – Canvas

+0

Chỉ cần nhận thấy nó. Xin lỗi, ở đây bạn đi! :) –

+0

Một thủ thuật phổ biến là chuyển đổi toàn bộ khung hình bằng một pixel ngay từ đầu để tránh điều này, tôi tin. –

Trả lời

1

Sau khi đọc qua và thử một số cách tiếp cận, tôi đã quyết định tự mình làm theo. Tôi đã tạo một canvas (ảo) khác có kích thước số nguyên tương ứng với số lượng ô trong lưới.

Sau khi vẽ tất cả các ô trong đó, tôi gọi context.drawImage() trên canvas chính và chuyển canvas ảo làm đối số cùng với tham số bù trừ và tỷ lệ để làm cho nó phù hợp với phần còn lại của bản vẽ của tôi. Giả sử rằng trình duyệt sẽ mở rộng toàn bộ hình ảnh của canvas ảo (và không phải là các ô riêng lẻ), tôi đã hy vọng loại bỏ các đường phân cách không mong muốn.

Bất chấp những nỗ lực của tôi, các đường vẫn còn đó. Bất kỳ đề xuất?

Đây là fiddle chứng minh kỹ thuật của tôi: https://jsfiddle.net/ngxjnywz/5/

+0

Tôi đã phát hiện ra thủ phạm. Hóa ra cách tiếp cận này hoạt động miễn là tôi không thay đổi canvas thứ cấp 0,5 pixel (như được đề xuất trong câu trả lời khác). Sau khi loại bỏ 'context.translate (0.5, 0.5)', mọi thứ khác rơi vào vị trí. –

4

jsFiddle: https://jsfiddle.net/ngxjnywz/2/

đoạn mã javascript

var cellWidth = Math.ceil(canvasWidth/numberOfCells); 
var cellHeight = Math.ceil(canvasHeight/numberOfCells); 

Tùy thuộc vào chiều rộng, chiều cao và numberOfCells của bạn đôi khi bạn đang nhận được một ... cho phép nói 4.2 là 4, tuy nhiên điều này sẽ được hiển thị sai và sẽ cho phép một dòng trống 1 pixel xuất hiện. Vì vậy, tất cả những gì bạn cần làm là sử dụng chức năng Math.ceil và điều này sẽ làm cho cellWidth và cellHeight của bạn luôn trở thành số cao hơn và bạn sẽ không nhận được các dòng trống nữa

+0

Thật không may làm tròn chỉ hoạt động nếu đường song song với trục X hoặc Y, cũng không tính đến bất kỳ chuyển đổi có thể được áp dụng. – Blindman67

+0

Đó là giải pháp thực sự tốt đẹp và dễ dàng. Nó có thể hơi lộn xộn một chút vì các ô sẽ bắt đầu chồng lên nhau và có thể khiến cho thứ tự bản vẽ đột nhiên trở nên có liên quan, nhưng vì cùng một 'cellWidth' sẽ được sử dụng để bù lại quy trình vẽ, điều này sẽ được ngăn chặn. –

+0

Tôi vừa thử "ctx.fillRect (j * cellWidth + 151, i * cellHeight + 77, cellWidth, cellHeight);" và nó hoạt động mà không có một vấn đề tuy nhiên tôi có thể xác nhận rằng bất kỳ "biến đổi" trên lưới sẽ tái tạo dòng, tuy nhiên nếu bạn chuyển đổi bất cứ điều gì sau khi lưới nó là tốt, Hãy xem liên kết của tôi https://jsfiddle.net/ngxjnywz/ 4/ – Canvas

2

Giải pháp tốt nhất là thêm xung đột rộng 0,5 pixel tất cả các bản đầy, sử dụng cùng một kiểu như điền và bù đắp tất cả bản vẽ để bạn hiển thị ở giữa pixel thay vì ở trên cùng bên trái.

Nếu bạn thêm tỷ lệ hoặc bản dịch, bạn sẽ phải điều chỉnh tọa độ để bạn vẫn cung cấp cho các trung tâm cho tọa độ bản vẽ của mình.

Cuối cùng, bạn chỉ có thể giảm hiện vật nhưng trong nhiều trường hợp, bạn sẽ không thể xóa hoàn toàn chúng.

Câu trả lời này cho bạn biết cách loại bỏ các tạo tác cho một canvas không được chuyển đổi. How to fill the gaps

+0

Đây là một thủ tục khá phức tạp. Trong thiết lập cụ thể của tôi, tôi sẽ phải suy nghĩ lại hoàn toàn về toán học của bản vẽ lưới của tôi. –

+0

@ PetrMánek Đúng, nhưng trong các tình huống khác, đây thực sự là giải pháp đơn giản nhất - chỉ cần thêm 0,5 vào tất cả các tọa độ. –

+0

@ PetrMánek. Thủ thuật nửa pixel hoạt động tốt với chi phí của một số thiết kế lại. Cách giải quyết khác là tạo "khối xây dựng" trên canvas thứ hai và [lắp ráp thiết kế của bạn từ các khối xây dựng đó] (http://stackoverflow.com/questions/29355920/canvas-polygons-not-touching-properly) – markE