Giter VIP home page Giter VIP logo

canvas2pdf's Introduction

Canvas2PDF

Canvas2PDF exports your HTML canvas as PDF using JavaScript. Note that this library generates actual PDF drawing calls to create a PDF with vector graphics, unlike some alternate libraries which rasterize your canvas and place it as an image in your PDF.

Usage

import PdfContext from "/src/canvas2pdf";
import blobStream from "blob-stream";
import { saveAs } from "file-saver";

// Create a new PDF canvas context.
const ctx = new PdfContext(blobStream());

// draw your canvas like you would normally
ctx.fillStyle = "yellow";
ctx.fillRect(100, 100, 100, 100);
// more canvas drawing, etc...

// convert your PDF to a Blob and save to file
ctx.stream.on("finish", function () {
  const blob = ctx.stream.toBlob("application/pdf");
  saveAs(blob, "example.pdf", true);
});
ctx.end();

Interactive Browser Demo

Open Demo

Notes

  • Calling fill and then stroke consecutively only executes fill
  • Some canvas 2d context methods are not implemented yet (e.g. arcTo)

License

MIT

Developer Dependencies

  • GraphicsMagick is required for running tests

canvas2pdf's People

Contributors

eternalharvest avatar joshua-gould avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

canvas2pdf's Issues

arcTo(x1, y1, x2, y2, radius)

Hi,

Could you implement the arcTo(x1, y1, x2, y2, radius) function, please?
Your library is great but it is missing the very function I use all the time.

Thanks

Support fillAndStroke()

For dual compatibility between native browser context and canvas2pdf context, this call can solve a otherwise difficult (or performance costly) problem.

See dankrusi@71904d5

Dual Compatibility Browser Canvas and canvas2pdf

If you wish to write applications that can draw to either context (a browsers native canvas context or the canvas2pdf context)
and be fully compatible with each other, one should stick to the supported context API calls
provided by canvas2pdf.

If you wish to call a fill() and stroke() consecutively,
you should use the PDF-style call fillAndStroke() instead with the following compatibility
extensions for the browser canvas:

Object.defineProperty(CanvasRenderingContext2D.prototype, 'fillAndStroke', {
    value: function () {
        this.fill();
        this.stroke();
    }
});

For example, if your application used to have drawing calls similar to:

ctx.beginPath();
ctx.arc(...);
ctx.lineTo(...);
ctx.lineTo(...);
ctx.closePath();
ctx.fill();
ctx.stroke();

...you would update those calls to use fillAndStroke():

ctx.beginPath();
ctx.arc(...);
ctx.lineTo(...);
ctx.lineTo(...);
ctx.closePath();
ctx.fillAndStroke();

context transformation support

It's a shame the library doesn't support context transformation, ie the following

ctx.setTransform(2,1,.5,1,0,1);

has no effect on the pdf image

Do we need jsdom or node-canvas?

From canvas2svg page:

You can use canvas2svg with node.js using jsdom with node-canvas. To do this first create a new document object, and then create a new instance of C2S based on that document:

var canvas = require('canvas'),
jsdom = require('jsdom'),
C2S = require('canvas2svg');

var document = jsdom.jsdom();
var ctx = new C2S({document: document});

// ... drawing code goes here ...

Do we need to do the same in order to use canvas2pdf in node.js? Whats the benefit of jsdom?

AMD dependency for PDFDocument

Your library works great, but we've encountered a problem when used with AMD and require.js.

You are explicitly calling for global PDFDocument, which causes a problem as this dependency should be defined in define for AMD. pdfkit also supports AMD so it's not possible to shim it to global without ugly exposing PDFDocument to global.

Would be great if you could fix this, or let me know if you are open to PRs.

blobStream is not defined

I'm Using in Angular 8, When i call
var ctx = new canvas2pdf.Context(blobStream());
its throw - blobStream is not defined

Nextjs support?

Hey!

Trying to get this working with Nextjs 13.
Getting errors like:
ReferenceError: PDFDocument is not defined
at new canvas2pdf.PdfContext

I'm using it as a client side component.

Any chance anyone has an idea or example how usage with nextjs?

ctx.addPage()

I need to make a multi-page PDF but the function ctx.addPage() is missing.
Adding the following in the file canvas2pdf.js file solved it.

  /**
   * Add a new page
   */
  canvas2pdf.PdfContext.prototype.addPage = function () {
    this.doc.addPage();
  };

new page in pdf

Is there any method to create a new page inside PDF ?
How to configure page size?

font props support

Hi and thank you for this amazing solution, just wanted to check if im missing something regarding font family and font size, for some reason no matter what i do, inside the pdf the text stays with the default font.

Any idea why?
image

How to use inside node?

I would like to use canvas2pdf inside node.js. My main idea is to put the js inside AWS Lambda and whenever a request comes, I would like to create a pdf and put to S3. But I cannot find how to do it without blobStream. Is there any example regarding this? Thank you.

ctx.arc()

I think there is a bug with ctx.arc() when used with ctx.fill().
Here is an example:

ctx.beginPath();
ctx.moveTo(300,300); //0
ctx.lineTo(300,270); //1
ctx.lineTo(180,270); //2
ctx.arc(180,220,50,1/2*Math.PI,Math.PI,false);
ctx.lineTo(130,100); //4
ctx.lineTo(100,100); //5
ctx.lineTo(100,220); //6
ctx.arc(180,220,80,Math.PI,1/2*Math.PI,true);
ctx.lineTo(300,300); //0
ctx.fillStyle = 'red';
ctx.fill();
ctx.stroke();

Gives you this drawing:
image

To fix it, I rewrote arc() as following:

