为什么将画布保存为jpeg或pdf会导致黑色图像?

时间:2022-01-11 21:19:52

I have the following code:

我有以下代码:

var imgData;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();

imageObj.onload = function() {
    context.drawImage(imageObj, 0, 0);
};
imgData = canvas.toDataURL("image/jpeg", 1.0);
imageObj.src = 'http://images.visitcanberra.com.au/images/canberra_hero_image.jpg';

When a user click on JPG or PDF file is downloaded. There's following code for download JPG:

当用户点击JPG或PDF文件时下载。下载JPG的代码如下:

function saveAsJPG(){
    var pom = document.createElement('a');
    pom.setAttribute('href', imgData);
    pom.setAttribute('download', 'img.jpg');

    if (document.createEvent) {
        var event = document.createEvent('MouseEvents');
        event.initEvent('click', true, true);
        pom.dispatchEvent(event);
    } else {
        pom.click();
    }
}

And following code for PDF:

并遵循PDF的代码:

function saveAsPDF(){
          var pdf = new jsPDF();        
          pdf.addImage(imgData, 'JPEG', 0, 0);
          pdf.save("download.pdf");
      }

Code works "correct" expect issue that it don't download image but black screen. There is working JSFiddle example: https://jsfiddle.net/1c1o8wjx/

代码工作“正确”期待它不下载图像而是黑屏的问题。有一个工作JSFiddle的例子:https://jsfiddle.net/1c1o8wjx/

Could you help me to understand possible reasons why it's not working as supposed?

你能帮助我理解为什么它不能按照假设工作的原因吗?

2 个解决方案

#1


You are loading the balloon-city image from a domain that's different from the web page's domain. For security reasons, this "cross-domain" image drawing will cause the browsers to "taint" the canvas. Tainted canvas's are not allowed to use .toDataURL to export their content.

您正在从与网页的域不同的域中加载气球城市图像。出于安全原因,这种“跨域”图像绘制将导致浏览器“污染”画布。受污染的画布不允许使用.toDataURL导出其内容。

This "cross-domain" drawing to the canvas is why you're getting an all black file...#myCanvas has not actually created your dataURL because the browser disallowed it.

这个“跨域”绘图到画布是为什么你得到一个全黑的文件...#myCanvas实际上没有创建你的dataURL,因为浏览器不允许它。

The workaround is to host your image on the same domain as your web page. Then the browser will allow canvas.toDataURL and your images will appear as they should.

解决方法是将您的图像托管在与您的网页相同的域中。然后浏览器将允许canvas.toDataURL,您的图像将按原样显示。

Example code and a Demo:

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var imgData;
var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/canberra_hero_image.jpg";
function start(){
  canvas.width=img.width;
  canvas.height=img.height;
  ctx.drawImage(img,0,0);
  imgData=canvas.toDataURL('image/jpeg',1.0);
  $('#printJPG').on('click',saveAsJPG);
}

function saveAsJPG(){
  var pom = document.createElement('a');
  pom.setAttribute('href', imgData);
  pom.setAttribute('download', 'img.jpg');

  if (document.createEvent) {
    var event = document.createEvent('MouseEvents');
    event.initEvent('click', true, true);
    pom.dispatchEvent(event);
  } else {
    pom.click();
  }
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
  <li><a href="#" id="printJPG">Print as JPG</a></li>
</ul>    
<canvas id="canvas" width=300 height=300></canvas>

Also note that Internet Explorer does not currently support the "download" attribute.

另请注意,Internet Explorer目前不支持“下载”属性。

#2


You must wait for the image to load before calling canvas.toDataURL("image/jpeg", 1.0);. Try the following:

在调用canvas.toDataURL(“image / jpeg”,1.0);之前,必须等待图像加载。请尝试以下方法:

var imgData;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();

imageObj.onload = function() {
    context.drawImage(imageObj, 0, 0);
    imgData = canvas.toDataURL("image/jpeg", 1.0);
};
imageObj.src = 'http://images.visitcanberra.com.au/images/canberra_hero_image.jpg';

It won't work in the fiddle because of a security error (the image belongs to a different domain). Try it in your webpage.

由于安全性错误(图像属于不同的域),它在小提琴中不起作用。在您的网页中试用它。

#1


You are loading the balloon-city image from a domain that's different from the web page's domain. For security reasons, this "cross-domain" image drawing will cause the browsers to "taint" the canvas. Tainted canvas's are not allowed to use .toDataURL to export their content.

您正在从与网页的域不同的域中加载气球城市图像。出于安全原因,这种“跨域”图像绘制将导致浏览器“污染”画布。受污染的画布不允许使用.toDataURL导出其内容。

This "cross-domain" drawing to the canvas is why you're getting an all black file...#myCanvas has not actually created your dataURL because the browser disallowed it.

这个“跨域”绘图到画布是为什么你得到一个全黑的文件...#myCanvas实际上没有创建你的dataURL,因为浏览器不允许它。

The workaround is to host your image on the same domain as your web page. Then the browser will allow canvas.toDataURL and your images will appear as they should.

解决方法是将您的图像托管在与您的网页相同的域中。然后浏览器将允许canvas.toDataURL,您的图像将按原样显示。

Example code and a Demo:

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var imgData;
var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/canberra_hero_image.jpg";
function start(){
  canvas.width=img.width;
  canvas.height=img.height;
  ctx.drawImage(img,0,0);
  imgData=canvas.toDataURL('image/jpeg',1.0);
  $('#printJPG').on('click',saveAsJPG);
}

function saveAsJPG(){
  var pom = document.createElement('a');
  pom.setAttribute('href', imgData);
  pom.setAttribute('download', 'img.jpg');

  if (document.createEvent) {
    var event = document.createEvent('MouseEvents');
    event.initEvent('click', true, true);
    pom.dispatchEvent(event);
  } else {
    pom.click();
  }
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
  <li><a href="#" id="printJPG">Print as JPG</a></li>
</ul>    
<canvas id="canvas" width=300 height=300></canvas>

Also note that Internet Explorer does not currently support the "download" attribute.

另请注意,Internet Explorer目前不支持“下载”属性。

#2


You must wait for the image to load before calling canvas.toDataURL("image/jpeg", 1.0);. Try the following:

在调用canvas.toDataURL(“image / jpeg”,1.0);之前,必须等待图像加载。请尝试以下方法:

var imgData;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();

imageObj.onload = function() {
    context.drawImage(imageObj, 0, 0);
    imgData = canvas.toDataURL("image/jpeg", 1.0);
};
imageObj.src = 'http://images.visitcanberra.com.au/images/canberra_hero_image.jpg';

It won't work in the fiddle because of a security error (the image belongs to a different domain). Try it in your webpage.

由于安全性错误(图像属于不同的域),它在小提琴中不起作用。在您的网页中试用它。