将 HTML 元素渲染到 <canvas>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12652769/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 03:06:00  来源:igfitidea点击:

Rendering HTML elements to <canvas>

htmlhtml5-canvas

提问by gotch4

Is there a way to have an arbitrary HTML element rendered in a canvas (and then access its buffer...).

有没有办法在画布中呈现任意 HTML 元素(然后访问其缓冲区......)。

采纳答案by Mikko Ohtamaa

You won't get real HTML rendering to <canvas>per se currently, because canvas context does not have functions to render HTML elements.

<canvas>目前不会获得真正的 HTML 渲染本身,因为画布上下文没有渲染 HTML 元素的功能。

There are some emulations:

有一些模拟:

html2canvas project http://html2canvas.hertzen.com/index.html(basically a HTML renderer attempt built on Javascript + canvas)

html2canvas 项目http://html2canvas.hertzen.com/index.html(基本上是基于 Javascript + canvas 构建的 HTML 渲染器尝试)

HTML to SVG to <canvas>might be possible depending on your use case:

<canvas>根据您的用例,HTML 到 SVG可能是可能的:

https://github.com/miohtama/Krusovice/blob/master/src/tools/html2svg2canvas.js

https://github.com/miohtama/Krusovice/blob/master/src/tools/html2svg2canvas.js

Also if you are using Firefox you can hack some extendedpermissions and then render a DOM window to <canvas>

此外,如果您使用的是 Firefox,您可以破解一些扩展权限,然后将 DOM 窗口呈现给<canvas>

https://developer.mozilla.org/en-US/docs/HTML/Canvas/Drawing_Graphics_with_Canvas?redirectlocale=en-US&redirectslug=Drawing_Graphics_with_Canvas#Rendering_Web_Content_Into_A_Canvas

https://developer.mozilla.org/en-US/docs/HTML/Canvas/Drawing_Graphics_with_Canvas?redirectlocale=en-US&redirectslug=Drawing_Graphics_with_Canvas#Rendering_Web_Content_Into_A_Canvas

回答by Suresh Mahawar

Take a look on MDN

看看MDN

It will render html element using creating SVG images.

它将使用创建 SVG 图像来呈现 html 元素。

For Example:There is <em>I</em> like <span style="color:white; text-shadow:0 0 2px blue;">cheese</span>HTML element. And I want to add it into <canvas id="canvas" style="border:2px solid black;" width="200" height="200"></canvas>Canvas Element.

例如:<em>I</em> like <span style="color:white; text-shadow:0 0 2px blue;">cheese</span>HTML 元素。我想将它添加到<canvas id="canvas" style="border:2px solid black;" width="200" height="200"></canvas>Canvas Element 中。

Here is Javascript Code to add HTML element to canvas.

这是将 HTML 元素添加到 canvas 的 Javascript 代码

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:40px">' +
  '<em>I</em> like <span style="color:white; text-shadow:0 0 2px blue;">cheese</span>' +
  '</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="canvas" style="border:2px solid black;" width="200" height="200"></canvas>

回答by CpnCrunch

Here is code to render arbitrary HTML into a canvas:

这是将任意 HTML 渲染到画布中的代码:

