Khi bạn vẽ hình ảnh từ nguồn khác domain (cross-origin) lên canvas, canvas sẽ bị "tainted" (nhiễm bẩn). Sau đó, bạn không thể gọi getImageData(), toDataURL(), hoặc toBlob() trên canvas đó — trình duyệt sẽ ném lỗi bảo mật: "The canvas has been tainted by cross-origin data".
Giải pháp: Sử dụng thuộc tính crossOrigin
Thiết lập thuộc tính crossOrigin trên đối tượng Image trước khi gán src:
var img = new Image();
img.crossOrigin = "Anonymous"; // Quan trọng: đặt TRƯỚC khi gán src
img.src = "https://domain-khac.com/hinh-anh.jpg";
img.onload = function() {
ctx.drawImage(img, 0, 0);
// Bây giờ có thể dùng getImageData(), toDataURL() bình thường
var data = ctx.getImageData(0, 0, canvas.width, canvas.height);
};
Yêu cầu phía Server (CORS)
Server chứa hình ảnh phải gửi header CORS phù hợp:
Access-Control-Allow-Origin: *
Hoặc chỉ cho phép domain cụ thể:
Access-Control-Allow-Origin: https://your-domain.com
Các giá trị của crossOrigin
| Giá trị | Ý nghĩa |
|---|---|
"anonymous" | Yêu cầu CORS không gửi credential (cookie, HTTP auth). Phổ biến nhất. |
"use-credentials" | Yêu cầu CORS kèm credential. Server phải phản hồi Access-Control-Allow-Credentials: true và không được dùng wildcard (*) cho Origin. |
"" (rỗng) hoặc không thiết lập | Mặc định: Không dùng CORS → canvas bị tainted nếu cross-origin. |
Lưu ý
- Nếu server không hỗ trợ CORS, bạn không thể đọc pixel data từ canvas. Giải pháp: Proxy hình ảnh qua server của mình (server-side fetch rồi serve lại với header CORS).
- Lỗi này cũng xảy ra với
<video>vẽ lên canvas.