API HTML-in-Canvas cho phép bạn kết xuất các cây con DOM có thể truy cập và tương tác trực tiếp vào ngữ cảnh canvas 2D. Đọc tổng quan về HTML-in-Canvas để tìm hiểu thêm về API này và các lợi ích của API này.
Hướng dẫn này minh hoạ cách kết xuất HTML thành canvas 2D. Để kết xuất HTML trong canvas 2D, bạn cần thực hiện các bước sau:
- Chuẩn bị canvas. Đặt các thuộc tính phù hợp một cách rõ ràng để cho trình duyệt biết rằng trình duyệt nên kết xuất HTML vào một canvas. Cách thiết lập này giống hệt nhau trong các bối cảnh 2D, WebGL và WebGPU. Tìm hiểu cách thiết lập canvas và cách khai báo các phần tử HTML cần được vẽ độc lập.
- Vẽ hình ảnh phần tử vào canvas.
- [Không bắt buộc] Đồng bộ hoá DOM và pixel.
Vẽ các phần tử HTML vào canvas 2D
Sau khi canvas sẵn sàng và các phần tử được đánh dấu là drawable, hãy kết xuất các phần tử đó vào ngữ cảnh 2D bằng phương thức drawElementImage().
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const childElement1 = document.getElementById("childElement1");
const childElement2 = document.getElementById("childElement2");
canvas.onpaint = () => {
ctx.reset();
// 1. Draw the primary element at coordinate (20, 20)
ctx.drawElementImage(childElement1, 20, 20);
// 2. Draw the secondary nested button at a custom offset
ctx.drawElementImage(childElement2, 40, 90);
}
drawElementImage() hỗ trợ các biểu mẫu 3 đối số, 5 đối số, 7 đối số và 9 đối số, đồng thời chấp nhận tham số options không bắt buộc:
// 1. Basic position: (element, dx, dy, options?)
ctx.drawElementImage(targetElement, 100, 150);
// 2. Scaled / resized: (element, dx, dy, dWidth, dHeight, options?)
ctx.drawElementImage(targetElement, 100, 150, 180, 60);
// 3. Cropped, default size: (element, sx, sy, swidth, sheight, dx, dy, options?)
ctx.drawElementImage(targetElement, 0, 0, 90, 30, 100, 150);
// 4. Cropped and resized: (element, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, options?)
ctx.drawElementImage(targetElement, 0, 0, 90, 30, 100, 150, 180, 60);
| Biểu mẫu quá tải | Thông số | Hiệu ứng bố cục |
|---|---|---|
| Kích thước mặc định | (element, dx, dy) |
Toàn bộ phần tử ở kích thước mặc định, với góc trên cùng bên trái tại (dx, dy). |
| Hộp đích đến tuỳ chỉnh | (element, dx, dy, dwidth, dheight) |
Điều chỉnh tỷ lệ hình ảnh phần tử đầy đủ thành khung nhìn dw × dh trên canvas. |
| Đã cắt, kích thước mặc định | (element, sx, sy, swidth, sheight, dx, dy) |
Chỉ vùng swidth × sheight bắt đầu tại (sx, sy), được vẽ theo kích thước mặc định của vùng đó (cùng tỷ lệ với biểu mẫu có kích thước mặc định). |
| Lát cắt nguồn đến đích | (element, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) |
Cắt phần tử nguồn bắt đầu từ (sx, sy) với kích thước swidth × sheight, sau đó liên kết phần tử đó với đích đến (dx, dy, dwidth, dheight). |
Đồng bộ hoá DOM và pixel
Vì việc kết xuất <canvas> là bắt buộc trong khi bố cục DOM và kiểu CSS có tính phản ứng, nên trình duyệt cần có một cơ chế để đồng bộ hoá các pixel canvas được kết xuất, vùng kiểm thử nhấn tương tác và cây hỗ trợ tiếp cận. Trước khi tìm hiểu cách đồng bộ hoá DOM và pixel, hãy đảm bảo bạn hiểu rõ sự kiện paint kích hoạt khi các phần tử DOM cập nhật và cần được vẽ lại.
Trong ngữ cảnh canvas 2D, trình duyệt sẽ tự động đồng bộ hoá toạ độ bố cục của phần tử, ranh giới hỗ trợ tiếp cận và thử nghiệm nhấn con trỏ với toạ độ canvas được vẽ.
Cập nhật hình học phần tử theo cách thủ công
Trong các trường hợp nâng cao, bạn có thể chọn không sử dụng tính năng đồng bộ hoá hình học tự động và kiểm soát các phép biến đổi không gian theo cách thủ công. Truyền { preserveElementGeometry: true } đến drawElementImage() để ngăn trình duyệt tự động ghi đè toạ độ thử nghiệm nhấn hiện có của phần tử:
// 1. Draw the element without altering its existing hit-test bounds
ctx.drawElementImage(targetElement, elementX, 200, { preserveElementGeometry: true });
// 2. Construct a custom transform matrix as needed,
// assuming scaleX/scaleY = canvas grid pixels per CSS pixel,
// from your resize observer (see "Units and sizing").
const currentTransform = new DOMMatrix();
currentTransform.a = 1.5; // scale X
currentTransform.e = x / scaleX; // translate X: grid px → CSS px
currentTransform.f = y / scaleY; // translate Y: grid px → CSS px
// 3. Explicitly apply the custom transform
canvas.updateElementGeometry(targetElement, { canvasTransform: currentTransform });
drawElementImage() sẽ tự động cập nhật hình dạng này. Bản minh hoạ này cho thấy cách hình học không đồng bộ khi { preserveElementGeometry: true } được đặt.Các bước tiếp theo
- Tìm hiểu các khái niệm kỹ thuật cốt lõi đằng sau HTML-in-Canvas.
- Tìm hiểu cách kết xuất HTML trong Canvas WebGL.
- Tìm hiểu cách kết xuất HTML trong Canvas WebGPU.
- Tìm hiểu về chiến lược dự phòng.
- Gửi vấn đề trên GitHub để chia sẻ ý kiến phản hồi của bạn.
- Hãy xem bộ sưu tập bản minh hoạ HTML trong Canvas do cộng đồng cung cấp.