{"id":13721918,"url":"https://github.com/pshihn/puppet-canvas","last_synced_at":"2025-08-21T10:31:28.436Z","repository":{"id":42936569,"uuid":"236063339","full_name":"pshihn/puppet-canvas","owner":"pshihn","description":"HTML5 Canvas implementation for NodeJS backed by Puppeteer","archived":false,"fork":false,"pushed_at":"2023-05-07T20:28:29.000Z","size":110,"stargazers_count":65,"open_issues_count":8,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-14T06:05:00.027Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pshihn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-01-24T18:52:13.000Z","updated_at":"2024-10-31T03:35:47.000Z","dependencies_parsed_at":"2024-01-06T01:09:55.438Z","dependency_job_id":"bafa0bdb-5d0a-4ee0-ab6d-136d963dca9e","html_url":"https://github.com/pshihn/puppet-canvas","commit_stats":{"total_commits":33,"total_committers":3,"mean_commits":11.0,"dds":0.4242424242424242,"last_synced_commit":"feae9a721766776b0b039cca21e4167a66c3be3c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pshihn%2Fpuppet-canvas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pshihn%2Fpuppet-canvas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pshihn%2Fpuppet-canvas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pshihn%2Fpuppet-canvas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pshihn","download_url":"https://codeload.github.com/pshihn/puppet-canvas/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230507051,"owners_count":18236944,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T01:01:22.744Z","updated_at":"2024-12-19T22:08:20.580Z","avatar_url":"https://github.com/pshihn.png","language":"TypeScript","funding_links":[],"categories":["Packages"],"sub_categories":[],"readme":"# puppet-canvas\npuppet-canvas is a [Puppeteer](https://github.com/puppeteer/puppeteer) backed implementation of HTML [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) for NodeJS. \n\n\u003cimg alt=\"puppet-canvas logo\" src=\"https://user-images.githubusercontent.com/833927/73148934-a7de4580-4073-11ea-9956-f88bb8355d8f.png\" height=\"200\" align=\"right\"\u003e\n\n## Installation\n\n```bash\n$ npm install puppet-canvas --save\n```\n\n## Usage\n\nFollowing example draws a house and grabs the data url of the image.\n\n```javascript\nimport { createCanvas, close } from 'puppet-canvas';\n// OR const { createCanvas, close } = require('puppet-canvas')\n\nasync(() =\u003e {\n\nconst canvas = await createCanvas(400, 400);\nconst ctx = await canvas.getContext('2d');\n\n// Draw a house\nctx.lineWidth = 10;\nctx.strokeRect(75, 140, 150, 110);\nctx.fillRect(130, 190, 40, 60);\nctx.moveTo(50, 140);\nctx.lineTo(150, 60);\nctx.lineTo(250, 140);\nctx.closePath();\nctx.stroke();\n\n// Get the image as a data url\nconst dataUrl = await canvas.toDataURL();\n\n// Release\nawait close();\n\n})();\n```\n![house image](https://user-images.githubusercontent.com/833927/73148753-c263ef00-4072-11ea-923c-2ec0f1c0306c.png)\n\n### Using images\n\nTo use external images in your canvas, first load the image using the `loadImage` method.\n\n```javascript\nimport { createCanvas, loadImage } from 'puppet-canvas';\n\nconst canvas = await createCanvas(400, 400);\nconst ctx = await canvas.getContext('2d');\nconst image = await loadImage('https://....', canvas);\nawait ctx.drawImage(image, 100, 100);\n```\n\n### Using complex objects\n\nAny non-serializable object returned by puppeteer is automatically proxied as well. So one can use/pass more complex objects like a gradient:\n\n```javascript\nconst gradient = await ctx.createLinearGradient(20, 0, 220, 0);\ngradient.addColorStop(0, 'green');\ngradient.addColorStop(.5, 'cyan');\ngradient.addColorStop(1, 'green');\nctx.fillStyle = gradient;\nctx.fillRect(20, 20, 200, 100);\n```\n\n### Using custom fonts\nWhen using a custom font for rendering text, you can ensure the font is loaded by calling the `loadFont` methods. \n\n```javascript\nimport { createCanvas, loadFont } from 'puppet-canvas';\n\nconst canvas = await createCanvas(400, 400);\nconst ctx = await canvas.getContext('2d');\n\nawait loadFont(\n  'Bangers',\n  'https://fonts.gstatic.com/s/bangers/v12/FeVQS0BTqb0h60ACH55Q2J5hm24.woff2',\n  canvas\n);\nctx.font = `bold 48px Bangers`;\nctx.fillText('Hello world', 50, 100);\n```\n\n## Implementation\n**puppet-canvas** creates a canvas on a puppeteer instance, and exposes the API via a JavaScript Proxy. \n\nA side effect of this is that all calls, essentially become `async`. For normal drawing, one doesn't need to `await` each command unless a value is being returned.\n\nA *proxied* solution is somewhat better than alternate ones because, firstly, the rendering is exactly what the browser would have rendered (Chrome). Secondly, this is mostly future-proof since all methods are just proxied to the actual instance. So, any new API added to the Canvas, should automagically work. \n\n#### Implentation Shortcomings\n\nThough a proxied implementation is simpler, smaller, and more flexible, it can be slower than alternative native implementations. For example, manipulating lots of pixels, one pixel at a time, may be slow and not recommended.\n\nThe other shortcoming is from a dev experience, everything is an `async` call. So it creates more code for getting child object and properties. The following code:\n```javascript\nconst imageDataLength = ctx.createImageData(10, 10).data.length;\n```\nhas to be refactored as\n```javascript\nconst imageData = await ctx.createImageData(10, 10);\nconst imageDataLength = await (await imageData.data).length;\n```\n\n#### Why don't I just use puppeteer\n\nYes, you can and for some cases it may even be a better dev experience. \n\n**puppet-canvas** provides a simple abstraction layer so you don't have to jump in and out of Puppeteer's execution context all the time. You treat the canvas very similar to canvas on the web, and not worry much about anything else.\n\n## Full API\n\n#### createCanvas(width: number, height: number) =\u003e Promise\\\u003cHTMLCanvasElement\\\u003e\n  \nCreates a canvas instance with the specified width and height (in pixels)\n\n#### linkCanvas(canvas: ElementHandle\\\u003cHTMLCanvasElement\\\u003e) =\u003e Promise\\\u003cHTMLCanvasElement\\\u003e\n\nSay, you want to use this with an existing instance of puppeteer, you can pass in the ElementHandle of the canvase in your page. \n\n#### close() =\u003e Promise\n\nClose associated puppeteer instance. Usually called at the end.\n\n#### releaseCanvas(canvas: HTMLCanvasElement) =\u003e Promise\n\nRelease the canvas instance, if you do not want puppet-canvas to proxy it anymore, but still want to keep the canvas instance around \n\n#### screenshotCanvas(canvas: HTMLCanvasElement, options?: ScreenshotOptions) =\u003e Promise\u003cstring | Buffer\u003e\nTake a screenshot of the canvas. The method optionally takes in `ScreenshotOptions` which are the same options as described in [Puppeteer screenshot method](https://pptr.dev/#?product=Puppeteer\u0026version=v2.0.0\u0026show=api-pagescreenshotoptions)\n\n#### loadFont(name: string, url: string, canvas: HTMLCanvasElement) =\u003e Promise\nLoad a font for the canvas element to use. **name** is the `font-family` name of the font. **url** is the url to the font file (like a `woff` file)\n\n#### loadImage(url: string, canvas: HTMLCanvasElement, page?: Page) =\u003e Promise\\\u003cHTMLImageElement\\\u003e\nLoad an image from a URL that could be used by the canvas, e.g. for drawing the image on the canvas. \n\n\n## License\n[MIT License](https://github.com/pshihn/puppet-canvas/blob/master/LICENSE) (c) [Preet Shihn](https://twitter.com/preetster)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpshihn%2Fpuppet-canvas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpshihn%2Fpuppet-canvas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpshihn%2Fpuppet-canvas/lists"}