function myArc(x0,y0,r,a0,a1,counterclockwise){
	var delta=0.1;
	if(a0>a1 && counterclockwise==false){a1+=2*Math.PI;}
	if(a1>a0 && counterclockwise==true){a0+=2*Math.PI;}
	if(counterclockwise==true){
		for (var a=a0; a>=a1; a-=delta) {
			ctx.lineTo(x0+r*Math.cos(a),y0+r*Math.sin(a));
		}
	}else{
		for (var a=a0; a<=a1; a+=delta) {
			ctx.lineTo(x0+r*Math.cos(a),y0+r*Math.sin(a));
		}		
	}
}
ctx.beginPath();
ctx.moveTo(300,300); //0
ctx.lineTo(300,270); //1
ctx.lineTo(180,270); //2
myArc(180,220,50,1/2*Math.PI,Math.PI,false);
ctx.arc(180,220,50,1/2*Math.PI,Math.PI,false);
ctx.lineTo(130,100); //4
ctx.lineTo(100,100); //5
ctx.lineTo(100,220); //6
myArc(180,220,80,Math.PI,1/2*Math.PI,true);
ctx.lineTo(300,300); //0
ctx.fillStyle = 'red';
ctx.fill();
ctx.stroke();

And it gives this drawing:
image

Maybe the start-angle and end-angle are inverted for some cases in your code.

ctx.scale(x,y)

The function scale(x) with one parameter works fine.
But when you try to use a second parameter scale(x,y) it doesn't work
(where x : scale of the width, y : scale of the height).
To solve that, I used the pdfkit transform function instead of scale:

  // canvas2pdf.PdfContext.prototype.scale = function (x, y) {
  //   this.doc.scale(x, y);
  // };

  canvas2pdf.PdfContext.prototype.scale = function (x, y=x) {
    this.doc.transform(x,0,0,y,0,0);
  };

The canvas2pdf can not draw the plot in canvas tag region?

Hi developer,
I want to bind the tag like,, to draw the vector plot using canvas2pdf API

but it seem can not been work like i said before.
The canvas2pdf only create a object like new canvas2pdf.PdfContext(stream) , however it seem can not be selected the draw region by
canvas id selector.

how can i assign the region where i want to plot into canvas? can i hope do that?
Best
hanhuihong

canvas2pdf doesnt capture iframe in pdf

I have a couple of iframe with charts on my page. I was able to download the pdf for a particular DOM element but it doesn't capture iframe. any thoughts?

How to get it to work without nodejs

Hi there,

I'm trying to use this module without nodejs, but I'm getting an error telling me PdfContext is undefined. Here is my code for reference:

(index.html)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="blob-stream.js"></script>
    <script src="file-saver.min.js"></script>
    <script src="canvas2pdf.min.js"></script>
    <script src="./index.js"></script>
</head>

<body>
...
</body>

</html>

The file canvas2pdf.min.js above is the /dist/canvas2pdf.js file

(index.js)

// Create a new PDF canvas context.
const ctxPdf = new PdfContext(blobStream());

// draw your canvas like you would normally
ctxPdf.fillStyle = "yellow";
ctxPdf.fillRect(100, 100, 100, 100);
// more canvas drawing, etc...

// convert your PDF to a Blob and save to file
ctxPdf.stream.on("finish", function () {
  var blob = ctxPdf.stream.toBlob("application/pdf");
  saveAs(blob, "example.pdf", true);
});
ctxPdf.end();

And this is the error the browser is throwing Uncaught ReferenceError: PdfContext is not defined

Any idea what I'm doing wrong?

fill()

Hi again,

I am still testing your library and found a problem with the fill() function.
The following is suppose to produce a red rectangle with black border:

ctx.beginPath();
ctx.moveTo(170, 80);
ctx.rect(20,20,150,100);
ctx.fillStyle = 'red';
ctx.fill();
ctx.strokeStyle = 'black';
ctx.lineWidth = 5;
ctx.stroke();

Like this one:
image
But instead I just get a red rectangle without border:
image

Why the saveAs function not found when using the demo code?

Hi Developer,

      <link rel="stylesheet" href="/api/static/web/plugins/bootstrap-3.4.1/css/bootstrap.min.css">

<script src="/api/static/web/js/jquery-3.6.0.min.js"></script>
<script src="/api/static/web/js/pdfkit.js"></script>
<script src="/api/static/web/js/blob-stream.js"></script>
<script src="/api/static/web/js/canvas2pdf.js"></script>

var ctx = new canvas2pdf.PdfContext(blobStream());

//draw your canvas like you would normally
ctx.fillStyle = 'yellow';

ctx.fillRect(100, 100, 100, 100);
// more canvas drawing, etc...

//convert your PDF to a Blob and save to file
ctx.stream.on('finish', function () {
    var blob = ctx.stream.toBlob('application/pdf');
    saveAs(blob, 'example.pdf', true);
});

ctx.end()
when i runing above code, it show me the error:
image

Had any advices for this issue?
Best

Could it run on browser?

I copied canvas2pdf.js from dist and require it from ViolentMonkey.
The browser throws:

Uncaught TypeError: (intermediate value)[Symbol.iterator] is not a function

I don't think it can't run on browser, but do I forget anything?

ctx.clip()

The clip() function seem to be implemented in the file 'canvas2pdf.js':

canvas2pdf.PdfContext.prototype.clip = function () { this.doc.clip(); } ;

But when I try to use it with this example from https://www.w3schools.com/tags/canvas_clip.asp, it doesn't work:

var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); // Clip a rectangular area ctx.rect(50, 20, 200, 120); ctx.stroke(); ctx.clip(); // Draw red rectangle after clip() ctx.fillStyle = "red"; ctx.fillRect(0, 0, 150, 100);

Am I missing something ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.