2013-08-07 45 views
11

Tôi đang làm việc trên một dự án sử dụng canvas để tự động cắt hình ảnh, sau đó trả về URL dữ liệu của nó. Nó sử dụng hình ảnh từ một máy chủ bên ngoài, trong đó có các tiêu đề CORS thích hợp để cho phép các hình ảnh được chuyển đổi thành URI dữ liệu sau khi chúng được cắt mặc dù chúng có nguồn gốc chéo.Canvas.toDataURL() hoạt động trong tất cả các trình duyệt ngoại trừ IE10

Mã hoạt động hoàn hảo (và không có lỗi bảo mật!) Trong tất cả các trình duyệt ngoại trừ IE 10, trong đó nó ném 'SCRIPT5022: SecurityError' khi canvas.toDataURL() được gọi.

Đây có phải là lỗi trong IE hay điều gì đó mà tôi cần phải làm khác trong mã của mình để làm cho nó hoạt động trong Idiot Exploder? Cảm ơn. -Scott

EDIT Đây là (hầu hết) mã tôi đang sử dụng để tạo và vẽ canvas;

var canvas = document.createElement('canvas'); 
var ctx = canvas.getContext('2d'); 
var img = new Image(); 
img.src = imageServerURL + '?id=' + imageIdToGet; // imageServerURL points to a different domain but the server has headers allowing requests from my domain 
/* 
    code here that defines the cropping area, in variables like ulX, lrY, etc. 
*/ 
ctx.beginPath(); 
ctx.moveTo(ulX, ulY); 
ctx.lineTo(urX, urY); 
ctx.lineTo(lrX, lrY); 
ctx.lineTo(llX, llY); 
ctx.closePath(); 
ctx.clip(); 
ctx.drawImage(img, 0, 0); 
var url = canvas.toDataURL(); // This succeeds in all other browsers but throws a SecurityError in IE 
+0

Để bắt đầu, hãy cho chúng tôi biết mã của bạn và/hoặc giải thích cách tạo canvas này. –

+0

Đã chỉnh sửa câu hỏi gốc. –

Trả lời

5

Tôi không tin rằng IE10 có hỗ trợ CORS cho hình ảnh. This MDN article có vẻ như ngược lại.

Theo các tiểu bang Bài chi tiết:

Mặc dù bạn có thể sử dụng hình ảnh mà không CORS chính trong khung hình của bạn, làm như vậy taints canvas. Khi canvas đã bị nhiễm độc, bạn không còn có thể kéo dữ liệu ra khỏi canvas nữa. Ví dụ, bạn không còn có thể sử dụng các phương thức toBlob(), toDataURL() hoặc getImageData() của canvas nữa; làm như vậy sẽ ném một lỗi bảo mật.

Vì vậy, có vẻ như bạn sẽ phải proxy hình ảnh từ cùng một nguồn gốc/tên miền giống như lưu trữ mã được đề cập trước khi thử thực hiện việc này, ít nhất là cho IE10 và Opera.

Để xử lý các trình duyệt không có hỗ trợ CORS cho hình ảnh, bạn sẽ cần ủy quyền phía máy chủ hình ảnh. Bạn có thể làm điều này khá dễ dàng bằng cách gửi nguồn của hình ảnh đến một điểm cuối đã biết trên máy chủ cục bộ của bạn và chuyển vào url nguồn của hình ảnh dưới dạng tham số truy vấn.

Ví dụ:

var sourceImageUrl = "https://www.google.com/images/srpr/logo4w.png", 
    localProxyEndpoint = "/imageproxy", 
    image = new Image(); 

image.src = localProxyEndpoint + "?source=" + encodeURIComponent(sourceImageUrl); 

Bây giờ, server-side, bạn sẽ xử lý yêu cầu GET này, rip off giá trị của tham số source từ URI, lấy hình ảnh từ các nguồn, và gửi lại trong phản ứng của bạn.

+0

Nó hoạt động như mong đợi trong Opera 15 trên Windows 8. Giải pháp "proxy" này đòi hỏi những gì? –

+0

Có thể hoạt động trong Opera 15 kể từ phiên bản Opera đó dựa trên Chromium. Tôi sẽ chỉnh sửa câu trả lời của mình với nhiều chi tiết hơn một chút. –

+0

@ScottOdle Tôi đã cập nhật câu trả lời của mình với một số chi tiết. –

19

Thật không may, IE10 vẫn là trình duyệt phổ biến duy nhất không hỗ trợ CORS cho hình ảnh được vẽ vào Canvas ngay cả khi tiêu đề CORS được đặt đúng. Nhưng có giải pháp cho điều đó thông qua XMLHttpRequest thậm chí không cần ủy quyền hình ảnh trên phía máy chủ:

var xhr = new XMLHttpRequest(); 
xhr.onload = function() { 
    var url = URL.createObjectURL(this.response); 
    img.src = url; 

    // here you can use img for drawing to canvas and handling 

    // don't forget to free memory up when you're done (you can do this as soon as image is drawn to canvas) 
    URL.revokeObjectURL(url); 
}; 
xhr.open('GET', url, true); 
xhr.responseType = 'blob'; 
xhr.send(); 
+0

Điều này thật tuyệt! Cũng làm việc cho IE 11 và xóa các vấn đề với việc sử dụng ctx.getImageData(). Cảm ơn! –

+2

Tôi đang sử dụng fabricJS và có cùng sự cố với IE. Thay đổi duy nhất tôi phải làm từ ví dụ của bạn là revokeObjectURL cho đến khi hình ảnh đã tải 'img.onload = function (e) {...} 'Bạn có thể tìm thấy một ví dụ hoàn chỉnh ở đây http://www.html5rocks.com/en/tutorials/file/xhr2/#toc-reponseTypeBlob – mbenegas

+9

Điều này không hoạt động khi url là dữ liệu uri (dữ liệu: hình ảnh/svg + xml ; base64, ...) – vbarbarosh

Các vấn đề liên quan