{"id":16126338,"url":"https://github.com/mattdesl/penplot","last_synced_at":"2025-04-09T13:03:49.897Z","repository":{"id":42568781,"uuid":"84518621","full_name":"mattdesl/penplot","owner":"mattdesl","description":"[DEPRECATED] see canvas-sketch","archived":false,"fork":false,"pushed_at":"2018-06-08T15:49:54.000Z","size":964,"stargazers_count":269,"open_issues_count":1,"forks_count":18,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-04-06T19:15:48.526Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/mattdesl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-10T04:18:33.000Z","updated_at":"2025-02-20T05:59:41.000Z","dependencies_parsed_at":"2022-09-26T16:22:15.661Z","dependency_job_id":null,"html_url":"https://github.com/mattdesl/penplot","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattdesl%2Fpenplot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattdesl%2Fpenplot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattdesl%2Fpenplot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattdesl%2Fpenplot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mattdesl","download_url":"https://codeload.github.com/mattdesl/penplot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248045230,"owners_count":21038553,"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-10-09T21:38:16.498Z","updated_at":"2025-04-09T13:03:49.875Z","avatar_url":"https://github.com/mattdesl.png","language":"JavaScript","readme":"# penplot\n\n[![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges)\n\nAn experimental and highly opinionated development environment for generative and pen plotter art.\n\nSome features:\n\n- Zero configuration: just run a command and start writing `\u003ccanvas\u003e` renderings\n- Fast live-reload on file save\n- Hotkey for high-quality PNG output\n- Hotkey for SVG rendering\n- A builtin library of utilities for random numbers, geometry tools, SVG exporting, and other functions\n- Easy integration with Inkscape and AxiDraw v3\n\n## Quick Start\n\nYou can install this with npm.\n\n```sh\nnpm install penplot -g\n```\n\nHere is a simple command you can use to quick-start a new plot:\n\n```sh\npenplot src/index.js --write --open\n```\n\nThis will write a new `src/index.js` file and open `localhost:9966`. Now start editing your `index.js` file to see the LiveReload in action.\n\n\u003cimg src=\"docs/screenshots/screenshot.png\" width=\"50%\" /\u003e\n\nWhile in your browser session, you can hit `Cmd/Ctrl + P` to export the SVG to a file in your Downloads folder, or `Cmd/Ctrl + S` to save a PNG file.\n\nThe SVG should be formatted to fit a Letter size paper with a pen plotter like AxiDraw V3.\n\n## Penplot Modules\n\nThe *penplot* tool is both a development environment and kitchen sink of utility functions. It tries to make some aspects easier for you, like sizing and printing to SVG or PNG.\n\nThe `--write` flag generates a simple plot that looks like this:\n\n```js\n// Some handy functions \u0026 constants\nimport { PaperSize, Orientation } from 'penplot';\nimport { polylinesToSVG } from 'penplot/util/svg';\nimport { clipPolylinesToBox } from 'penplot/util/geom';\n\n// Export the paper layout \u0026 dimensions for penplot to set up\nexport const orientation = Orientation.LANDSCAPE;\nexport const dimensions = PaperSize.LETTER;\n\n// The plot functiond defines how the artwork will look\nexport default function createPlot (context, dimensions) {\n  const [ width, height ] = dimensions;\n  let lines = [];\n\n  // Add [ x, y ] points to the array of lines\n  // e.g. [ [ 5, 2 ], [ 2, 3 ] ] is one line\n  ... algorithmic code ...\n\n  // Clip all the lines to a 1.5 cm margin for our pen plotter\n  const margin = 1.5;\n  const box = [ margin, margin, width - margin, height - margin ];\n  lines = clipPolylinesToBox(lines, box);\n\n  return {\n    draw,\n    print,\n    background: 'white' // used when exporting the canvas to PNG\n  };\n\n  function draw () {\n    lines.forEach(points =\u003e {\n      context.beginPath();\n      points.forEach(p =\u003e context.lineTo(p[0], p[1]));\n      context.stroke();\n    });\n  }\n\n  function print () {\n    return polylinesToSVG(lines, {\n      dimensions\n    });\n  }\n}\n```\n\nAll units here are in centimeters (including `width` and `height`), which makes it easy to reason about things like line thickness and distances.\n\nUsing an array of line primitives, you can build up complex prints that can be easily exported to SVG or PNG. However, this means everything will be built from line segments; e.g. circles are generated with `cos()` and `sin()`.\n\nSee the [Some Examples](#some-examples) for more inspiration.\n\n## More Commands\n\nHere are some commands you can try.\n\n```sh\n# stub out a new file called plot.js\npenplot plot.js --write\n\n# run plot.js and open the browser\npenplot plot.js --open\n\n# set the output folder for SVG/PNG files\npenplot plot.js --output=tmp\n```\n\n## Print Output\n\nYou can also use this as a tool for developing algorithmic/generative art. For example, you can develop the artwork in a browser for LiveReload and fast iterations, and when you want to print it you can set the dimensions and output size like so:\n\n```js\n// desired orientation\nexport const orientation = Orientation.PORTRAIT;\n\n// desired dimensions in CM (used for aspect ratio)\nexport const dimensions = PaperSize.LETTER;\n\n// your artwork\nexport default function createPlot (context, dimensions) {\n  // your artwork...\n\n  return {\n    outputSize: '300 dpi'\n  }\n}\n```\n\nThe `outputSize` option can be any of the following:\n\n- a string with DPI resolution like `'300dpi'` or `'72 DPI'`\n- a single number to use as the pixel width; in this case the height is computed automatically based on the `dimensions` aspect\n- an array of `[ width, height ]`, where either (or both) can be specified as pixel sizes. If you specify `'auto'`, `-1` or `null` as a dimension, it will be computed automatically based on the aspect ratio\n\nThe default output width is 1280 px.\n\n## Some Examples\n\nIn the [example](./example) folder you will find some variations of plots.\n\n##### [simple-circles.js](./example/simple-circles.js)\n\n\u003cimg src=\"docs/screenshots/circles-1.png\" width=\"50%\" /\u003e\n\nThis example shows the basics of using *penplot* for hardware like AxiDraw V3. You can run it like so:\n\n```sh\npenplot example/simple-circles.js --open\n```\n\nAnd hit `Cmd/Ctrl + S` or `Cmd/Ctrl + P` to save a PNG or SVG file, respectively.\n\n##### [swirling-circles.js](./example/swirling-circles.js)\n\n\u003cimg src=\"docs/screenshots/circles-2.png\" width=\"50%\" /\u003e\n\nThis example shows how you can use a built-in function `clipPolylinesToBox` in `penplot/util/geom.js` to clip the lines to a margin.\n\n##### [generative-paint.js](./example/generative-paint.js)\n\n\u003cimg src=\"docs/screenshots/paint-1.png\" width=\"50%\" /\u003e\n\nThis example shows a more complex algorithmic artwork, and how you can use penplot as a development environment for print-size generative art even when you have no plans to print it to a pen plotter.\n\nThe `outputSize` parameter in this demo is set to `'300 dpi'`, which will convert the `dimensions` and `orientation` to a pixel size suitable for print when saving to PNG.\n\n## License\n\nMIT, see [LICENSE.md](http://github.com/mattdesl/penplot/blob/master/LICENSE.md) for details.\n","funding_links":[],"categories":["Software"],"sub_categories":["Vector Creation"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattdesl%2Fpenplot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmattdesl%2Fpenplot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattdesl%2Fpenplot/lists"}