web-dev-qa-db-fra.com

Comment puis-je convertir un élément HTML en un élément de toile?

Il serait extrêmement utile de pouvoir convertir temporairement un élément régulier en un canvas. Par exemple, supposons que j'ai un style div que je souhaite retourner. Je souhaite créer dynamiquement un canevas, "rendre" la HTMLElement dans le canevas, masquer l'élément d'origine et animer le canevas.

Cela peut-il être fait?

46
davemyron

Désolé, le navigateur ne rend pas le code HTML dans un canevas.

Ce serait un risque potentiel pour la sécurité si vous le pouviez, car HTML peut inclure du contenu (en particulier des images et des iframes) provenant de sites tiers. Si canvas peut transformer le contenu HTML en image et lire les données d'image, vous pouvez éventuellement extraire le contenu privilégié d'autres sites.

Pour obtenir un canevas à partir de HTML, vous devez écrire votre propre moteur de rendu HTML à partir de rien en utilisant drawImage et fillText, qui est une tâche potentiellement énorme. Il y a une telle tentative ici mais c'est un peu louche et loin d'être complet. (Il essaie même d’analyser le code HTML/CSS à partir de zéro, ce qui, à mon avis, est fou! Il serait plus facile de partir d’un véritable nœud DOM avec les styles appliqués et de lire le style à l’aide de getComputedStyle et les positions relatives de certaines parties à l'aide de offsetTop et al.)

16
bobince

Il y a une bibliothèque qui essaie de faire ce que vous dites.

Voir ces exemples et obtenir le code

http://hertzen.com/experiments/jsfeedback/

http://html2canvas.hertzen.com/

Lit le DOM, à partir du code HTML et le convertit en canevas, échoue sur certains, mais en général.

48
Aristos

S'appuyant sur l'article de Mozdev faisant référence à natevw, j'ai lancé un petit projet visant à rendre du HTML au format canvas dans Firefox, Chrome & Safari. Ainsi, par exemple, vous pouvez simplement faire:

rasterizeHTML.drawHTML('<span class="color: green">This is HTML</span>' 
                     + '<img src="local_img.png"/>', canvas);

Le code source et un exemple plus complet est ici .

8
cburgmer

Consultez ce didacticiel sur MDN: https://developer.mozilla.org/en/HTML/Canvas/Drawing_DOM_objects_into_a_canvas

Lien alternatif (2019): https://reference.codeproject.com/book/dom/canvas_api/drawing_dom_objects_into_a_canvas

Il utilise une image SVG temporaire pour inclure le contenu HTML en tant qu '"élément étranger", puis restitue cette image SVG en un élément de canevas. Toutefois, il existe des restrictions importantes sur ce que vous pouvez inclure dans une image SVG de cette manière. (Voir la section "Sécurité" pour plus de détails.)

7
natevw

Vous pouvez utiliser dom-to-image library (je suis le responsable).
Voici comment vous pouvez aborder votre problème:

var parent = document.getElementById('my-node-parent');
var node = document.getElementById('my-node');

var canvas = document.createElement('canvas');
canvas.width = node.scrollWidth;
canvas.height = node.scrollHeight;

domtoimage.toPng(node).then(function (pngDataUrl) {
    var img = new Image();
    img.onload = function () {
        var context = canvas.getContext('2d');

        context.translate(canvas.width, 0);
        context.scale(-1, 1);
        context.drawImage(img, 0, 0);

        parent.removeChild(node);
        parent.appendChild(canvas);
    };

    img.src = pngDataUrl;
});

Et voici jsfiddle

6
tsayen

Rien de tel, désolé.

Bien que les spécifications stipulent:

Une future version de l'API de contexte 2D pourrait permettre de restituer des fragments de documents, rendus à l'aide de CSS, directement dans l'espace de travail.

Qui peut être aussi proche que vous obtiendrez.

Beaucoup de gens veulent un accord de type ctx.drawArbitraryHTML/Element, mais il n’ya rien de tel.

La seule exception est l'exclusive drawWindow de Mozilla, qui trace un instantané du contenu d'une fenêtre DOM dans le canevas. Cette fonctionnalité est uniquement disponible pour le code fonctionnant avec des privilèges Chrome ("local uniquement"). Ce n'est pas autorisé dans les pages HTML normales. Vous pouvez donc l'utiliser pour écrire des extensions FireFox comme celui-ci le fait mais c'est tout.

5
Simon Sarris

Vous pourriez vous épargner les transformations, vous pourriez utiliser CSS3 Transitions pour retourner les codes <div> et <ol> et les balises HTML de votre choix. Voici quelques démos avec le code source qui explique à voir et à apprendre: http://www.webdesignerwall.com/trends/47-amazing-css3-animation-demos/

3
Jürgen Messing

le code suivant peut être utilisé dans 2 modes, le mode 1 enregistre le code HTML dans une image, le mode 2 enregistre le code HTML dans une zone de dessin.

ce code fonctionne avec la bibliothèque: https://github.com/tsayen/dom-to-image

* "id_div" est l'identifiant de l'élément HTML que vous souhaitez transformer.

** le "canvas_out" est l'id du div qui contiendra le canevas alors essayez ce code .:

   function Guardardiv(id_div){

      var mode = 2 // default 1 (save to image), mode 2 = save to canvas
      console.log("Process start");
      var node = document.getElementById(id_div);
      // get the div that will contain the canvas
      var canvas_out = document.getElementById('canvas_out');
      var canvas = document.createElement('canvas');
      canvas.width = node.scrollWidth;
      canvas.height = node.scrollHeight;

      domtoimage.toPng(node).then(function (pngDataUrl) {
          var img = new Image();
          img.onload = function () {
          var context = canvas.getContext('2d');
          context.drawImage(img, 0, 0);
        };

        if (mode == 1){ // save to image
             downloadURI(pngDataUrl, "salida.png");
        }else if (mode == 2){ // save to canvas
          img.src = pngDataUrl;
          canvas_out.appendChild(img);

        }
      console.log("Process finish");
    });

    }

alors, si vous voulez sauvegarder dans une image, ajoutez simplement cette fonction:

    function downloadURI(uri, name) {
        var link = document.createElement("a");

        link.download = name;
        link.href = uri;
        document.body.appendChild(link);
        link.click();   
    }

Exemple d'utilisation:

 <html>
 <head>
 </script src="/dom-to-image.js"></script>
 </head> 
 <body>
 <div id="container">
   All content that want to transform
  </div>
  <button onclick="Guardardiv('container');">Convert<button> 

 <!-- if use mode 2 -->
 <div id="canvas_out"></div>
 </html>

Commentaire si cela fonctionne . Comenten si les sirvio :)

0
Luis Villadiego

La solution la plus simple pour animer les éléments DOM consiste à utiliser des transitions/animations CSS, mais je pense que vous le savez déjà et que vous essayez d'utiliser canvas pour faire des choses que CSS ne vous laisse pas faire. Qu'en est-il de filtres personnalisés CSS ? vous pouvez transformer vos éléments de toutes les manières imaginables si vous savez écrire des shaders. Un autre lien et n'oubliez pas de vérifier le laboratoire de filtres CSS .
Note: Comme vous pouvez probablement l’imaginer, le support du navigateur est mauvais.

0
olanod