是否有一种方法可以在画布中呈现任意HTML元素(然后访问其缓冲区)...。
是否有一种方法可以在画布中呈现任意HTML元素(然后访问其缓冲区)...。
目前来看,你无法直接将HTML元素渲染到<canvas>
中,因为canvas上下文并没有用于渲染HTML元素的功能。
但有一些模拟方法:
html2canvas项目http://html2canvas.hertzen.com/index.html(基本上是一个基于Javascript + canvas的HTML渲染器尝试)
根据您的使用情况,可能可以通过将HTML转换为SVG再绘制到<canvas>
上来实现:
https://github.com/miohtama/Krusovice/blob/master/src/tools/html2svg2canvas.js
此外,如果您正在使用Firefox浏览器,可以通过获取扩展权限,然后将DOM窗口渲染到<canvas>
中。
给定加载到JS string
值中的HTML,可以将其呈现为<canvas>
或<img>
元素。这是通过SVG的<foreignObject>
元素来完成的。
以下是在Javascript中将HTML string
呈现为<canvas>
元素或<img />
元素的工作示例:
<canvas>
元素:const renderThisHtml = `<em>I</em> like <span style="color:white; text-shadow:0 0 2px blue;">cheese</span> `;
const butMakeItLargerForStackOverflowDemoPurposes = `<span style="font-size: 30px">${renderThisHtml}</span>`;
renderHtmlToCanvas( document.getElementById( 'myCanvas' ), butMakeItLargerForStackOverflowDemoPurposes );
function renderHtmlToCanvas( canvas, html ) {
const ctx = canvas.getContext( '2d' );
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="${canvas.width}" height="${canvas.height}">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml">${html}</div>
</foreignObject>
</svg>`;
const svgBlob = new Blob( [svg], { type: 'image/svg+xml;charset=utf-8' } );
const svgObjectUrl = URL.createObjectURL( svgBlob );
const tempImg = new Image();
tempImg.addEventListener( 'load', function() {
ctx.drawImage( tempImg, 0, 0 );
URL.revokeObjectURL( svgObjectUrl );
} );
tempImg.src = svgObjectUrl;
}
<canvas id="myCanvas" style="border:2px solid black;" width="200" height="200"></canvas>
<img />
图像元素:您还可以通过一些调整将HTML渲染到文档中的<img>
元素中:
const renderThisHtml = `<em>I</em> like <span style="color:white; text-shadow:0 0 2px blue;">cheese</span> `;
const butMakeItLargerForStackOverflowDemoPurposes = `<span style="font-size: 30px">${renderThisHtml}</span>`;
renderHtmlToImg( document.getElementById( 'myImg' ), butMakeItLargerForStackOverflowDemoPurposes );
function renderHtmlToImg( img, html ) {
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="${img.width}" height="${img.height}">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml">${html}</div>
</foreignObject>
</svg>`;
const svgBlob = new Blob( [svg], { type: 'image/svg+xml;charset=utf-8' } );
const svgObjectUrl = URL.createObjectURL( svgBlob );
const oldSrc = img.src;
if( oldSrc && oldSrc.startsWith( 'blob:' ) ) { // See https://dev59.com/06Tja4cB1Zd3GeqPGbtj#75848053
URL.revokeObjectURL( oldSrc );
}
img.src = svgObjectUrl;
}
<img id="myImg" style="border:2px solid black;" width="200" height="200" />
foreignObject
在IE中不受支持。 - icfantv这是将任意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>
element()
函数可能最终会对某些人有所帮助,即使它不是直接回答问题的答案。它允许您将元素(以及所有子元素,包括视频,跨域iframe等)用作背景图像(以及在 CSS 代码中通常使用 url(...)
的任何其他地方)。这篇博客文章展示了您可以通过它实现什么。element()
在除Firefox以外的所有浏览器中仍然得到了非常差的支持:https://caniuse.com/css-element-function - flyingace<foreignObject>
。position: relative
的div中,然后将canvas和其他元素设置为position: absolute
。这样它们将彼此重叠。然后,您可以使用left
和right
CSS属性来定位html元素。z-index
CSS属性将其置于canvas之前。