Phương pháp CanvasRenderingContext2D
0, một phần của API Canvas 2D, thêm một đường thẳng vào đường dẫn phụ hiện tại bằng cách kết nối điểm cuối cùng của đường dẫn phụ với tọa độ
1 đã chỉ địnhGiống như các phương thức khác sửa đổi đường dẫn hiện tại, phương thức này không trực tiếp hiển thị bất kỳ thứ gì. Để vẽ đường dẫn lên canvas, bạn có thể sử dụng phương pháp
2 hoặc
3cú pháp
lineTo[x, y]
Thông số
0Tọa độ trục x của điểm cuối của đường
1Tọa độ trục y của điểm cuối của đường
Giá trị trả về
Không có [
2]ví dụ
Vẽ một đường thẳng
Ví dụ này vẽ một đường thẳng bằng phương pháp
0HTML
JavaScript
Dòng bắt đầu tại [30, 50] và kết thúc tại [150, 100]
const canvas = document.getElementById["canvas"];
const ctx = canvas.getContext["2d"];
ctx.beginPath[]; // Start a new path
ctx.moveTo[30, 50]; // Move the pen to [30, 50]
ctx.lineTo[150, 100]; // Draw a line to [150, 100]
ctx.stroke[]; // Render the path
Kết quả
Vẽ các đường kết nối
Mỗi cuộc gọi của
0 [và các phương thức tương tự] sẽ tự động thêm vào đường dẫn con hiện tại, có nghĩa là tất cả các dòng sẽ được vuốt hoặc điền vào cùng nhau. Ví dụ này vẽ một chữ cái 'M' với một đường liền kề CSS Visual Dictionary chứa các sơ đồ trực quan cho mọi thuộc tính CSS đơn lẻ được sử dụng phổ biến. Ngữ pháp JavaScript chứa…
hướng dẫn. trung bình. com
Một dự án mới luôn bắt đầu với một câu hỏi giải quyết vấn đề
Làm cách nào để bạn vẽ một đường trên màn hình máy tính mà không có canvas hoặc thư viện?
Là một người mới viết mã, bạn thường nghe về các thuật toán
Người tạo HTML Canvas, SVG, WebGL và các thư viện đồ họa khác phải viết mã để vẽ các đường từ đầu
Đã đến lúc vạch ra ranh giới giữa nghe về điều gì đó và thực hiện nó. . ]
Trong hướng dẫn này, tôi sẽ chỉ cho bạn các chi tiết cơ bản về việc thiết kế một thuật toán là như thế nào. Tôi sẽ lấy thuật toán Bresenham’s Line Drawing làm ví dụ
Tại sao lại là thuật toán vẽ đường của Bresenham?
Tôi nghĩ đó là một mẫu vật hoàn hảo để học hỏi vì nhiều lý do
- Thật bổ ích — bạn không chỉ tính toán các con số mà còn xem kết quả trực quan
- Nó tương đối đơn giản như ví dụ đầu tiên của bạn để nghiên cứu các thuật toán từ
- Nó sử dụng Hệ tọa độ Descartes — hệ tọa độ được sử dụng làm cơ sở trong nhiều thuật toán phổ biến. Đó là điều kiện tiên quyết để Machine Learning [sử dụng cái gọi là chức năng kích hoạt trong AI, là các phương trình toán học dựa trên CCS. ]
- Bạn có thể triển khai nó bằng JavaScript [xem bản demo trực tiếp tại đây. ]
Bạn đã bao giờ có một dự án mà bạn luôn trì hoãn sau này chưa?
Chà, vẽ một đường trong HTML mà không cần canvas là điều tôi nghĩ trong hơn một năm. Và cuối cùng tôi đã quyết định thực hiện hướng dẫn này về chủ đề
Nhân tiện, bạn có thể theo dõi tôi trên Twitter để biết thêm hướng dẫn về freemium
Hãy xem bản demo vẽ đường này đang hoạt động trực tiếp trên một trang mẫu mà tôi đã tạo
Trên đây là kết quả của thuật toán được giải thích trong hướng dẫn này. Một đường được vẽ giữa hai điểm trên màn hình raster điển hình. Trong trường hợp này, tôi đã sử dụng một lưới HTML đơn giản được tạo thành từ các phần tử DIV. Nó hơi chậm và không phù hợp để hiển thị đồ họa hiệu suất cao trong thời gian thực, nhưng nó thể hiện rõ ràng mục đích của thuật toán này
Làm thế nào một cái gì đó như thế này làm việc? . Với hai điểm cuối bất kỳ — chúng ta có thể hiển thị một đường trên màn hình raster
Trong trường hợp này, nó được biểu thị bằng một lưới HTML đơn giản được tạo từ các phần tử DIV
Làm thế nào nó hoạt động?Các thuật toán là những con thú khó khăn
Đầu tiên, tốt nhất là hình dung bạn đang cố gắng đạt được điều gì
Thuật toán của Bresenham giải quyết vấn đề vẽ các đường trong Góc phần tư 1
Thuật toán này giải quyết việc vẽ đường cho Góc phần tư 1 trên Hệ tọa độ Descartes
Vẽ một đường theo bất kỳ hướng nào đòi hỏi phải suy nghĩ theo góc phần tư
Mặc dù thuật toán cho Góc phần tư 1 rất đơn giản — nhưng việc triển khai cho tất cả các góc phần tư [và quãng tám] lại rất phức tạp. Nhưng chỉ về mặt hậu cần. Các trường hợp còn lại là hình ảnh phản chiếu đơn giản của hai phần tám trong Góc phần tư 1
Điều này có nghĩa là thay vì phát minh lại bánh xe, tất cả những gì bạn phải làm là hoán đổi một số biến xung quanh hoặc lật dấu của chúng ở đây và ở đó
Vấn đề là - làm cách nào để chúng tôi viết mã đó bằng JavaScript?
Tại sao vẽ các dòng trong HTML mà không cần Canvas?Nhiều lý do
Để cung cấp một lời giải thích rõ ràng về cách thức hoạt động của thuật toán vẽ Bresenham
Nhiều hướng dẫn vẽ đường thẳng của Bresenham mà tôi đã xem qua chỉ giải thích các dẫn xuất toán học. Nhưng họ không đi sâu vào chi tiết về mã cho từng octant hoặc triển khai thực tế bản demo. Nó chỉ giống như thực hiện một cái gì đó mà bạn không thực sự hiểu
Thật đơn giản — một số thứ chỉ là niềm vui. Ý tôi là, sẽ không tuyệt sao nếu vẽ các đường trong HTML mà không cần sử dụng canvas hoặc WebGL? . Bạn có thể sinh sản bao nhiêu tùy thích
Tôi đến từ một nền tảng phát triển trò chơi. Và trong các trò chơi, bạn thường xử lý các đường vẽ. Nhưng ngoài ra, tôi luôn thấy ý tưởng vẽ các đường trong HTML thật hấp dẫn. Có lẽ bởi vì tôi chưa bao giờ thấy nó được thực hiện trước đây
Tất nhiên, tốc độ kết xuất HTML thô sẽ là một vấn đề. Và vâng, sẽ cần tối ưu hóa thêm để đạt được hiệu suất có ý nghĩa. Nhưng trọng tâm của hướng dẫn vẽ đường này chủ yếu tập trung vào giải thích thuật toán vẽ đường. Bạn luôn có thể triển khai lại nó trong bất kỳ môi trường raster hoặc thư viện đồ họa nào khác
Triển khai thuật toán vẽ đường trong JSChúng tôi lấy hai đồng bằng và tính hệ số góc của phương trình đường thẳng, dựa trên hai điểm cuối của đường thẳng
Điểm đầu và điểm cuối của đường được cung cấp cho bốn tham số của hàm draw_line [tương ứng [x0, y0] và [x1, y1]]
Bạn có thể triển khai điều này bằng C, C++, Python, Java hoặc bất kỳ ngôn ngữ nào khác. Tất nhiên, trong hướng dẫn này, chúng tôi sẽ sử dụng JavaScript
Sau khi chúng tôi hiểu rõ về thuật toán một cách trực quan, đã đến lúc bắt đầu chuyển đổi logic thành mã
Đây là mã giả
draw_line[x0, y0, x1, y1] // Calculate "deltas" of the line [difference between two ending points]
dx = x1 - x0
dy = y1 - y0 // Calculate the line equation based on deltas
D = [2 * dy] - dx
y = y0 // Draw the line based on arguments provided
for x from x0 to x1 // Draw pixel at this location
pixel[x, y] // Progress the line drawing algorithm parameters
if D > 0
y = y + 1
D = D - 2*dx
end if
D = D + 2*dy
Chuyển đổi nó thành JavaScript, chúng tôi nhận được như sau
let draw_line = [x0, y0, x1, y1] => { // Calculate "deltas" of the line [difference between two ending points]
let dx = x1 - x0;
let dy = y1 - y0; // Calculate the line equation based on deltas
let D = [2 * dy] - dx; let y = y0; // Draw the line based on arguments provided
for [let x = x0; x < x1; x++]
{
// Place pixel on the raster display
pixel[x, y]; if [D >= 0]
{
y = y + 1;
D = D - 2 * dx;
} D = D + 2 * dy;
}
};
Lưu ý rằng tất cả điều này chỉ dành cho Góc phần tư 1
Giải thích logic thuật toán
Trước tiên, chúng tôi tính toán sự khác biệt giữa các điểm cuối của đường trên cả hai trục [dx và dy] thường được gọi là delta - tương ứng cho mỗi chiều trong hai chiều
Sau đó, chúng tôi tính toàn bộ delta của đường thẳng [ở đây được lưu trữ trong biến D] — bạn có thể coi nó như một phương trình toán học để vẽ một đường thẳng. Hay nói cách khác phương trình hệ số góc
Trước khi lặp qua từng khoảng của đường, hãy đặt lại bộ đếm trục y [mà chúng ta sẽ đi bằng vòng lặp for, khi đường đang được vẽ] bằng cách đặt nó về vị trí ban đầu trên đường. Ở đây y0 đề cập đến tọa độ Y của điểm đầu tiên trên đường thẳng
Cuối cùng, vẽ đường thẳng một "pixel" tại một thời điểm, bằng mã giả được hiển thị dưới dạng hàm pixel[x, y]. Sau khi pixel được hiển thị, chúng tôi có thể điều chỉnh vị trí pixel hiện tại bằng cách sử dụng các bước delta mà chúng tôi đã tính toán
Mỗi khi bộ đếm delta vượt quá 0, chúng tôi chuyển xuống pixel tiếp theo trên trục Y và điều chỉnh lại biến D nhưng ở chiều ngược lại, điều này kết thúc bằng việc vẽ dần dần đường trên cả hai chiều cho đến khi chúng tôi đi đến cuối đường
Nhưng đó không phải là tất cả. Ngoài ra, tùy thuộc vào sự thống trị của trục, vòng lặp for phải được sửa đổi để di chuyển theo hướng đó. Để hoàn thành thuật toán, chúng ta cũng phải điều chỉnh các tham số dựa trên octant [trong số tám] chúng ta đang ở. Điều này được giải thích chi tiết trong phần sau
Vẽ trong cả 4 góc phần tư / 8 OctantsThuật toán đường thẳng của barebones Bresenham ở trên được thiết kế để chỉ vẽ một đường thẳng trong một góc phần tư [Góc phần tư 1] của hệ tọa độ Descartes. Nhưng chúng ta cần bao phủ tất cả các hướng. Rốt cuộc, một đường ngẫu nhiên có thể được vẽ từ bất kỳ điểm nào trên màn hình raster đến bất kỳ điểm nào khác
Điều này có nghĩa là ngoài mã giả ở trên, chúng ta cần quan tâm đến hai thứ khác
- Thuật toán Quadrant-Aware. Thuật toán phải điều chỉnh các tham số của trình vòng lặp, cho mỗi trong số bốn góc phần tư. Chúng tôi có thể hoán đổi các điểm cuối của đường để đảm bảo rằng chúng tôi luôn vẽ đường từ trái sang phải và chia thuật toán thành hai phần chính [đường hướng lên hoặc hướng xuống từ điểm bắt đầu. ] Hoặc chúng ta có thể phân nhánh theo bốn trường hợp khác nhau, tương ứng cho từng góc phần tư và chỉ cần hoán đổi các trình vòng lặp trục x và trục y để phù hợp với hướng của đường
- Axis-Dominance. Nhưng ngay cả trong mỗi góc phần tư, đường thẳng sẽ chiếm ưu thế trục x hoặc trục y. Điều này có nghĩa là thực sự không có bốn mà là tám trường hợp khác nhau. Một cho mỗi trong số tám quãng tám. May mắn thay, thuật toán vẫn giống hệt nhau, tất cả những gì chúng ta cần làm là chuyển đổi các vòng lặp và phân nhánh một vài lần
Đó là rất nhiều phân nhánh. Nhưng thuật toán được trình bày trong ví dụ sau sẽ xử lý tất cả các trường hợp có thể xảy ra
Thuật toán hoàn chỉnh của Bresenham trong JavaScriptĐược rồi — tất cả những điều này nghe có vẻ tuyệt vời về mặt lý thuyết — và chúng tôi đã đề cập đến mã giả và phiên bản JavaScript — nhưng chỉ dành cho một góc phần tư. Hãy cùng xem toàn bộ enchilada
________số 8Đây chỉ là một cách để viết thuật toán vẽ đường Bresenham. Bạn có thể tung hứng xung quanh các tham số và ứng biến khi phân nhánh. Nhưng ý tưởng cơ bản là có
Câu lệnh if chính phân nhánh giữa hai trường hợp chi phối trục tiềm năng
Mã nhận biết octant - trong hai phạm vi câu lệnh if, bạn cũng sẽ thấy rằng mã về cơ bản phản chiếu chính nó giữa trục X và Y [được theo dõi bởi các biến px và py] nhưng logic thuật toán thì khá giống nhau.
điểm ảnh[x, y]Hãy nhớ rằng, chúng tôi không sử dụng canvas hoặc bất kỳ thư viện đồ họa nào khác khi viết các thuật toán đồ họa của riêng mình
Điều này có nghĩa là phương tiện thực tế mà bạn chọn để vẽ dữ liệu phụ thuộc hoàn toàn vào bạn. Trong bản demo này, tôi đã sử dụng lưới DIV cơ bản
Hàm pixel[x, y] này là cách bạn chọn để triển khai vẽ đường dựa trên loại màn hình raster bạn sẽ sử dụng
Về cơ bản, nó đặt một “pixel” tại vị trí X và Y trên “màn hình”/đầu ra kết xuất
Từ cuối cùngMọi người thường hỏi tôi cách cải thiện kỹ năng mã hóa của họ. Tôi thường khuyên bạn nên chọn một dự án cao hơn một chút so với khả năng hiện tại của bạn. Nếu bạn đảm bảo hoàn thành nó, trải nghiệm này sẽ giúp bạn nâng cao kỹ năng mã hóa của mình. Đối với tôi, đây là loại dự án