How to take print (screenshot) of a web page?

12

I'd like to know how to get print out of a page, and save it as an image.

Here is an example for understanding:

    
asked by anonymous 15.05.2015 / 16:28

4 answers

11
  

You can use the html2canvas, note that it does not take a real photo, but   yes try to redraw the elements of the page, note that the other   answers are correct, but the examples probably   will work in the current version of html2canvas, since several functions were   modified and passed to uses es6-promise

Using the html2canvas

I recommend downloading the 0.5.0-alpha2 version at link and include in the page that will need to take the "photo", should be something like:

<script src="html2canvas.js"></script>

html2canvas(document.getElementById("id-do-meu-elemento"), {
    "logging": true //Habilita os logs
}).then(function(canvas) {
    var img = new Image();
    img.onload = function () {
        img.onload = null;
        document.getElementById("output").appendChild(img);
    };
    img.src = canvas.toDataURL("image/png");
});

However, there may be cases where images are from different domains, you will need to use CORS , then we will have than using proxy.

Proxy in this case is not the technology to use a different ip on your machine, but a script that runs on the server and displays the image of the external domain as if it were in your domain, or even three domains seu-site.com , maps.google.com and proxy.seu-site.com it makes use of CORS or data URI scheme .

Proxy for html2canvas

I developed four proxies in different languages:

  • Proxy in PHP : link
  • C # proxy : link
  • Proxy in Python : link (supports any framework)
  • Proxy in VbScript (for classic asp) : link

The usage would be something like (example with aspx ):

html2canvas(document.getElementById("ID-DO-ELEMENTO"), {
    "logging": true, //Habilita os logs
    "proxy":"html2canvasproxy.ashx"
}).then(function(canvas) {
    var img = new Image();
    img.onload = function () {
        img.onload = null;
        document.getElementById("output").appendChild(img);
    };
    img.src = canvas.toDataURL("image/png");
});

List of options to use in html2canvas(..., {opções}).then(...)

+-----------------+---------+-----------+----------------------+
| Opção           | Tipo    | padrão    |  Descrição           |
+-----------------+---------+-----------+----------------------+
| allowTaint      | boolean | false     | Permite causar o     |
|                 |         |           | taint quando houver  |
|                 |         |           | imagens cross-origin |
+-----------------+---------+-----------+----------------------+
| background      | string  | #fff      | Troca a cor de fundo |
|                 |         |           | do canvas, se não    |
|                 |         |           | espeficicado no dom  |
|                 |         |           | use 'undefined' para |
|                 |         |           | transparente         |
+-----------------+---------+-----------+----------------------+
| height          | number  | null      | Limita a altura do   |
|                 |         |           | em pixels. Se 'null' |
|                 |         |           | irá renderezar com   |
|                 |         |           | a altura total da ja-|
|                 |         |           | nela                 |
+-----------------+---------+-----------+----------------------+
| letterRendering | boolean | false     | Usado para renderizar|
|                 |         |           | cada letra separada- |
|                 |         |           | mente. É necessário  |
|                 |         |           | se estiver usando    |
|                 |         |           | 'letter-spacing'     |
+-----------------+---------+-----------+----------------------+
| logging         | boolean | false     | Quando 'true' mostra |
|                 |         |           | log no console do    |
|                 |         |           | navegador            |
+-----------------+---------+-----------+----------------------+
| proxy           | string  | undefined | A url do proxy é usa-|
|                 |         |           | da para carregar ima-|
|                 |         |           | gens cross-origin.   |
|                 |         |           | Se não definido ou   |
|                 |         |           | vazio as imagens não |
|                 |         |           | serão carregadas     |
+-----------------+---------+-----------+----------------------+
| taintTest       | boolean | true      | Testa cada imagem    |
|                 |         |           | para antes de dese-  |
|                 |         |           | nhar, para verificar |
|                 |         |           | se irá manchar o can-| 
|                 |         |           | vas.                 |
+-----------------+---------+-----------+----------------------+
| timeout         | number  | 0         |Tempo de espera para  |
|                 |         |           | o carregamento das   |
|                 |         |           | imagens em milesegun-|
|                 |         |           | dos. Se 0 não haverá |
|                 |         |           | esperar              |
+-----------------+---------+-----------+----------------------+
| width           | number  | null      | Limita a largura do  |
|                 |         |           | em pixels. Se 'null' |
|                 |         |           | irá renderezar com   |
|                 |         |           | a largura total da   |
|                 |         |           | janela               |
+-----------------+---------+-----------+----------------------+
| useCORS         | boolean | false     | Se 'true' tenta car- |
|                 |         |           | regar as imagens com |
|                 |         |           | cross-origem, se não |
|                 |         |           | tenta usar o proxy   |
+-----------------+---------+-----------+----------------------+

Drawing DOM with SVG inside the Canvas

It is possible to draw SVGs within Canvas , but at the moment we use <foreignObject> , browsers WebKit and Blink/Chromium have security locks as use this, ie you can draw, but you can not use toDataURI (in Firefox it works if you use CORS ).

