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(){});
Brian McCutchon
  • 8,354
  • 3
  • 33
  • 45
dmee3
  • 304
  • 2
  • 11
  • 1
    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 code – nicholaswmin Jan 18 '15 at 16:29
  • The link to the spiral raster example should have a health warning! ;) – Ben Smith Jan 18 '15 at 22:11
  • 1
    @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 :/ – dmee3 Jan 19 '15 at 23:42
  • 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. – Simon Robb Jul 10 '15 at 02:13
  • 1
    Did you use something like [node-canvas](https://github.com/Automattic/node-canvas) to draw on the canvas with node? You can use [CEF](https://bitbucket.org/chromiumembedded/cef), [cefpython](https://code.google.com/p/cefpython/) or [phantomjs](http://phantomjs.org/) to draw on server side. – arthur.sw Jul 28 '15 at 12:06

1 Answers1

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>
Ritesh Karwa
  • 2,196
  • 1
  • 13
  • 17
  • 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). – dmee3 Jun 25 '15 at 21:06