CodingTrain / CodingTrain/node-p5-test

Using p5.js in Node runtime

Đang mở
#1 3 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
JavaScript
Star
7
Fork
1
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Mô tả

## TL;DR: scroll down to the bottom for the templates
---

After studying the source code of [`p5.js`](https://github.com/processing/p5.js), this is what I have gathered so far:

> [These](https://gist.github.com/ccf46106d311bb7dd93fea40c634eece) variables are available in browser `window` and unavailable in node

## p5 Instance Mode

For making p5 work in instance mode I created this template:

```js
// Adapted from:
// ! Heart Curve
// ! Daniel Shiffman
// https://thecodingtrain.com/CodingChallenges/134-heart-curve.html
// https://youtu.be/oUBAi9xQ2X4
// https://editor.p5js.org/codingtrain/sketches/egvieHyt0

const w = 400,
h = 400;
setupWindow(w, h);

const p5 = require("p5");

new p5((p) => {
const heart = [];
let a = 0;
p.setup = () => {
p.createCanvas(w, h);
while (true) {
const r = p.height / 40;
const x = r * 16 * p.pow(p.sin(a), 3);
const y = -r * (13 * p.cos(a) - 5 * p.cos(2 * a) - 2 * p.cos(3 * a) - p.cos(4 * a));
heart.push(p.createVector(x, y));
// So that it stops
if (a > p.TWO_PI) {
break;
}

a += 0.1;
}
p.background(0);
p.translate(p.width / 2, p.height / 2);

p.stroke(255);
p.strokeWeight(2);
p.fill(150, 0, 100);
p.beginShape();
for (let v of heart) {
p.vertex(v.x, v.y);
}
p.endShape();
saveAsPNG(p, "filename");
};
});

async function saveAsPNG(p5Inst, filename = "sketch", exit = true) {
// --- save as png function code ---
}

function setupWindow(w = 100, h = 100) {
// --- setup window function code ---
}
```
**In this way, p5.js can be used in Instance Mode to work with `node-canvas`**

Click here to see the codes for saveAsPNG and setupWindow:

**`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

}

```

## Going further - Global Mode!

This is the template for using p5.js in node with Global Mode:

```js
// Adapted from:
// ! Heart Curve
// ! Daniel Shiffman
// https://thecodingtrain.com/CodingChallenges/134-heart-curve.html
// https://youtu.be/oUBAi9xQ2X4
// https://editor.p5js.org/codingtrain/sketches/egvieHyt0

// width and height to be passed both in createCanvas and in setupWindow
setupWindow(400, 400);
// Note that in global mode even though we don't use the p5 variable, it still needs to be imported.
const p5 = require("p5");

const heart = [];
let a = 0;

function setup() {
createCanvas(400, 400);
}

function draw() {
while (true) {
const r = height / 40;
const x = r * 16 * pow(sin(a), 3);
const y = -r * (13 * cos(a) - 5 * cos(2 * a) - 2 * cos(3 * a) - cos(4 * a));
heart.push(createVector(x, y));
// So that it stops
if (a > TWO_PI) {
break;
}

a += 0.1;
}
background(0);
translate(width / 2, height / 2);

stroke(255);
strokeWeight(2);
fill(150, 0, 100);
beginShape();
for (let v of heart) {
vertex(v.x, v.y);
}
endShape();
// in global mode, p5 is attatched to the window (global in node)
// the third arg stands for whether to exit the process
// in this case, if false is passed, then this sketch will run forever, until manually cancelled (because this is the draw loop)
saveAsPNG(global, "globalimg", true);
}
```

In this case as well, the functions `saveAsPNG` and `setupWindow` should be appended at the end of the file, with the last two lines of `setupWindow` uncommented.

This is the output of the global mode code
![globalimg](https://user-images.githubusercontent.com/59444569/107874719-72f09b00-6ee1-11eb-90d4-f887a10eac06.png)

## Use these Templates!
To Use these templates, first install these node-modules
`npm i p5 canvas jsdom`
* [Template for using `node-canvas` with `p5.js` in global mode](https://gist.github.com/c59e02991929db850373b3c7d1a858ef)
* [Template for using `node-canvas` with `p5.js` in instance mode](https://gist.github.com/3e898a0acf73f6b58a563981732b4fdc)

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.