Việc kết xuất HTML trong canvas WebGL cho phép bạn sử dụng cây con DOM trực tiếp làm kết cấu GPU động, áp dụng hiệu ứng chương trình đổ bóng cho DOM trực tiếp và tích hợp HTML tương tác vào cảnh 3D.
Hướng dẫn này minh hoạ cách kết xuất HTML vào canvas WebGL. Tìm hiểu thêm về HTML-in-Canvas trong phần Tổng quan về API.
Để kết xuất HTML trong canvas WebGL, 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.
- Áp dụng HTML làm hoạ tiết:
- Phân bổ trước bộ nhớ kết cấu GPU.
- Tải ảnh chụp nhanh DOM lên dưới dạng hoạ tiết.
- Đồng bộ hoá DOM và pixel.
Vẽ một phần tử HTML dưới dạng kết cấu WebGL
Trong WebGL, các phần tử HTML được tải lên GPU dưới dạng kết cấu 2D bằng texElementSubImage2D().
Phân bổ trước bộ nhớ hoạ tiết
Không giống như canvas 2D (tự động quản lý bộ nhớ sao lưu), ngữ cảnh WebGL yêu cầu quản lý bộ nhớ rõ ràng.
Trước khi tải pixel DOM lên, bạn phải phân bổ trước bộ nhớ GPU. Điều này cho phép trình duyệt cập nhật nhanh hình ảnh phụ mà không cần kích hoạt việc phân bổ lại bộ nhớ GPU tốn kém.
Phân bổ trước vùng đệm bằng các tham số kích thước đã chọn và đặt srcData thành null như sau:
// Only allocate texture backing once
if (!textureBufferAllocated) {
// Pre-allocate texture backing with pre-determined size.
gl.texImage2D(
/* target */ gl.TEXTURE_2D,
/* level */ 0,
/* internalformat */ gl.RGBA8,
/* width */ myElementWidth,
/* height */ myElementHeight,
/* border */ 0,
/* format */ gl.RGBA,
/* type */ gl.UNSIGNED_BYTE,
/* srcData */ null
);
textureBufferAllocated = true;
}
Để kết cấu khớp với kích thước bố cục tự nhiên của phần tử HTML, hãy sử dụng canvas.getElementImageDefaultSize() để truy xuất kích thước mặc định của kết cấu theo pixel lưới canvas:
const { width, height } = canvas.getElementImageDefaultSize(myElement);
// Pre-allocate texture backing. Only do this once, or whenever the element
// changes size.
gl.texImage2D(
/* target */ gl.TEXTURE_2D,
/* level */ 0,
/* internalformat */ gl.RGBA8,
/* width */ Math.ceil(width),
/* height */ Math.ceil(height),
/* border */ 0,
/* format */ gl.RGBA,
/* type */ gl.UNSIGNED_BYTE,
/* srcData */ null
);
Tải ảnh chụp nhanh DOM lên dưới dạng hoạ tiết
Bước tiếp theo là tải phần tử HTML lên kết cấu bên trong vòng lặp kết xuất hoặc trình nghe paint.
canvas.onpaint = () => {
// 1. Pre-allocate texture backing first
// ...
// 2. Upload HTML snapshot into the WebGL texture
gl.texElementSubImage2D(
/* target */ gl.TEXTURE_2D,
/* level */ 0,
/* xoffset */ 0,
/* yoffset */ 0,
/* element */ myElement // or an ElementImage from `captureElementImage()`
);
// ...
};
Đồng bộ hoá hình học
Không giống như trong bối cảnh 2D, trình duyệt không thể tự động suy luận vị trí kết cấu xuất hiện trên màn hình trong bối cảnh 3D. Bạn cần phải căn chỉnh thử nghiệm nhấn DOM và hộp giới hạn hỗ trợ tiếp cận với lưới 3D theo cách thủ công.
Để làm việc này, hãy tạo một DOMMatrix liên kết hộp đường viền của phần tử với vị trí pixel canvas được kết xuất, sau đó áp dụng bằng updateElementGeometry():
canvas.addEventListener("paint", () => {
// 1. Upload fresh DOM snapshot to GPU texture
gl.bindTexture(gl.TEXTURE_2D, myTexture);
gl.texElementSubImage2D(gl.TEXTURE_2D, 0, 0, 0, myElement);
// 2. Draw your 3D scene
draw3DScene();
// 3. Construct the CSS-pixel transform mapping the element's
// border box to its drawn position on the canvas as needed
// (for example: scale and translate)
const canvasTransform = new DOMMatrix();
// scale X
canvasTransform.a = canvas.clientWidth / myElement.offsetWidth;
// scale Y
canvasTransform.d = canvas.clientHeight / myElement.offsetHeight;
// translate X (CSS px)
canvasTransform.e = 50;
// translate Y (CSS px)
canvasTransform.f = 100;
// 4. Update DOM position, accessibility focus rings, and pointer hit-testing
canvas.updateElementGeometry(myElement, {
canvasTransform: canvasTransform,
});
});
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 bối cảnh 2D.
- 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.