Por que canvas.toDataURL () lança uma exceção de segurança?

Eu não dormi o suficiente ou o quê? Este código a seguir

var frame=document.getElementById("viewer"); frame.width=100; frame.height=100; var ctx=frame.getContext("2d"); var img=new Image(); img.src="http://sofpt.miximages.com/javascript/logo_huge_domains.gif" img.onload=function() { // draw image ctx.drawImage(img, 0, 0) // Here's where the error happens: window.open(frame.toDataURL("image/png")); } 

está jogando este erro:

 SECURITY_ERR: DOM Exception 18 

Não tem como isso não funcionar! Alguém pode explicar isso, por favor?

Nas especificações diz:

Sempre que o método toDataURL () de um elemento de canvas cujo sinalizador de origem-limpo está definido como false for chamado, o método deve gerar uma exceção SECURITY_ERR.

Se a imagem estiver vindo de outro servidor, não acho que você possa usar toDataURL ()

Definir atributo de origem cruzada nos objects de imagem funcionou para mim (eu estava usando fabricjs)

  var c = document.createElement("img"); c.onload=function(){ // add the image to canvas or whatnot c=c.onload=null }; c.setAttribute('crossOrigin','anonymous'); c.src='http://google.com/cat.png'; 

Para aqueles que usam o fabricjs, veja como corrigir o Image.fromUrl

 // patch fabric for cross domain image jazz fabric.Image.fromURL=function(d,f,e){ var c=fabric.document.createElement("img"); c.onload=function(){ if(f){f(new fabric.Image(c,e))} c=c.onload=null }; c.setAttribute('crossOrigin','anonymous'); c.src=d; }; 

Se a imagem estiver hospedada em um host que define Access-Control-Allow-Origin ou Access-Control-Allow-Credentials, você poderá usar o recurso CORS (Cross Origin Resource Sharing). Veja aqui (o atributo crossorigin) para mais detalhes.

Sua outra opção é o servidor ter um terminal que busca e exibe uma imagem. (por exemplo, http: // your_host / endpoint? url = URL ) A desvantagem dessa abordagem é a latência e a busca teoricamente desnecessária.

Se houver mais soluções alternativas, eu estaria interessado em ouvir sobre elas.

Parece que existe uma maneira de impedir que, se o hosting de imagens puder fornecer os seguintes headers HTTP para os resources de imagem e o navegador suportar CORS:

  access-controle-permitir-origem: *
 access-controle-permitir-credenciais: true 

Está escrito aqui: http://www.w3.org/TR/cors/#use-cases

Eu tive o mesmo problema e todas as imagens estão hospedadas no mesmo domínio … Então, se alguém está tendo o mesmo problema, aqui está como eu resolvi:

Eu tinha dois botões: um para gerar a canvas e outro para gerar a imagem da canvas. Só funcionou para mim, e desculpe por não saber porque, quando escrevi todo o código no primeiro botão. Então, quando clico, gero a canvas e a imagem ao mesmo tempo …

Eu sempre tenho esse problema de segurança quando os códigos estavam em funções diferentes … = /

Finalmente encontrei a solução. Só precisa adicionar o crossOrigin como terceiro param em fromURL func

 fabric.Image.fromURL(imageUrl, function (image) { //your logic }, { crossOrigin: "Anonymous" }); 

Você não pode colocar espaços em seu ID

Atualizar

Meu palpite é que a imagem está em um servidor diferente do que você está executando o script. Consegui duplicar o erro ao executá-lo na minha própria página, mas funcionou bem no momento em que usei uma imagem hospedada no mesmo domínio. Por isso, é relacionado à segurança – coloque a imagem em seu site. Alguém sabe por que esse é o caso?

Consegui fazer funcionar usando isso:

Escreva isso na primeira linha do seu .htaccess no seu servidor de origem

 Header add Access-Control-Allow-Origin "*" 

Então, ao criar um elemento , faça o seguinte:

 // jQuery var img = $('')[0] // or pure var img = document.createElement('img'); img.src='http://your_server/img.png'; img.setAttribute('crossOrigin','anonymous'); 

Se você estiver simplesmente desenhando algumas imagens em uma canvas, verifique se está carregando as imagens do mesmo domínio.

http://www.example.com é diferente de example.com

Portanto, verifique se suas imagens e o URL que você tem em sua barra de endereço são os mesmos, www ou não.

Estou usando o fabric.js e poderia resolver isso usando toDatalessJSON em vez de toDataURL:

 canvas.toDatalessJSON({ format: 'jpeg' }).objects[0].src 

Editar: Nevermind. Isso resulta em apenas a imagem de plano de fundo sendo exportada para JPG, sem o desenho na parte superior, portanto, não foi totalmente útil, afinal.