Skip to content

Instantly share code, notes, and snippets.

@elykahn
Forked from mattdesl/about.md
Created January 4, 2020 07:22
Show Gist options
  • Select an option

  • Save elykahn/acd0a1d3cfb3c9d1faae22b7055bbcb3 to your computer and use it in GitHub Desktop.

Select an option

Save elykahn/acd0a1d3cfb3c9d1faae22b7055bbcb3 to your computer and use it in GitHub Desktop.

Revisions

  1. @mattdesl mattdesl revised this gist Dec 28, 2019. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions about.md
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,13 @@ npm install canvas-sketch-cli -g
    Then copy the `sketch.js` and `canvas-to-svg.js` into a new folder, say the folder is called `mysketch`. Install dependencies:

    ```sh
    # move into it
    cd mysketch

    # make a new package.json
    npm init -y

    # install deps
    npm install canvas-sketch canvas-sketch-util canvas2svg --save
    ```

  2. @mattdesl mattdesl revised this gist Dec 28, 2019. 1 changed file with 23 additions and 0 deletions.
    23 changes: 23 additions & 0 deletions about.md
    Original file line number Diff line number Diff line change
    @@ -21,4 +21,27 @@ Then run the sketch:

    ```
    canvas-sketch sketch.js --open
    ```

    ## Usage in Existing Sketches

    It looks like this:

    ```js
    const canvasSketch = require('canvas-sketch');
    const svg = require('./canvas-to-svg.js');

    const settings = {
    // ... your settings ...
    };

    const sketch = () => {
    return svg(props => {
    const { context, width, height } = props;

    // ... draw your art ...
    });
    };

    canvasSketch(sketch, settings);
    ```
  3. @mattdesl mattdesl created this gist Dec 28, 2019.
    24 changes: 24 additions & 0 deletions about.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    # PNG + SVG export from canvas-sketch

    The helper function `canvas-to-svg.js` wraps a given render function (or renderer object) so that you can use Canvas2D context methods as usual, but upon single frame export (with Cmd/Ctrl + S) it will produce both a PNG and SVG file.

    This uses [canvas2svg](https://github.com/gliffy/canvas2svg) which is not a perfect solution, as the Canvas2D API was never designed to be translated to SVG. Its best to stick with simple shape and path operations.

    Full instructions: first install the canvas-sketch CLI if you haven't already:

    ```sh
    npm install canvas-sketch-cli -g
    ```

    Then copy the `sketch.js` and `canvas-to-svg.js` into a new folder, say the folder is called `mysketch`. Install dependencies:

    ```sh
    npm init -y
    npm install canvas-sketch canvas-sketch-util canvas2svg --save
    ```

    Then run the sketch:

    ```
    canvas-sketch sketch.js --open
    ```
    51 changes: 51 additions & 0 deletions canvas-to-svg.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,51 @@
    const canvasSketch = require("canvas-sketch");
    const Canvas2SVG = require("canvas2svg");
    const Color = require("canvas-sketch-util/color");

    module.exports = canvasToSVG;
    function canvasToSVG(sketch) {
    const obj = typeof sketch === "function" ? {} : sketch;
    const render = typeof sketch === "function" ? sketch : obj.render;
    return {
    ...obj,
    render(props) {
    render(props);
    if (props.exporting && !props.recording) {
    return [props.canvas, serialize(render, props)];
    }
    }
    };
    }

    function fix(node, name) {
    if (!node.hasAttribute(name) || !node.getAttribute(name)) return;
    const attr = node.getAttribute(name);
    const parsed = Color.parse(attr);
    if (parsed) node.setAttribute(name, parsed.hex);
    }

    function serialize(draw, props) {
    const {
    canvasWidth,
    canvasHeight,
    width,
    height,
    units,
    scaleX,
    scaleY
    } = props;
    const context = new Canvas2SVG(canvasWidth, canvasHeight);
    draw({ ...props, context });
    const svg = context.getSvg().cloneNode(true);
    svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
    [...svg.querySelectorAll("*")].forEach(node => {
    fix(node, "fill");
    fix(node, "stroke");
    });
    svg.setAttribute("width", width + units);
    svg.setAttribute("height", height + units);
    return {
    data: new XMLSerializer().serializeToString(svg),
    extension: ".svg"
    };
    }
    80 changes: 80 additions & 0 deletions sketch.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,80 @@
    const canvasSketch = require("canvas-sketch");
    const svg = require("./canvas-to-svg.js");

    const settings = {
    scaleToView: true,
    dimensions: "A4",
    units: "in",
    animate: false,
    time: 1.5,
    duration: 5,
    pixelsPerInch: 300
    };

    const sketch = async () => {
    // Setup your font assets here
    const fontName = "Suprapower-Heavy";
    const fontFormat = ".otf";
    const fontPath = "assets/fonts/";

    try {
    // We ensure the font is loaded before rendering,
    // otherwise the first frame might not draw the correct font.
    const fontUrl = `${fontPath}${fontName}${fontFormat}`;
    const font = new window.FontFace(fontName, `url(${fontUrl})`);
    await font.load();
    document.fonts.add(font);
    } catch (err) {
    console.warn(`Font not loaded, will fall back to another sans-serif.`);
    }

    return svg(({ context, width, height, playhead }) => {
    const margin = 0.5; // half inch margin

    // fill paper white bg
    context.fillStyle = "hsl(0, 0%, 100%)";
    context.fillRect(0, 0, width, height);

    // fill gray ink bg
    context.fillStyle = "hsl(0, 0%, 90%)";
    context.fillRect(margin, margin, width - margin * 2, height - margin * 2);

    // draw some rect shape
    context.save();
    context.fillStyle = "tomato";
    const size = width * 0.5;
    context.translate(width / 2, height / 2);
    context.rotate(playhead * Math.PI * 2);
    context.translate(-size / 2, -size / 2);
    context.fillRect(0, 0, size, size);
    context.restore();

    // draw some path shape
    context.beginPath();
    context.arc(
    width / 2,
    height / 2,
    width / 4,
    0,
    Math.PI * 2 * playhead,
    false
    );
    context.lineWidth = width * 0.1;
    context.lineJoin = "round";
    context.lineCap = "round";
    context.strokeStyle = "rebeccapurple";
    context.globalAlpha = 0.85;
    context.stroke();
    context.globalAlpha = 1;

    // draw some text - which will be exported as <text>
    // (i.e. no fonts embedded!)
    context.font = `${width * 0.075}px "${fontName}", "Helvetica", sans-serif`;
    context.textAlign = "center";
    context.textBaseline = "middle";
    context.fillStyle = "black";
    context.fillText("SVG", width / 2, height / 2);
    });
    };

    canvasSketch(sketch, settings);