JavaScript saving user generated image using HTML/JS [duplicate]

Is it possible to capture or print what's displayed in an html canvas as an image or pdf?

I'd like to generate an image via canvas, and be able to generate a png from that image.

Answer:1

HTML5 provides Canvas.toDataURL(mimetype) which is implemented in Opera, Firefox, and Safari 4 beta. There are a number of security restrictions, however (mostly to do with drawing content from another origin onto the canvas).

So you don't need an additional library.

e.g.

 <canvas id=canvas width=200 height=200></canvas>
 <script>
      window.onload = function() {
          var canvas = document.getElementById("canvas");
          var context = canvas.getContext("2d");
          context.fillStyle = "green";
          context.fillRect(50, 50, 100, 100);
          // no argument defaults to image/png; image/jpeg, etc also work on some
          // implementations -- image/png is the only one that must be supported per spec.
          window.location = canvas.toDataURL("image/png");
      }
 </script>

Theoretically this should create and then navigate to an image with a green square in the middle of it, but I haven't tested.

Answer:2
function exportCanvasAsPNG(id, fileName) {

    var canvasElement = document.getElementById(id);

    var MIME_TYPE = "image/png";

    var imgURL = canvasElement.toDataURL(MIME_TYPE);

    var dlLink = document.createElement('a');
    dlLink.download = fileName;
    dlLink.href = imgURL;
    dlLink.dataset.downloadurl = [MIME_TYPE, dlLink.download, dlLink.href].join(':');

    document.body.appendChild(dlLink);
    dlLink.click();
    document.body.removeChild(dlLink);
}
Answer:3

Here is some help if you do the download through a server (this way you can name/convert/post-process/etc your file):

-Post data using toDataURL

-Set the headers

$filename = "test.jpg"; //or png
header('Content-Description: File Transfer');
if($msie = !strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false)      
  header("Content-type: application/force-download");else       
  header("Content-type: application/octet-stream"); 
header("Content-Disposition: attachment; filename=\"$filename\"");   
header("Content-Transfer-Encoding: binary"); 
header("Expires: 0"); header("Cache-Control: must-revalidate"); 
header("Pragma: public");

-create image

$data = $_POST['data'];
$img = imagecreatefromstring(base64_decode(substr($data,strpos($data,',')+1)));

-export image as JPEG

$width = imagesx($img);
$height = imagesy($img);
$output = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($output,  255, 255, 255);
imagefilledrectangle($output, 0, 0, $width, $height, $white);
imagecopy($output, $img, 0, 0, 0, 0, $width, $height);
imagejpeg($output);
exit();

-or as transparent PNG

imagesavealpha($img, true);
imagepng($img);
die($img);
Answer:4

Another interesting solution is PhantomJS. It's a headless WebKit scriptable with JavaScript or CoffeeScript.

One of the use case is screen capture : you can programmatically capture web contents, including SVG and Canvas and/or Create web site screenshots with thumbnail preview.

The best entry point is the screen capture wiki page.

Here is a good example for polar clock (from RaphaelJS):

>phantomjs rasterize.js http://raphaeljs.com/polar-clock.html clock.png

Do you want to render a page to a PDF ?

> phantomjs rasterize.js 'http://en.wikipedia.org/w/index.php?title=Jakarta&printable=yes' jakarta.pdf
Answer:5

If you are using jQuery, which quite a lot of people do, then you would implement the accepted answer like so:

var canvas = $("#mycanvas")[0];
var img = canvas.toDataURL("image/png");

$("#elememt-to-write-to").html('<img src="'+img+'"/>');
Answer:6

You can use jspdf to capture a canvas into an image or pdf like this:

var imgData = canvas.toDataURL('image/png');              
var doc = new jsPDF('p', 'mm');
doc.addImage(imgData, 'PNG', 10, 10);
doc.save('sample-file.pdf');

More info: https://github.com/MrRio/jsPDF

Answer:7

This is the other way, without strings although I don't really know if it's faster or not. Instead of toDataURL (as all questions here propose). In my case want to prevent dataUrl/base64 since I need a Array buffer or view. So the other method in HTMLCanvasElement is toBlob. (TypeScript function):

    export function canvasToArrayBuffer(canvas: HTMLCanvasElement, mime: string): Promise<ArrayBuffer> {
  return new Promise((resolve, reject) => canvas.toBlob(async (d) => {
    if (d) {
      const r = new FileReader();
      r.addEventListener('loadend', e => {
        const ab = r.result;
        if (ab) {
          resolve(ab as ArrayBuffer);
        }
        else {
           reject(new Error('Expected FileReader result'));
        }
      }); r.addEventListener('error', e => {
        reject(e)
      });
      r.readAsArrayBuffer(d);
    }
    else {
      reject(new Error('Expected toBlob() to be defined'));
    }
  }, mime));
}

Another advantage of blobs is you can create ObjectUrls to represent data as files, similar to HTMLInputFile's 'files' member. More info:

https://developer.mozilla.org/es/docs/Web/API/HTMLCanvasElement/toBlob

Answer:8

Listening to scroll events in Safari iOS browser triggers the console message every time, even on the momentum, but in the cordova built app that triggers only when the scroll has stopped. el-with-...

Listening to scroll events in Safari iOS browser triggers the console message every time, even on the momentum, but in the cordova built app that triggers only when the scroll has stopped. el-with-...

  1. cordova momentum scrolling

why is it that codeigniter session doesn't update values when an ajax request is done? controller index: public function index() { $this->session->set_userdata( 'greetings', 'hello!' ); } ...

why is it that codeigniter session doesn't update values when an ajax request is done? controller index: public function index() { $this->session->set_userdata( 'greetings', 'hello!' ); } ...

  1. codeigniter session doesn't work

I want to update a variable called hideProgressBar the Directive "ng-hide" in this view through the $ scope in my control. But it does not work. The line below works: $ Scope.hideProgessBar = true; ...

I want to update a variable called hideProgressBar the Directive "ng-hide" in this view through the $ scope in my control. But it does not work. The line below works: $ Scope.hideProgessBar = true; ...

I need to pas params to Aurelia on start. Depending on values passed the application will have diffrent state. This application is injected on page which is build with PHP, so the best way would be ...

I need to pas params to Aurelia on start. Depending on values passed the application will have diffrent state. This application is injected on page which is build with PHP, so the best way would be ...