The following example is simple, purchased from MDN , to use % style and CSS properties will need to be converted to <link> and convert <style> to url(...) and even then text fonts will not be supported (unbelievably it looks like I'm working on some months in a library that does all this, takes "photo" of the page using SVG, I just stopped because of the question of web-sources, which is very difficult to embed in SVG), so you can try, but it will only work on browsers with the Gecko engine (used Firefox) and it will still be a bit laborious to import, but CSS and HTML effects all will probably work, simple example follows:

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;

Note that to use SVG you need a valid HTML (or better XHTML), to do this use this script:

var doc = document.implementation.createHTMLDocument("");

//Adicione o seu html, como por exemplo document.documentElement.innerHTML
doc.write(STRING DO CONTEUDO HTML);

doc.documentElement.setAttribute("xmlns", doc.documentElement.namespaceURI);

var html = (new XMLSerializer).serializeToString(doc);

var docWidth  = Math.max(document.documentElement.clientWidth,
                         document.body.scrollWidth,
                         document.documentElement.scrollWidth,
                         document.body.offsetWidth,
                         document.documentElement.offsetWidth);

var docHeight = Math.max(document.documentElement.clientHeight,
                         document.body.scrollHeight,
                         document.documentElement.scrollHeight,
                         document.body.offsetHeight,
                         document.documentElement.offsetHeight);

var data = '<svg xmlns="http://www.w3.org/2000/svg" ' +
           'width="' + docWidth + '" height="' + docHeight + '">' +
           '<foreignObject width="100%" height="100%">' +
             html +
           '</foreignObject>' +
           '</svg>';

Conclusion about taking page photo

With the exception of SVG canvas , no library has enough yet to simulate the HTML and CSS effects of browsers yet, and even get it, it will still be subject to BUGs or it will not be able to follow the motors of the web-browsers in real time, because everything is "simulated".

Saving canvas on the server

As you can see in the link to upload an image to canvas, do the following:

function uploadAjax(data, fileName, success, error)
{
    var oReq = new XMLHttpRequest();

    oReq.open("POST", "upload.php?filename=" + fileName, true);
    oReq.onreadystatechange = function() {
        if (oReq.readyState === 4) {
            if (oReq.status === 200) {
                success(oReq.responseText);
            } else {
                error(oReq.status);
            }
        }
    };
    oReq.send(data);
}

html2canvas(document.getElementById("id-do-meu-elemento"), {
    "logging": true //Habilita os logs
}).then(function(canvas) {
    uploadAjax(
        canvas.toDataURL("image/jpeg").replace(/^data[:]image\/(.*);base64,/, ""),
        "photo.jpg", function(response) {
            if (response === "OK") {
                alert("sucesso");
            } else {
                alert("Ajax: " + response);
            }
        }, function(errStatus) {
            alert("erro: " + errStatus);
        });
});
  

Change Data URI Scheme to the format you want, for example image/jpeg or image/gif , for example:

canvas.toDataURL("image/png")

PHP upload:

<?php
define('PASTA_UPLOAD', '/home/user/projeto/data');

if (isset($_GET['filename']) && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $cl = (int) $_SERVER['CONTENT_LENGTH'];

    $tmpFile = tempnam(sys_get_temp_dir(), '~upload-');

    $file = fopen($tmpFile, 'w');
    $fh   = fopen('php://input', 'r');
    if ($file && $fh) {
        $data = '';
        while (FALSE === feof($fh)) {
            $data .= fgets($fh, 256);
        }
        fwrite($file, base64_decode($data));
    }

    if ($file) {
        fclose($file);
    }

    if ($fh) {
        fclose($fh);
    }

    echo 'OK';
    copy($tmpFile, PASTA_UPLOAD . '/' . $_GET['filename']);
} else {
    echo 'Requisição inválida';
}

Saving on the Desktop User Machine

To save to Desktop, the user's browser must have support for the image/png attribute in the download tag (all modern Desktop browsers have), example:

function canvasDownload(canvas, filename, formato) {
    var a = document.createElement("a");
    a.href = canvas.toDataURL("image/" + (formato ? formato : "jpeg") );
    a.download = filename;
    a.click();
}

Note that it is necessary to add the <a> event to a user action, such as downloadHtml2canvas , click , etc, otherwise the script is blocked. Example usage:

<button id="gerar">Gerar</button>
<button id="salvar" disabled>Salvar</button>

<script>
(function() {
    var gerar  = document.getElementById("gerar"),
        salvar = document.getElementById("salvar"),
        currentCanvas = null;

    gerar.onclick = function() {
        salvar.disabled = true;
        html2canvas(document.getElementById("id-do-meu-elemento"), {
            "logging": true //Habilita os logs
        }).then(function(canvas) {
            currentCanvas = canvas;
            salvar.disabled = false;
        });
    };

    salvar.onclick = function() {
         if (currentCanvas !== null && salvar.disabled === false) {
             canvasDownload(currentCanvas, "foto.jpg");
         }
    };
})();
</script>
  

Note: If you want to save in another format simply adjust it:

     
  • mouseover
  •   
  • canvasDownload(currentCanvas, "foto.png", "png")
  •   
    
15.05.2015 / 20:23
5

You can use the html2canvas library that fits exactly to what you want, as it "strips print "from any division of an html page.

Here are the usage examples , but I'll leave a snippet below to illustrate:

$("#PrintTrigger").on("click", function (e) {
    e.preventDefault();
    
    html2canvas($("#Print"), {
      onrendered: function(canvas) {
        document.body.appendChild(canvas);
      }
    });
});
#Print {
    width: 300px;
    height: 300px;
    background: #00FF00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><scriptsrc="https://github.com/niklasvh/html2canvas/releases/download/0.4.1/html2canvas.js"></script>
<div id="Print">
    <h1>Vai printar esta div e repetí-la abaixo:</h1>
</div>
<button id="PrintTrigger">Tirar Print</button>

Operation

The JS code is very simple:

html2canvas(elemento, {
  onrendered: function(canvas) {
    // Ação à realizar, ao renderizar a imagem (print)
  }
});

element - Matches the html page you want to "print" (Possible without a DOM Element, an ID, or a Class)
onrendered - Function that will be executed once "print" is rendered. In this function you can use AJAX to send to the server without reloading the page, in fact, the possibilities are numerous.

    
15.05.2015 / 20:10
3

With PHP I think it can not be done, but with Javascript and canvas (HTML5) yes.

With the advent of HTML5, new tags have been implemented, one of them is the canvas , which makes it possible to accomplish this task.

With the canvas element you can create graphics, photo compositions, animations, 2D, 3D images and there are several APIs that provide you with a number of features, such as > html2canvas , and it's this API that we're going to work on.

First let's go to the site and download the file. I assume you have already downloaded the file jquery.js .

The html2canvas has an initial method called Preload , which receives two parameters.

  • Element : This is the element you want to render, by default it's document.body
  • Options : These are the rendering options.
  • Complete : callback function that will be called after Preloading
  • Logging : Log events on the console
  • Proxy : Url of the page to be used as proxy
  • Timeout : Time to load images

The script performs the following behavior:

  • Run Page Preload
  • Execute Parse of Elements
  • Run Object Render
  • Let's go to the code:

    <script>
        $(window).ready(function () {
            html2canvas.Preload(document.body, {
                complete: function (images) {
                    var queue = html2canvas.Parse();
                    var canvas = html2canvas.Renderer(queue, { elements: { length: 1} });
                    var img = canvas.toDataURL();
                    openConsole("<img src='" + img + "'><p>");
                }
            });
            function openConsole(content) {
                top.console = window.open('', 'myconsole',
                  'width=350,height=250'
                   + ',menubar=0'
                   + ',toolbar=1'
                   + ',status=0'
                   + ',scrollbars=1'
                   + ',resizable=1')
                top.console.document.writeln(
                  '<html><head><title>Console</title></head>'
                   + '<body bgcolor=white onLoad="self.focus()">'
                   + content
                   + '</body></html>'
                 )
                top.console.document.close()
            };
        });
    </script>
    

    Remembering that browsers that accept canvas are Chrome, FF, Opera, and IE7 +

    For more information, take a look at this article:

    link

        
    15.05.2015 / 19:54
    2

    I already use the Headless Browser PhantomJS to download full FAX-rendered WEB pages that are displayed in the regular browser (it interprets JS and CSS) but with it is also possible to perform a print screen of the desired page of the following form:

    • Create a file with .js extension
    • Paste and save the following content:

    Command that accesses a certain page and saves its contents in a .png (but can save as PDF):

    var page = require('webpage').create();
    page.open('http://stackoverflow.com/', function() {
      page.render('stackoverflow.png');
      phantom.exit();
    });
    
    • Call it the following command line: program name (if it has been entered in the path) plus npath of the javascript file created in the above item getting as follows:

      phantomjs test.js

    It is also possible to establish the dimensions of the window where the site is displayed (this is useful if you want to see how a responsive site is being rendered) as follows (this configuration must be done before the page.open ()) :

    var webPage = require('webpage');
    var page = webPage.create();
    
    page.viewportSize = {
      width: 480,
      height: 800
    };
    

    You can call it using the shell_exec command like this:

        $pathToPhantomJS = 'C:\phantomjs-2.0.0-windows\bin\phantomjs';
        $pathToJSScript = 'GetPage.js';
        $comand = $pathToPhantomJS . ' ' . $pathToJSScript . ' ' . $site;
        shell_exec($comand);
    

    It is possible to create a CRON JOB to run the phantomjs teste.js command at a certain time.

    The PhantomJS was very useful to me and it is very configurable and I could not describe all the possibilities here so I am sticking some official and non-official links that may be useful:

      

    Note: A relevant point raised by the user @GuilhermeNascimento is that this solution only works on the Servidor side or on its Desktop .

    Download

    Link: link

    Documentation

    Screen Capture: Link

    viewportSize: Link

    shell_exec (PHP): Link

        
    15.05.2015 / 21:15