Paper.js: Allow using paperjs without canvas

Created on 9 Feb 2015  路  21Comments  路  Source: paperjs/paper.js

Note: This feature was already requested in issue #561, but #561 has changed into a more sprecific one about plumin.js. Therefore I opened this issue which only covers the request for canvasless paperjs projects.

It would be great to have a simple way of using paperjs projects without a canvas element.

Why would this be useful?

  1. Some projects may only do some processing of vector graphics without displaying them. Requring a canvas for these projects only adds unnecessary overhead.
  2. Currently paperjs cannot be used in a web worker, because web workers cannot access the DOM. Providing a way to use paperjs without a canvas would overcome this limitation.

How would the API look like?
The easiest way would certainly be to create a canvasless projects by simply calling the Project constructor without any arguments, just like this: var paperProjCanvasless = new paper.Project();

How can this be implemented?
As explained by @lehni in #561, using a DummyView class that only implements the necessary functions for offscreen processing like View#getPixelSize() and View#getTextWidth(), but ignores all rendering calls, would be the easiest way.

I will try to implement a simple DummyView class and post my results here.

important feature

Most helpful comment

I'm having some problems exporting SVG from the web worker's 'worker.js' script.

Uncaught TypeError: Cannot read property 'createElementNS' of undefined

Is that because that worker.js doesn't have access to the document needed to make an SVG?

It seems like exportSVG works on node.js running paper.js, but how can that have access to the document outside the browser?

All 21 comments

+1

+1 I have hit the same issue with web workers.

This feature would be really useful. I want to share some code between nodejs and the browser and use paperjs for some calculations serverside. Is there an easy way to implement the mentioned DummyView?

Yep, having the main scope of Paper.js in the main window and delegating image processing to WebWorkers (by sending ImageData via postMessage) would be ace.

Related: #582

So I've finally implemented worker support in 8fb7c415379f6d0711cb8ec9842cd8529a42c51b. Please test and let me know if it works for you!

You can download a fresh build here:
https://github.com/paperjs/paper.js/tree/prebuilt/module
https://github.com/paperjs/paper.js/tree/prebuilt/dist

There's also an example illustrating how to use it here:
https://github.com/paperjs/paper.js/tree/develop/examples/Worker

Very cool! I'll have to play with this soon :)

Please release to npm too thx :)

Should a canvas-less paperjs project be able to export SVG? I can't tell if I'm doing this wrong or just missing the point. I've got a simple Node.js project that draws a line (taken from the Using JavaScript Directly tutorial) and tried to export the result. The JSON exports fine, but not the SVG. Is this because the SVG export relies on the existence of a DOM?

Node.js code:

var paper = require('paper');
paper.setup([640, 480]);

// Create a Paper.js Path to draw a line into it:
var path = new paper.Path();
// Give the stroke a color
path.strokeColor = 'black';
var start = new paper.Point(100, 100);
// Move to start and draw a line from there
path.moveTo(start);
// Note that the plus operator on Point objects does not work
// in JavaScript. Instead, we need to call the add() function:
path.lineTo(start.add([ 200, -50 ]));
// Draw the view now:
paper.view.draw();

console.log(paper.project.exportJSON());
console.log(paper.project.exportSVG());

Console output:

[["Layer",{"applyMatrix":true,"children":[["Path",{"applyMatrix":true,"segments":[[100,100],[300,50]],"strokeColor":[0,0,0]}]]}]]
HTMLUnknownElement {}

I found some related GitHub issues with a familiar face:
https://github.com/tmpvar/jsdom/issues/620
https://github.com/tmpvar/jsdom/issues/1371
https://github.com/paperjs/paper.js/issues/821

But I still can't tell if the HTMLUnknownElement {} is expected in my case.

Yes that's expected... Here's the crucial part from above links:

SVG will indeed be represented by HTMLUnknownElement in our implementation, since we don't have a SVG DOM, but that shouldn't cause any problems.
https://github.com/tmpvar/jsdom/issues/1371#issuecomment-177606614

Try this and you'll see it works:

console.log(paper.project.exportSVG({ asString: true }));

Oh I see, the SVG worked fine, but I was trying to console out the DOM tree itself instead of a string representation... your fix worked perfectly, thank you!

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="480"><g fill="none" fill-rule="nonzero" stroke="#000000" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M100,100l200,-50"></path></g></svg>

Paper.js still seems to pull in the canvas module in node, even if only a canvas-less project is created. Could canvas be lazily loaded as soon as it's needed?
The motivation is that canvas is a binary module that requires a custom build process on electron.

I'm no Node.js expert, but we're already defining the canvas as an optional dependency. I'm not sure there is more we can do? NPM is primarily for use in Node.js. If we don't define "canvas" as a dependency at all, then we'll hit all the people who actually want to use Paper.js it in Node.js.

How would you propose to achieve your suggestion?

  "optionalDependencies": {
    "canvas": "^1.3.5"
  },

It seems to me that canvas is require()'d anyway, whether it's used or not (see dist/node/canvas). But even moving the call to require to just before it's used didn't work for me, so maybe I fail to understand how canvasless mode is triggered in node.

Edit: Just to clarify, this is not really about dependencies for NPM but about the call to require('canvas') in node

Oh I see. Canvas-less mode in Node.js wasn't planned for so far. Could you open a new issue for that, and provide some context? It certainly makes sense to support that too.

I'm having some problems exporting SVG from the web worker's 'worker.js' script.

Uncaught TypeError: Cannot read property 'createElementNS' of undefined

Is that because that worker.js doesn't have access to the document needed to make an SVG?

It seems like exportSVG works on node.js running paper.js, but how can that have access to the document outside the browser?

Yeah I don't think you can use a worker to build SVGs. You'll have to send the scene graph back as JSON and do that in the main thread.

In node.js it works through the use of JSDOM, which emulates a browser DOM.

This may (or may not) be helpful to people Googling this issue.

When I got the error Uncaught typeError: Cannot read property 'createElementNS' of undefined running in node.js it was because I hadn't got jsdom in my packages - I had to explicitly require it (i.e. npm install jsdom).

(I ended up using [email protected] because that's what nvm installed - other versions probably work too! )

@deanWombourne this was helpful, thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wes-r picture wes-r  路  3Comments

jsbroks picture jsbroks  路  4Comments

9oelM picture 9oelM  路  5Comments

croqaz picture croqaz  路  6Comments

khurramraheel picture khurramraheel  路  7Comments