2015-10-01 51 views
2

我試圖在畫布上繪製圖像,然後得到它的dataURL(),但返回的數據如空。CanvasContext2D drawImage()問題[onload和CORS]

當我在控制檯檢查它,我看到有字符串中有很多A:("data:image/png;base64,iVBO..some random chars... bQhfoAAAAAAAAAA... a lot of A ...AAAASUVORK5CYII="

當我嘗試追加畫布到文檔中,沒有任何拉伸,我不沒有在控制檯中拋出任何錯誤。

這裏有什麼問題?

這裏是我的代碼:

var img = new Image(); 
img.src = "http://somerandomWebsite/picture.png"; 
var canvas = document.createElement('canvas'); 
canvas.width = img.width; 
canvas.height = img.height; 
var context = canvas.getContext('2d'); 
context.drawImage(img, 0,0); // this doesn't seem to work 
var dataURL = canvas.toDataURL(); // this will give me a lot of "A"  
doSomething(dataURL); 

而且,做一個快速刷新時,圖像被正確地繪製在畫布上,但我得到了在控制檯中的錯誤信息和dataURL是空的。

Firefox中的消息是:「SecurityError:操作不安全。」,
in Chrome它是「Uncaught SecurityError:無法執行'HTMLCanvasElement'上的'toDataURL':受污染的畫布可能無法導出。」,
和IE我剛剛得到「SecurityError」

這是什麼意思?

+0

這篇文章的目的是爲每週20個左右的規範,我們得到關於這個特定問題。請讓我知道它是否可以改進。 – Kaiido

+0

在做任何與他們更相關的事情之前,不僅僅是加載圖像的要點?如果你認爲參考dataURL很有用,你應該提及(可能的)CORS問題。無論如何+1維基的想法/努力。 – GameAlchemist

+0

@GameAlchemist你是對的,我試圖將這兩個問題結合起來,因爲它們非常相似,並且經常成對出現。我在答案中談到了CORS問題。不知道搜索引擎如何處理這個問題,也許我應該在問題中添加「canvas is tainted」消息錯誤。無論如何,我問這個問題也轉換爲wiki,這樣,你就可以編輯它。 – Kaiido

回答

2

你必須等待你的圖像有加載纔可以在畫布上繪製它。

要做到這一點,只需使用<img>元素的load事件處理程序:

// create a new image 
var img = new Image(); 
// declare a function to call once the image has loaded 
img.onload = function(){ 
    var canvas = document.createElement('canvas'); 
    canvas.width = img.width; 
    canvas.height = img.height; 
    var context = canvas.getContext('2d'); 
    context.drawImage(img, 0,0); 
    var dataURL = canvas.toDataURL(); 
    // now you can do something with the dataURL 
    doSomething(dataURL); 
} 
// now set the image's src 
img.src = "http://somerandomWebsite/picture.png"; 

而且,在畫布context.toDataURL()context.getImageData正常工作,你必須讓你的圖像資源在cross-origin compliant way,否則畫布會「污染」,這意味着任何獲取像素數據的方法都將被阻止。

  • 如果您的圖片來自相同的服務器,沒問題。
  • 如果您的圖像是由外部服務器提供的,請確保它允許您在其跨源標頭中,並將img.crossOrigin設置爲"use-credentials"
  • 如果服務器確實允許匿名請求,則可以將img.crossOrigin設置爲"anonymous"

諾塔Bene的CORS頭由服務器發送時,cross-origin屬性只會讓它知道要使用CORS來獲取圖像數據,在沒有辦法,你可以,如果繞過它服務器設置不正確。
另外一些UserAgents(IE & Safari)仍未實現此屬性。

邊緣情況:如果你的一些圖片是從你的服務器和一些是從CORS標準的一個,那麼你可能想,如果你在該cross-origin屬性設置爲"anonymous"使用onerror事件處理程序應該解僱非CORS服務器。

function corsError(){ 
    this.crossOrigin=''; 
    this.src=''; 
    this.removeEventListener('error', corsError, false); 
} 
img.addEventListener('error', corsError, false);