如何将图像添加到画布?

时间:2016-01-20 07:09:03

标签: canvas html2canvas

尝试对<img>标记应用模糊效果时,画布上不显示任何内容。

我正在<img>传递<foreignObject>标记,以便应用模糊效果。

这种技术适用于文本,但不适用于<img>

这是我的代码。

var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');

var data = '<svg xmlns="http://www.w3.org/2000/svg" width="700" height="350">'+
' <foreignObject width="100%" height="100%">'+
'  <div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">'+
   //start code
'  <div id="custom_image_box" class="col-xs-12 edit_div" style="background-color: rgb(255, 255, 255);">'+
'   <div id="added_background_0" class="ui-widget-content draggable resizable ui-draggable ui-resizable ui-resizable-autohide" style="position: absolute; z-index: 0; -webkit-filter: blur(2px);">'+
'    <img id="image_0" class="image_resize" src="http://localhost/image_designer/htdocs/assets/upload_image/1450334949.jpg" style=" width: 100%; height: 100%;">'+
'    <div class="ui-resizable-handle ui-resizable-nw" id="nwgrip" "="" style="display: none;">'+
'    </div>'+
'    <div class="ui-resizable-handle ui-resizable-ne" id="negrip" style="display: none;">'+
'    </div>'+
'    <div class="ui-resizable-handle ui-resizable-sw" id="swgrip" style="display: none;">'+
'    </div>'+
'    <div class="ui-resizable-handle ui-resizable-se" id="segrip" style="display: none;">'+
'    </div>'+
'   </div>'+
'  </div>'+
  //end code
'  </div>'+
' </foreignObject>'+
'</svg>';

var DOMURL = window.URL || window.webkitURL || window;

var img = new Image();
var svg = new Blob([data], {
  type: 'image/svg+xml; charset=utf-8'
});
var url = DOMURL.createObjectURL(svg);

img.onload = function() {
  ctx.drawImage(img, 0, 0);
  DOMURL.revokeObjectURL(url);
}

img.src = url;
<canvas id="mycanvas" width="700" height="300"></canvas>

1 个答案:

答案 0 :(得分:0)

首先,

为了正确显示<foreignObject>标记中的<img>,您必须使用完美编写的HTML。您忘记关闭<img/>标记,因此未显示任何内容。 "="" div上还有一些奇怪的#nwgrip属性

要避免此类问题,最好的方法是使用DOM,并调用new XMLSerializer.serializeToString(yourDOMElement)。这样,浏览器就已经完成了解析,并且您的标记将被清理。

清理代码,显示空图像,模糊:

var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');

var data = '<svg xmlns="http://www.w3.org/2000/svg" width="700" height="350">' +
  '<foreignObject width="100%" height="100%">' +
   '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">' +
    '<div style="background-color: rgb(255, 255, 255);">' +
     '<div style="position: absolute; z-index: 0; -webkit-filter: blur(2px); filter: blur(2px);">' +
      // added some text to show the blur effect does work
      'some text'+
      '<img src="https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png" style="width: 100%; height: 100%;"/>' +
     '</div>' +
    '</div>' +
   '</div>' +
  '</foreignObject>' +
 '</svg>';

var DOMURL = window.URL || window.webkitURL || window;

var img = new Image();
var svg = new Blob([data], {
  type: 'image/svg+xml; charset=utf-8'
});
var url = DOMURL.createObjectURL(svg);

img.onload = function() {
  ctx.drawImage(img, 0, 0);
  DOMURL.revokeObjectURL(url);
}
img.src = url;
<canvas id="mycanvas" width="700" height="350"></canvas>

其次,

您无法从<img>标记加载任何外部数据。因此,在您的情况下,这意味着您不想加载要显示的<img>资源。

一个解决方案,首先将图像转换为dataURL版本,然后将img标记的src设置为所需的dataURL:

var srcToDataURL = function(src, callback) {
  var ctx = document.createElement('canvas').getContext('2d');
  var img = new Image();
  img.crossOrigin = "anonymous";
  img.onload = function() {
    ctx.canvas.width = this.width;
    ctx.canvas.height = this.height;
    ctx.drawImage(this, 0, 0);
    callback(ctx.canvas.toDataURL());
  }
  img.src = src;
};

var src = "https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png";

srcToDataURL(src, function(imgData) {
  var canvas = document.getElementById('mycanvas');
  var ctx = canvas.getContext('2d');
  var data = '<svg xmlns="http://www.w3.org/2000/svg" width="700" height="350">' +
    '<foreignObject width="100%" height="100%">' +
    '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">' +
    '<div style="background-color: rgb(255, 255, 255);">' +
    '<div style="position: absolute; z-index: 0; -webkit-filter: blur(2px); filter: blur(2px);">' +
    '<img src="'+  imgData + '" style="width: 100%; height: 100%;"/>' +
    '</div>' +
    '</div>' +
    '</div>' +
    '</foreignObject>' +
    '</svg>';

  var DOMURL = window.URL || window.webkitURL || window;

  var img = new Image();
  var svg = new Blob([data], {
    type: 'image/svg+xml; charset=utf-8'
  });
  var url = DOMURL.createObjectURL(svg);

  img.onload = function() {
    ctx.drawImage(img, 0, 0);
    DOMURL.revokeObjectURL(url);
  }
  img.src = url;
});
<canvas id="mycanvas" width="700" height="350"></canvas>

<强>第三, IE&lt; Edge和Safari 9(最新版)不支持在画布上绘制<foreignObject>,并且会污染它。 html2canvas将无法再捕捉您的画布。

如果您必须支持这些浏览器,更好的方法是使用像StackBlur这样的库直接将图像模糊到画布上。

作为旁注,您不需要使用Blob构造函数将svg附加到画布上,dataURI方式适用于更多浏览器,并且知道的错误较少:

var srcToDataURL = function(src, callback) {
  var ctx = document.createElement('canvas').getContext('2d');
  var img = new Image();
  img.crossOrigin = "anonymous";
  img.onload = function() {
    ctx.canvas.width = this.width;
    ctx.canvas.height = this.height;
    ctx.drawImage(this, 0, 0);
    callback(ctx.canvas.toDataURL());
  }
  img.src = src;
};

var src = "https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png";

srcToDataURL(src, function(imgData) {
  var canvas = document.getElementById('mycanvas');
  var ctx = canvas.getContext('2d');
  var data = '<svg xmlns="http://www.w3.org/2000/svg" width="700" height="350">' +
    '<foreignObject width="100%" height="100%">' +
    '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">' +
    '<div style="background-color: rgb(255, 255, 255);">' +
    '<div style="position: absolute; z-index: 0; -webkit-filter: blur(2px); filter: blur(2px);">' +
    '<img src="'+  imgData + '" style="width: 100%; height: 100%;"/>' +
    '</div>' +
    '</div>' +
    '</div>' +
    '</foreignObject>' +
    '</svg>';

  var img = new Image();
  var url = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(data);

  img.onload = function() {
    ctx.drawImage(img, 0, 0);
  }
  img.src = url;
});
<canvas id="mycanvas" width="700" height="350"></canvas>