【问题标题】:Inserting HTML into canvas without creating CORS restriction将 HTML 插入画布而不创建 CORS 限制
【发布时间】:2015-02-23 12:05:47
【问题描述】:

我正在尝试使用 MDN's method 从添加了 HTML 元素数据的画布中获取图像数据。插入 HTML 数据后,我无法再访问画布的图像数据(在 Chrome 中):

//This function is a direct copy of https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas#JavaScript
onload = function() {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');

  var data = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
      '<foreignObject width="100%" height="100%">' +
      '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:14px">' +
      'example' +
      '</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);
    getData(ctx);
  };

  img.src = url;
};

//the part where it goes wrong:
function getData(ctx) {
  try {
    ctx.getImageData(0,0,100,100);
  } catch(e) {
    alert(e);
  }
}
&lt;canvas id="canvas"&gt;&lt;/canvas&gt;

我的问题是:是否可以插入 HTML 数据,并且仍然能够访问图像数据?

【问题讨论】:

    标签: javascript google-chrome canvas cors


    【解决方案1】:

    再环顾四周后,我发现data: URI 在插入完全相同的 HTML 位后仍然允许访问图像数据。尽管 data: URI 比 blobs 慢,但这似乎是最好的方法。

    onload = function() {
      var canvas = document.getElementById('canvas');
      var ctx = canvas.getContext('2d');
    
      var data = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
          '<foreignObject width="100%" height="100%">' +
          '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:14px">' +
          'example' +
          '</div>' +
          '</foreignObject>' +
          '</svg>';
      var DOMURL = window.URL || window.webkitURL || window;
      var img = new Image();
      var url = 'data:image/svg+xml;base64,' + btoa(data);
    
      img.onload = function () {
        ctx.drawImage(img, 0, 0);
        DOMURL.revokeObjectURL(url);
        getData(ctx);
      };
      img.src = url;
    };
    
    function getData(ctx) {
      try {
        ctx.getImageData(0,0,100,100);
        alert('Finished without errors');
      } catch(e) {
        alert(e);
      }
    }
    &lt;canvas id="canvas"&gt;&lt;/canvas&gt;

    【讨论】:

      【解决方案2】:

      不,画布被 SVG 污染,因此不再允许使用 context.getImageData。由于跨域安全问题,这已成为必要。

      (有时不令人满意的)解决方法是将 html 从您的服务器反弹并使用无头浏览器(我推荐 PhantomJS)将 html 转换为图像。然后将该图像返回给客户端。由于html-as-image不是跨域的,所以不会污染画布,可以使用context.getImageData。

      【讨论】:

      • 好的,但是没有其他方法可以做到吗?只要不包含外来对象,将 svg 数据添加到画布就可以正常工作,那么没有其他方法可以插入 html 内容并仍然访问图像数据吗?
      • 我想我必须处理这个问题。我宁愿避免服务器端处理,但如果这是唯一的方法,我想我别无选择。
      • 是的,坏人已经毁了我们的 html 捕获。未来的浏览器正在努力放宽 CORS 限制,但尚未完成修复。
      • 我找到了另一种方法来避免使用服务器端处理并仍然达到预期的结果(请参阅我的答案)。我会在可能的情况下将我的“接受”移到那里,因为这是我最终使用的,所以我为 -15 代表道歉。
      • 没问题...很高兴你把它整理好了! :-) 虽然您的新技术不会启用全部范围的 html+css,但它适用于包括自动换行在内的基本布局内容。干杯!
      猜你喜欢
      • 2014-12-20
      • 1970-01-01
      • 1970-01-01
      • 2021-09-12
      • 2013-05-21
      • 1970-01-01
      • 2011-07-21
      • 2011-09-07
      • 2017-06-16
      相关资源
      最近更新 更多