[html] How can I convert an HTML element to a canvas element?

It would be incredibly useful to be able to temporarily convert a regular element into a canvas. For example, say I have a styled div that I want to flip. I want to dynamically create a canvas, "render" the HTMLElement into the canvas, hide the original element and animate the canvas.

Can it be done?

This question is related to html canvas

The answer is


You could spare yourself the transformations, you could use CSS3 Transitions to flip <div>'s and <ol>'s and any HTML tag you want. Here are some demos with source code explain to see and learn: http://www.webdesignerwall.com/trends/47-amazing-css3-animation-demos/


There is a library that try to do what you say.

See this examples and get the code

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

http://html2canvas.hertzen.com/

Reads the DOM, from the html and render it to a canvas, fail on some, but in general works.


Take a look at this tutorial on MDN: https://developer.mozilla.org/en/HTML/Canvas/Drawing_DOM_objects_into_a_canvas (archived)

Alternate Link (2019) : https://reference.codeproject.com/book/dom/canvas_api/drawing_dom_objects_into_a_canvas

It uses a temporary SVG image to include the HTML content as a "foreign element", then renders said SVG image into a canvas element. There are significant restrictions on what you can include in an SVG image in this way, however. (See the "Security" section for details.)


Building on top of the Mozdev post that natevw references I've started a small project to render HTML to canvas in Firefox, Chrome & Safari. So for example you can simply do:

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

Source code and a more extensive example is here.


No such thing, sorry.

Though the spec states:

A future version of the 2D context API may provide a way to render fragments of documents, rendered using CSS, straight to the canvas.

Which may be as close as you'll get.

A lot of people want a ctx.drawArbitraryHTML/Element kind of deal but there's nothing built in like that.

The only exception is Mozilla's exclusive drawWindow, which draws a snapshot of the contents of a DOM window into the canvas. This feature is only available for code running with Chrome ("local only") privileges. It is not allowed in normal HTML pages. So you can use it for writing FireFox extensions like this one does but that's it.


the next code can be used in 2 modes, mode 1 save the html code to a image, mode 2 save the html code to a canvas.

this code work with the library: https://github.com/tsayen/dom-to-image

*the "id_div" is the id of the element html that you want to transform.

**the "canvas_out" is the id of the div that will contain the canvas so try this 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");
    });

    }

so, if you want to save to image just add this function:

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

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

Example of use:

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

Comment if that work. Comenten si les sirvio :)


function convert() {
                    dom = document.getElementById('divname');
                    var script,
                    $this = this,
                    options = this.options,
                    runH2c = function(){
                        try {
                            var canvas =     window.html2canvas([ document.getElementById('divname') ], {
                                onrendered: function( canvas ) {

                                window.open(canvas.toDataURL());

                                }
                            });
                        } catch( e ) {
                            $this.h2cDone = true;
                            log("Error in html2canvas: " + e.message);
                        }
                    };

                    if ( window.html2canvas === undefined && script === undefined ) {
                    } else {.
                        // html2canvas already loaded, just run it then
                        runH2c();
                    }
                }

The easiest solution to animate the DOM elements is using CSS transitions/animations but I think you already know that and you try to use canvas to do stuff CSS doesn't let you to do. What about CSS custom filters? you can transform your elements in any imaginable way if you know how to write shaders. Some other link and don't forget to check the CSS filter lab.
Note: As you can probably imagine browser support is bad.


You can use dom-to-image library (I'm the maintainer).
Here's how you could approach your problem:

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

And here is jsfiddle