Implementing a Paper.js spiral raster example on server-side
Asked Answered
P

1

7

I am trying to draw a spiral raster example (link) on a server (running Node.js). However, I am facing an issue where my path is not displayed on the exported frame and I can only see the downloaded image. Probably a silly mistake on my side, however, days of looking through Google and documentation didn't help me to solve an issue.

What I did:

  • Add paper. prefixes
  • Changed +/- to corresponding add() and subtract()
  • Tried presenting a path within a layer.

Here is my code:

var paper = require('paper');
var fs = require('fs');
var drawer = {};

var canvas = new paper.Canvas(1000, 1000);
paper.setup(canvas);

var layer = paper.project.activeLayer;

drawer.drawSpiral = function(url, filename, fn) {   
    var url = 'http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png';
    var raster = new paper.Raster(url);

    raster.onLoad = function() {
        raster.fitBounds(paper.view.bounds);

        var position = paper.view.center;
        var count = 0;
        var max = Math.min(raster.bounds.width, raster.bounds.height) * 0.5;

        var path = new paper.Path();
        path.fillColor = 'black';
        path.closed = true;

        while ((paper.view.center - position).length < max) {
            count++;

            var vector = new paper.Point(count * 5, count / 100);
            var rot = vector.rotate(90);
            var color = raster.getAverageColor(position.add(vector).divide(2));
            var value = color ? (1 - color.gray) * 3.7 : 0;

            rot.length = Math.max(value, 0.2);
            path.add(position.add(vector).subtract(rot));
            path.insert(0, position.add(vector).add(rot));

            position = position.add(vector);
        }

        path.smooth();
        layer.insertChild(0, path);
        layer.fitBounds(paper.view.bounds);
        drawer.exportPNG(filename, fn);  
    };
}

drawer.exportPNG = function(filename, fn) {
    out = fs.createWriteStream(__dirname + '/static/img/' + filename + '.png');
    stream = canvas.pngStream();

    stream.on('data', function(chunk) {
        out.write(chunk);
    });

    stream.on('end', function() {
        fn();
    });
}

module.exports = drawer;

Invoked, obviously, like this:

var drawer = require('./drawer.js');
drawer.drawSpiral('','abc', function(){});
Prosecute answered 9/1, 2015 at 17:13 Comment(5)
I'm not familiar with using paper.js inside Node.js, but I'd try to update the View after drawing - try adding paper.view.update() at the end of your drawing codeFishnet
The link to the spiral raster example should have a health warning! ;)Loewi
@Nicholas, thanks for the suggestion, I will try it whenever I get a second. However, Nodejs example that was included in the repo also drew some paths and displayed them successfully without that line. Weird :/Prosecute
Great suggestion @NicholasKyriakides, that fixed my experience of the OP's problem. I imagine the reason the sample repo didn't need that line was for the same reason it's only needed sometimes in the browser: PaperScript is smart enough to remove the need for it under the hood, but requires a certain method of implementation to do so. I'd guess there is some implementation detail in the sample repo that has the same effect server-side.Seraph
Did you use something like node-canvas to draw on the canvas with node? You can use CEF, cefpython or phantomjs to draw on server side.Daimon
M
0

Here it works for me . You need to use an image from your system. Ownload an image and then use it

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Spiral Raster</title>
    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/paper.js/0.9.18/paper-full.min.js"></script>
    <script type="text/paperscript" canvas="canvas">
        // Please note: dragging and dropping images only works for
        // certain browsers when serving this script online:
        var path, position, max;
        var count = 0;
        var grow = true;
        var raster = new Raster('mona');
        raster.remove();

        var text = new PointText(view.bounds.bottomRight - [30, 30]);
        text.justification = 'right';
        text.fontSize = 10;
        text.content = window.FileReader
                ? 'drag & drop an image from your desktop to rasterize it'
                : 'to drag & drop images, please use Webkit, Firefox, Chrome or IE 10';

        resetSpiral();

        function onFrame(event) {
            if (grow) {
                if (raster && (view.center - position).length < max) {
                    for (var i = 0, l = count / 36 + 1; i < l; i++) {
                        growSpiral();
                    }
                    path.smooth();
                } else {
                    grow = false;
                }
            }
        }

        function growSpiral() {
                count++;
                var vector = new Point({
                    angle: count * 5,
                    length: count / 100
                });
                var rot = vector.rotate(90);
                var color = raster.getAverageColor(position + vector / 2);
                var value = color ? (color.gray) * 3.7 : 0;
                rot.length = Math.max(value, 0.2);
                path.add(position + vector - rot);
                path.insert(0, position + vector + rot);
                position += vector;
        }

        function resetSpiral() {
            grow = true;

            // Transform the raster, so it fills the view:
            raster.fitBounds(view.bounds);

            if (path)
                path.remove();

            position = view.center;
            count = 0;
            path = new Path();
            path.fillColor = 'black';
            path.closed = true;

            position = view.center;
            max = Math.min(raster.bounds.width, raster.bounds.height) * 0.5;
        }

        function onResize() {
            text.remove();
            if (count > 0)
                resetSpiral();
        }

        function onKeyDown(event) {
            if (event.key == 'space') {
                path.selected = !path.selected;
            }
        }

        function onDocumentDrag(event) {
            event.preventDefault();
        }

        function onDocumentDrop(event) {
            event.preventDefault();

            var file = event.dataTransfer.files[0];
            var reader = new FileReader();

            reader.onload = function ( event ) {
                var image = document.createElement('img');
                image.onload = function () {
                    raster = new Raster(image);
                    raster.remove();
                    resetSpiral();
                };
                image.src = event.target.result;
            };
            reader.readAsDataURL(file);
        }

        DomEvent.add(document, {
            drop: onDocumentDrop,
            dragover: onDocumentDrag,
            dragleave: onDocumentDrag
        });
    </script>
  <style>
  body {
    margin: 0;
    overflow: hidden;
  }
  </style>
</head>
<body>
    <canvas id="canvas" resize style="background-color:white"></canvas>
    <img width="512" height="512" id="mona" style="display: none;" src="it_follows.jpg">
</body>
</html>
Misestimate answered 24/6, 2015 at 19:14 Comment(1)
Hey, Ritesh! Thanks for your answer. I did implement the client side example already though. Question asked regarding drawing in Node.js (on the server side) to return the rendered image to the user (and thus offload the job to my server where it could be cached).Prosecute

© 2022 - 2024 — McMap. All rights reserved.