function render_html_to_canvas(html, ctx, x, y, width, height) {
    var xml = html_to_xml(txt);
    xml = xml.replace(/\#/g, '%23');
    var data = "data:image/svg+xml;charset=utf-8,"+'<svg xmlns="http://www.w3.org/2000/svg" width="'+width+'" height="'+height+'">' +
                        '<foreignObject width="100%" height="100%">' +
                        xml+
                        '</foreignObject>' +
                        '</svg>';

    var img = new Image();
    img.onload = function () {
        ctx.drawImage(img, x, y);
    }
    img.src = data;
}

function html_to_xml(html) {
    var doc = document.implementation.createHTMLDocument('');
    doc.write(html);

    // You must manually set the xmlns if you intend to immediately serialize     
    // the HTML document to a string as opposed to appending it to a
    // <foreignObject> in the DOM
    doc.documentElement.setAttribute('xmlns', doc.documentElement.namespaceURI);

    // Get well-formed markup
    html = (new XMLSerializer).serializeToString(doc.body);
    return html;
}

example:

例子:

const ctx = document.querySelector('canvas').getContext('2d');
const html = `
<p>this
<p>is <span style="color:red; font-weight: bold;">not</span>
<p><i>xml</i>!
<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABWElEQVQ4jZ2Tu07DQBBFz9jjvEAQqAlQ0CHxERQ0/AItBV9Ew8dQUNBQIho6qCFE4Nhex4u85OHdWAKxzfWsx0d3HpazdGITA4kROjl0ckFrnYJmQlJrKsQZxFOIMyEqIMpADGhSZpikB1hAGsovdxABGuepC/4L0U7xRTG/riG3J8fuvdifPKnmasXp5c2TB1HNPl24gNTnpeqsgmj1eFgayoHvRDWbLBOKJbn9WLGYflCCpmM/2a4Au6/PTjdH+z9lCJQ9vyeq0w/ve2kA3vaOnI6k4Pz+0Y24yP3Gapy+Bw6qdfsCRZfWSWgclCCVXTZu5LZFXKJJ2sepW2KYNCENB3U5pw93zLoDjNK6E7rTFcgbkGYJtiLckxCiw4W1OURsxUE5BokQiQj3JIToVtKwlhsurq+YDYbMBjuU/W3KtT3xIbrpAD7E60lwQohuaMtP8ldI0uMbGfC1r1zyWPUAAAAASUVORK5CYII=">`;
render_html_to_canvas(html, ctx, 0, 0, 300, 150);


function render_html_to_canvas(html, ctx, x, y, width, height) {
  var data = "data:image/svg+xml;charset=utf-8," + '<svg xmlns="http://www.w3.org/2000/svg" width="' + width + '" height="' + height + '">' +
    '<foreignObject width="100%" height="100%">' +
    html_to_xml(html) +
    '</foreignObject>' +
    '</svg>';

  var img = new Image();
  img.onload = function() {
    ctx.drawImage(img, x, y);
  }
  img.src = data;
}

function html_to_xml(html) {
  var doc = document.implementation.createHTMLDocument('');
  doc.write(html);

  // You must manually set the xmlns if you intend to immediately serialize     
  // the HTML document to a string as opposed to appending it to a
  // <foreignObject> in the DOM
  doc.documentElement.setAttribute('xmlns', doc.documentElement.namespaceURI);

  // Get well-formed markup
  html = (new XMLSerializer).serializeToString(doc.body);
  return html;
}
<canvas></canvas>

回答by Mohamed El Prince

RasterizeHTML is a very good project, but if you need to access the canvas it wont work on chrome. due to the use of <foreignObject>.

RasterizeHTML 是一个非常好的项目,但是如果您需要访问画布,它在 chrome 上不起作用。由于使用<foreignObject>.

If you need to access the canvas then you can use html2canvas

如果您需要访问画布,则可以使用 html2canvas

I am trying to find another project as html2canvas is very slow in performance

我正在尝试寻找另一个项目,因为 html2canvas 的性能非常慢

回答by Mohamed El Prince

The CSS element()functionmay eventually help some people here, even though it's not a direct answer to the question. It allows you to use an element (and all children, including videos, cross-domain iframes, etc.) as a background image (and anywhere else that you'd normally use url(...)in your CSS code). Here's a blog postthat shows what you can do with it.

CSSelement()函数最终可能会帮助这里的一些人,即使它不是问题的直接答案。它允许您使用元素(以及所有子元素,包括视频、跨域 iframe 等)作为背景图像(以及您通常url(...)在 CSS 代码中使用的任何其他地方)。这是一篇博客文章,展示了您可以用它做什么。

It has been implemented in Firefox since 2011, and is being consideredin Chromium/Chrome (don't forget to give the issue a star if you care about this functionality).

自 2011 年以来,它已在 Firefox 中实现,并且正在考虑在 Chromium/Chrome 中使用(如果您关心此功能,请不要忘记给该问题打个星)。

回答by Richard Otvos

According to the HTML specification you can't access the elements of the Canvas. You can get its context, and draw in it manipulate it, but that is all.

根据 HTML 规范,您无法访问 Canvas 的元素。您可以获取它的上下文,并在其中绘制并操作它,但仅此而已。

BUT, you can put both the Canvas and the html element in the same div with a aposition: relativeand then set the canvas and the other element to position: absolute. This ways they will be on the top of each other. Then you can use the leftand rightCSS properties to position the html element.

但是,您可以使用 aa 将 Canvas 和 html 元素放在同一个 div 中,position: relative然后将画布和另一个元素设置为position: absolute. 这样他们就会在彼此的顶部。然后您可以使用leftrightCSS 属性来定位 html 元素。

If the element doesn't shows up, maybe the canvas is before it, so use the z-indexCSS property to bring it before the canvas.

如果元素没有出现,可能是画布在它之前,所以使用z-indexCSS 属性将它放在画布之前。