web-dev-qa-db-fra.com

Rendu d'éléments HTML en <canvas>

Existe-t-il un moyen d'avoir un élément HTML arbitraire rendu dans un canevas (puis d'accéder à son tampon ...).

34
gotch4

Vous n'obtiendrez pas un véritable rendu HTML vers <canvas> en soi actuellement, car le contexte de canevas n'a pas de fonction pour rendre les éléments HTML.

Il y a quelques émulations:

projet html2canvas http://html2canvas.hertzen.com/index.html (essentiellement une tentative de rendu HTML basée sur Javascript + canvas)

HTML en SVG en <canvas> peut être possible selon votre cas d'utilisation:

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

De plus, si vous utilisez Firefox vous pouvez pirater certaines autorisations étendues puis rendre une fenêtre DOM en <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

25
Mikko Ohtamaa

Jetez un oeil sur MDN

Il rendra l'élément HTML en utilisant la création d'images SVG .

Par exemple: Il y a <em>I</em> like <span style="color:white; text-shadow:0 0 2px blue;">cheese</span> Élément HTML. Et je veux l'ajouter dans <canvas id="canvas" style="border:2px solid black;" width="200" height="200"></canvas> Élément Canvas.

Voici du code Javascript pour ajouter un élément HTML au canevas .

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>
12
Suresh Mahawar

Voici le code pour rendre le HTML arbitraire dans un canevas:

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;
}

exemple:

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>
6
CpnCrunch

RasterizeHTML est un très bon projet, mais si vous devez accéder au canevas, il ne fonctionnera pas sur Chrome. en raison de l'utilisation de foreignObject

Si vous devez accéder au canevas, vous pouvez utiliser html2canvas

J'essaie de trouver un autre projet car html2canvas est très lent dans les performances

3
Mohamed El Prince

Le CSS element() fonction peut éventuellement aider certaines personnes ici, même si ce n'est pas une réponse directe à la question. Il vous permet d'utiliser un élément (et tous les enfants, y compris les vidéos, les iframes interdomaines, etc.) comme image d'arrière-plan (et partout ailleurs que vous utiliseriez normalement url(...) dans votre code CSS). Voici un article de blog qui montre ce que vous pouvez en faire.

Il est implémenté dans Firefox depuis 2011 et est en cours d'examen en Chrome/Chrome (n'oubliez pas de donner une étoile au problème si vous vous souciez de cette fonctionnalité).

1
user10898116

Selon la spécification HTML, vous ne pouvez pas accéder aux éléments du canevas. Vous pouvez obtenir son contexte et le dessiner, le manipuler, mais c'est tout.

MAIS, vous pouvez mettre à la fois le Canvas et l'élément html dans la même div avec un aposition: relative, puis définissez le canevas et l'autre élément sur position: absolute. De cette façon, ils seront les uns sur les autres. Ensuite, vous pouvez utiliser les propriétés CSS left et right pour positionner l'élément html.

Si l'élément n'apparaît pas, le canevas est peut-être devant lui, alors utilisez le z-index Propriété CSS pour l'amener avant le canevas.

0
Richard Otvos