Open dipamsen opened 3 years ago
P.S. There is an issue with using this method of p5, whenever any kind of error is thrown, (undefined variable/invalid syntax, etc) in the sketch, only this error will show in the console:
Error: Uncaught [TypeError: Cannot read property '_ownerDocument' of undefined]
at reportException (jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:62:24)
at innerInvokeEventListeners (jsdom\lib\jsdom\living\events\EventTarget-impl.js:333:9)
at invokeEventListeners (jsdom\lib\jsdom\living\events\EventTarget-impl.js:274:3)
at DocumentImpl._dispatch (jsdom\lib\jsdom\living\events\EventTarget-impl.js:221:9)
at fireAnEvent (jsdom\lib\jsdom\living\helpers\events.js:18:36)
at dispatchEvent (jsdom\lib\jsdom\living\nodes\Document-impl.js:475:9)
at jsdom\lib\jsdom\living\nodes\Document-impl.js:480:11
at new Promise (<anonymous>)
at onLoad (jsdom\lib\jsdom\living\nodes\Document-impl.js:478:14)
at Object.check (jsdom\lib\jsdom\browser\resources\resource-queue.js:76:23) TypeError: Cannot read property '_ownerDocument' of undefined
at innerInvokeEventListeners (jsdom\lib\jsdom\living\events\EventTarget-impl.js:327:26)
at invokeEventListeners (jsdom\lib\jsdom\living\events\EventTarget-impl.js:274:3)
at EventTargetImpl._dispatch (jsdom\lib\jsdom\living\events\EventTarget-impl.js:221:9)
at fireAnEvent (jsdom\lib\jsdom\living\helpers\events.js:18:36)
at Document.<anonymous> (jsdom\lib\jsdom\browser\Window.js:776:9)
at Document.callTheUserObjectsOperation (jsdom\lib\jsdom\living\generated\EventListener.js:26:30)
at innerInvokeEventListeners (jsdom\lib\jsdom\living\events\EventTarget-impl.js:318:25)
at invokeEventListeners (jsdom\lib\jsdom\living\events\EventTarget-impl.js:274:3)
at DocumentImpl._dispatch (jsdom\lib\jsdom\living\events\EventTarget-impl.js:221:9)
at fireAnEvent (jsdom\lib\jsdom\living\helpers\events.js:18:36)
I don't have any idea on what is causing this error, as I have not checked the JSDOM source code out.
CodingTrain/Random-Whistle ported to node: here
@dipamsen Great job! I worked on this over the weekend and got pretty close but I don't think I would have gotten there. Thanks for sharing this. I hope to use this to output p5.js sketches to pixel arrays using a raspberry pi.
TL;DR: scroll down to the bottom for the templates
After studying the source code of
p5.js
, this is what I have gathered so far:p5 Instance Mode
For making p5 work in instance mode I created this template:
In this way, p5.js can be used in Instance Mode to work with
node-canvas
Click here to see the codes for
**`saveAsPNG` - Saves the canvas Image to filname using fs** ```js async function saveAsPNG(p5Inst, filename = "sketch", exit = true) { const fs = require("fs"); const buffer = p5Inst._renderer.drawingContext.canvas.toBuffer() await fs.promises.writeFile(filename + ".png", buffer) if (exit) process.exit(0) } ``` **`setupWindow` - Add necessary variables to `global` for p5 to run** ```js function setupWindow(w = 100, h = 100) { // Import required stuff const { createCanvas } = require("canvas"); const { JSDOM } = require("jsdom"); const { performance } = require("perf_hooks"); // All the global properties will be available to p5 global.window = global; // Use JSDOM to simulate DOM methods const dom = new JSDOM(); global.document = dom.window.document; const nodeCanvas = createCanvas(w, h); // p5 will use the methods on nodeCanvas context (overriding JSDOM's getContext function) dom.window.HTMLCanvasElement.prototype.getContext = (type) => { return nodeCanvas.getContext(type); }; // p5 uses window.performance global.performance = performance; // window.screen is used to determine displayWidth and displayHeight // in this case it will be undefined global.screen = {}; // p5 uses events "load" and "error" // Using JSDOM equivalent global.addEventListener = dom.window.addEventListener.bind(dom.window); global.removeEventListener = dom.window.removeEventListener.bind(dom.window); // Navigator.userAgent is used by p5 to polyfill methods in older browsers (safari) global.navigator = { userAgent: "node" }; // when we declare a function in node, it doesn't pollute global scope // So implicitly write code so that p5 can access these functions on global/window. // UNCOMMENT NEXT TWO LINES WHEN USING GLOBAL MODE // global.setup = setup // global.draw = draw } ```saveAsPNG
andsetupWindow
:Going further - Global Mode!
This is the template for using p5.js in node with Global Mode:
In this case as well, the functions
saveAsPNG
andsetupWindow
should be appended at the end of the file, with the last two lines ofsetupWindow
uncommented.This is the output of the global mode code
Use these Templates!
To Use these templates, first install these node-modules
npm i p5 canvas jsdom
node-canvas
withp5.js
in global modenode-canvas
withp5.js
in instance mode