{"id":686,"date":"2012-10-22T10:00:45","date_gmt":"2012-10-22T08:00:45","guid":{"rendered":"https:\/\/d-mueller.de\/blog\/?p=686"},"modified":"2016-01-11T23:49:45","modified_gmt":"2016-01-11T22:49:45","slug":"html2canvas-screenshots-von-webseiten-mit-javascript-erstellen","status":"publish","type":"post","link":"https:\/\/d-mueller.de\/blog\/html2canvas-screenshots-von-webseiten-mit-javascript-erstellen\/","title":{"rendered":"html2canvas &#8211; Screenshots von Webseiten mit Javascript erstellen"},"content":{"rendered":"<p>Auf einigen Webseiten wird dem Nutzer die M\u00f6glichkeit geboten, Feedback zu geben. Bei Youtube l\u00e4uft das bspw. so, dass man als &#8222;feedbackwilliger&#8220; Nutzer einen Bereich der Webseite markiert und diesen dann kommentieren kann. Nachzuvollziehen ist das \u00fcber den versteckt im Footer der Seite platzierten Link &#8222;Programmfehler melden&#8220;.<\/p>\n<div id=\"attachment_689\" style=\"width: 650px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/d-mueller.de\/blog\/wp-content\/uploads\/2012\/10\/Youtube-Feedback.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-689\" src=\"https:\/\/d-mueller.de\/blog\/wp-content\/uploads\/2012\/10\/Youtube-Feedback-1024x512.png\" alt=\"Youtube-Feedback\" title=\"Youtube-Feedback\" width=\"640\" height=\"320\" class=\"size-large wp-image-689\" srcset=\"https:\/\/d-mueller.de\/blog\/wp-content\/uploads\/2012\/10\/Youtube-Feedback-1024x512.png 1024w, https:\/\/d-mueller.de\/blog\/wp-content\/uploads\/2012\/10\/Youtube-Feedback-300x150.png 300w, https:\/\/d-mueller.de\/blog\/wp-content\/uploads\/2012\/10\/Youtube-Feedback.png 1148w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><p id=\"caption-attachment-689\" class=\"wp-caption-text\">Youtube-Feedback<\/p><\/div>\n<p>Durch das Projekt <a href=\"http:\/\/html2canvas.hertzen.com\/screenshots.html\">html2canvas<\/a> l\u00e4sst sich nun sowas ganz ohne Flash l\u00f6sen: Es wird in einem Canvas das DOM der Seite rekonstruiert und dann mittels der Funktion <i>canvas.toDataURL()<\/i> ein Datenstream erstellt, der sich dann mit Hilfe eines serverseitigen Scripts in ein vollwertiges Bild umwandeln l\u00e4sst. Aber der Reihe nach.<\/p>\n<h2>Das Setup<\/h2>\n<pre data-enlighter-language=\"html\" class=\"EnlighterJSRAW\">\r\n&lt;!doctype html&gt;\r\n&lt;head&gt;\r\n\t&lt;script src=&quot;http:\/\/ajax.googleapis.com\/ajax\/libs\/jquery\/1.8.1\/jquery.min.js&quot;&gt;&lt;\/script&gt;\r\n\t&lt;script src=&quot;https:\/\/raw.github.com\/niklasvh\/html2canvas\/master\/src\/plugins\/jquery.plugin.html2canvas.js&quot;&gt;&lt;\/script&gt;\r\n\t&lt;script src=&quot;http:\/\/html2canvas.hertzen.com\/js\/html2canvas.js?rev034&quot;&gt;&lt;\/script&gt;\r\n\t&lt;script src=&quot;makeScreenshot.js&quot;&gt;&lt;\/script&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n\t&lt;div style=&quot;width:500px;height:300px;background:red;border:5px solid yellow&quot;&gt;\r\n\t\t&lt;h1 style=&quot;color:green&quot;&gt;Das ist ein Test&lt;\/h1&gt;\r\n\t&lt;\/div&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;\r\n<\/pre>\n<p>Logischerweise brauchen wir jQuery, ein Plugin f\u00fcr html2canvas von der <a href=\"https:\/\/github.com\/niklasvh\/html2canvas\">Github-Seite des Projekts<\/a> und die eigentliche Library. Der Body ist unser Testcontent, den wir screenshotten wollen. Inhalt des Scripts <b>makeScreenshot.js<\/b>:<\/p>\n<pre data-enlighter-language=\"javascript\" class=\"EnlighterJSRAW\">\r\nfunction postCanvasToURL(data) \r\n{\r\n\tdata = data.replace(&#039;data:image\/png;base64,&#039;, &#039;&#039;);\r\n\tvar xhr = new XMLHttpRequest();\r\n\txhr.open(&#039;POST&#039;, &quot;post.php&quot;, true);\r\n\tvar boundary = &#039;this-is-a-string&#039;;\r\n\txhr.setRequestHeader(&#039;Content-Type&#039;, &#039;multipart\/form-data; boundary=&#039; + boundary);\r\n\trequest_str = &#039;--&#039; + boundary + &#039;\\r\\n&#039; + &#039;Content-Disposition: form-data; name=&quot;formelement&quot;; filename=&quot;image.png&quot;&#039; + &#039;\\r\\n&#039; +\r\n\t\t\t\t   &#039;Content-Type: image\/png&#039; + &#039;\\r\\n\\r\\n&#039; + atob(data) + &#039;\\r\\n&#039; + &#039;--&#039; + boundary + &#039;--&#039;;\r\n\r\n\tvar bytes = [];\r\n\r\n\tfor (var i in request_str)\r\n\t{\r\n\t\tbytes.push(request_str[i].charCodeAt(0) &amp; 0xff);\r\n\t}\r\n\r\n\txhr.send(new Uint8Array(bytes).buffer);\r\n}\r\n\r\n$(window).ready(function()\r\n{\r\n\tvar options = {onrendered : function(canvas) { postCanvasToURL(canvas.toDataURL()); }};\r\n\tvar canvasRecord = $(&#039;body&#039;).html2canvas(options);\r\n});\r\n<\/pre>\n<p>Basierend auf einigen halbgaren Stackoverflow-Antworten (<a href=\"http:\/\/stackoverflow.com\/questions\/10778105\/html2canvas-output-selected-div-php\">hier<\/a>, <a href=\"http:\/\/stackoverflow.com\/questions\/10457608\/create-screenshot-of-webpage-using-html2canvas-unable-to-initialize-properly\">hier<\/a> und <a href=\"http:\/\/stackoverflow.com\/questions\/9250505\/how-to-upload-a-screenshot-using-html2canvas\">hier<\/a>) erstellt die Funktion <i>postCanvasToUrl<\/i> die Data-URL des Canvas im korrekten <i>multipart\/form-data<\/i>-Format als Boundary an das PHP-Script post.php. Mehr passiert nicht. Auf der Serverseite liegt dann die Datei <b>post.php<\/b>, die den XHR-Request entgegennimmt und besch\u00e4mend einfach aufgebaut ist:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n&lt;?php\r\nmove_uploaded_file($_FILES[&#039;formelement&#039;][&#039;tmp_name&#039;], $_FILES[&#039;formelement&#039;][&#039;name&#039;]);\r\n<\/pre>\n<p>Wir verschieben einfach nur die Datei, die uns <i>postCanvasToURL<\/i> im $_FILES &#8211; Array serviert &#8211; wie bei einem normalen File-Upload eben. Resultat ist das optisch \u00fcber jeden Zweifel erhabene Bild:<\/p>\n<div id=\"attachment_691\" style=\"width: 500px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/d-mueller.de\/blog\/wp-content\/uploads\/2012\/10\/html2canvas-output.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-691\" src=\"https:\/\/d-mueller.de\/blog\/wp-content\/uploads\/2012\/10\/html2canvas-output.png\" alt=\"html2canvas-Output\" title=\"html2canvas-Output\" width=\"490\" height=\"298\" class=\"size-full wp-image-691\" srcset=\"https:\/\/d-mueller.de\/blog\/wp-content\/uploads\/2012\/10\/html2canvas-output.png 490w, https:\/\/d-mueller.de\/blog\/wp-content\/uploads\/2012\/10\/html2canvas-output-300x182.png 300w\" sizes=\"auto, (max-width: 490px) 100vw, 490px\" \/><\/a><p id=\"caption-attachment-691\" class=\"wp-caption-text\">html2canvas-Output<\/p><\/div>\n<p>Super Projekt auf jeden Fall! Zu beachten gilt, dass der Browser nat\u00fcrlich Canvas k\u00f6nnen sollte und der &#8222;Screenshot&#8220; in einigen F\u00e4llen nicht ganz akkurat ist. Auf der <a href=\"http:\/\/html2canvas.hertzen.com\/screenshots.html\">Testkonsole<\/a> l\u00e4sst sich hervorragend herumexperimentieren.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Auf einigen Webseiten wird dem Nutzer die M\u00f6glichkeit geboten, Feedback zu geben. Bei Youtube l\u00e4uft das bspw. so, dass man als &#8222;feedbackwilliger&#8220; Nutzer einen Bereich der Webseite markiert und diesen dann kommentieren kann. Nachzuvollziehen ist das \u00fcber den versteckt im &hellip; <a href=\"https:\/\/d-mueller.de\/blog\/html2canvas-screenshots-von-webseiten-mit-javascript-erstellen\/\">Weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,12,3],"tags":[],"class_list":["post-686","post","type-post","status-publish","format-standard","hentry","category-php","category-javascript","category-webdev"],"_links":{"self":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts\/686","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/comments?post=686"}],"version-history":[{"count":0,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts\/686\/revisions"}],"wp:attachment":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/media?parent=686"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/categories?post=686"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/tags?post=686"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}