Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

P5.js instance: export to SVG

Tags:

export

svg

p5.js

A p5.js sketch is creating a plot that I would like to export as SVG.

The plot is not static: it must be modified (in the demo by clicking on the circle) and then saved by pressing the Save SVG button.

P5.js alas doesn't provide beginDraw() and endDraw() as the standard Processing.

I am using https://github.com/zenozeng/p5.js-svg/, as described in this blog: https://makeyourownalgorithmicart.blogspot.de/2018/03/creating-svg-with-p5js.html

Saving a static SVG (without user interaction) is easy: uncommenting p.SVG and p.save() the code works:

<html>
<head>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.min.js"></script>
    <script type="text/javascript" src="https://github.com/zenozeng/p5.js-svg/releases/download/v0.5.2/p5.svg.js"></script>
</head>
<body>

    <script>

        let colors = ["red", "orange", "yellow", "lime", "green", "blue", "fuchsia"];
        let idx = 0;

        let sketch = function (p) {

            p.setup = function () {
                p.createCanvas(400, 400); // (400, 400, p.SVG);  <--------------
                p.noLoop();
            };

            p.draw = function () {

                p.background("white");
                p.fill(colors[idx]);
                p.stroke("black");
                p.strokeWeight(3);
                p.ellipse(200, 200, 200,200);

                // p.save();   // <-----------------------------------
            };

            p.mousePressed = function() {
                if (p.dist(p.mouseX, p.mouseY, 200,200) < 100) {
                    idx++;
                    idx %= colors.length;
                    p.redraw();
                }
            }
        };

        let myp5 = new p5(sketch, "my_image");

        let save_svg = function() {
            // ????   <------------------------------
        }


    </script>

    <div id="my_image"></div>

    <button onclick="save_svg()">Save SVG</button>

</body>
</html>

How can the user modify the plot and then save the final version only upon request? Is this possible using p5.js-svg or any other library?

I also tried https://github.com/gliffy/canvas2svg but I could not have it working at all.

like image 778
Alex Poca Avatar asked May 03 '18 14:05

Alex Poca


1 Answers

I found a solution: not the cleanest one, but it works. A bug concerns fonts: if you load a font, inside the SVG it is rendered as geometry. This means the SVG can be huge if there is a lot of text and slow to visualize.

I create a double canvas: a normal one and a SVG. The latter is put into a hidden div. Whenever I am done playing with it, I call the SVG save function that will use the latest calculated parameters (they must be shared between the two, of course).

<html>
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.min.js"></script>
<script type="text/javascript" src="https://github.com/zenozeng/p5.js-svg/releases/download/v0.5.2/p5.svg.js"></script>
</head>
<body>

    <script>

        let colors = ["red", "orange", "yellow", "lime", "green", "blue", "fuchsia"];
        let idx = 0;

        let sketch = function (p) {

            p.setup = function () {

                if (p.type === "SVG") {
                    p.createCanvas(400, 400, p.SVG);
                }
                else if (p.type === "NORMAL") {
                    p.createCanvas(400, 400);
                }
                else {
                    alert("don't know which canvas to create")
                }
                p.noLoop();
            };

            p.draw = function () {
                p.background("white");
                p.fill(colors[idx]);
                p.stroke("black");
                p.strokeWeight(3);
                p.ellipse(200, 200, 200,200);

                p.fill("black");
                p.noStroke();

                p.textStyle(p.NORMAL);
                p.text("test", 100, 100);

                p.textStyle(p.BOLD);
                p.text("bold", 200, 200);

                waiting = false;
            };


            p.mousePressed = function() {
                if (p.dist(p.mouseX, p.mouseY, 200,200) < 100) {
                    idx++;
                    idx %= colors.length;
                    p.redraw();
                }
            };

            p.save_canvas = function() {
                p.draw();
                p.save();
            }
        };

        cvs = new p5(sketch, "my_image");
        cvs.type = "NORMAL";

        svg = new p5(sketch, "hidden_div");
        svg.type = "SVG";


    </script>

    <div id="my_image"></div>
    <div id="hidden_div" style="display:none"></div>

    <button onclick="svg.save_canvas()">Save SVG</button>

</body>
</html>
like image 131
Alex Poca Avatar answered Nov 15 '22 08:11

Alex Poca