有没有办法在画布中呈现任意 HTML 元素(然后访问它的缓冲区......)。
6 回答
您目前不会获得真正的 HTML 渲染<canvas>
本身,因为画布上下文没有渲染 HTML 元素的功能。
有一些仿真:
html2canvas 项目http://html2canvas.hertzen.com/index.html(基本上是基于 Javascript + canvas 构建的 HTML 渲染器尝试)
<canvas>
根据您的用例,HTML 到 SVG可能是可能的:
https://github.com/miohtama/Krusovice/blob/master/src/tools/html2svg2canvas.js
此外,如果您使用的是 Firefox ,您可以破解一些扩展权限,然后渲染一个 DOM 窗口<canvas>
看看MDN(存档)
它将使用创建 SVG 图像来呈现 html 元素。
例如:
有<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>
画布元素中。
这是将 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>
这是将任意 HTML 渲染到画布中的代码:
function render_html_to_canvas(html, ctx, x, y, width, height) {
var xml = html_to_xml(html);
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;
}
例子:
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>
CSSelement()
函数最终可能会帮助这里的一些人,即使它不是问题的直接答案。它允许您使用一个元素(以及所有子元素,包括视频、跨域 iframe 等)作为背景图像(以及您通常url(...)
在 CSS 代码中使用的任何其他位置)。这是一篇博客文章,展示了你可以用它做什么。
它自 2011 年以来已在 Firefox 中实现,并且正在 Chromium/Chrome 中进行考虑(如果您关心此功能,请不要忘记给这个问题一个星号)。
RasterizeHTML 是一个非常好的项目,但如果您需要访问画布,它在 chrome 上将无法工作。由于使用<foreignObject>
.
如果您需要访问画布,那么您可以使用 html2canvas
我正在尝试寻找另一个项目,因为 html2canvas 的性能非常慢
根据 HTML 规范,您不能访问 Canvas 的元素。您可以获取它的上下文,并在其中绘制操作它,但仅此而已。
但是,您可以使用 aa 将 Canvas 和 html 元素放在同一个 div 中position: relative
,然后将 canvas 和其他元素设置为position: absolute
. 这样,他们将处于彼此之上。然后您可以使用left
和right
CSS 属性来定位 html 元素。
如果元素没有出现,可能画布在它之前,所以使用z-index
CSS 属性将它带到画布之前。