p5 中断 node.js

p5 breaks in node.js

我正在尝试制作 运行 服务器上的节点应用程序。我在 p5 和它的库 vida 中创建了一个运动检测系统。

我第一次尝试全局模式。然后我得到像 createCanvas is not defined 这样的错误。 现在我尝试了实例模式,但我觉得它变得更糟了。我收到错误 window is not defined in the p5.js script 和 require is not defined from the p5.dom.js 脚本.

我应该如何在节点应用程序中正确实现我的 p5 元素?

我读了a.o。 this Whosebug post,但我不知道在节点服务器内的浏览器中 运行 p5 是什么意思。

这是我的server.js

const express = require('express');
const multer = require('multer');
const sketch = require('./public/app.js');

const PORT=3000;
const upload = multer({dest: __dirname + '/uploads/images'});
const app = express();

//things possible to be accessed by the client
app.use(express.static('./public'));
app.use(express.static('./public/scripts'));

console.log(sketch.setup, sketch.draw);

//test
app.get('/', function (req, res) {
    res.send('hello world');
  });

app.post('/upload', upload.single('photo'), (req, res) => {
    if(req.file) {
        res.json(req.file);
    }
    else throw 'error';
});

app.listen(PORT, () => {
    console.log('Listening at ' + PORT );
});

下面是我的 app.js

的主要部分
'use strict';
/******** {SKETCH INSTANCE} *********/
var p5 = require('p5');
var myp5 = new p5(sketch);
var sketch = (s) => {
/**** { VIDA video } ****/
var myCapture;
var myVida;

function initCaptureDevice() {
  //code
};

/**** { P5 } ****/
  s.setup = function() {
    s.createCanvas(640, 480);
    initCaptureDevice();
    startup();

    myVida = new s.Vida(this); // create the object
    //vida code

    s.frameRate(10);
  };

  s.draw = function() {
    if(myCapture !== null && myCapture !== undefined) { // safety first
      s.background(0, 0, 255);

      myVida.update(myCapture);
      s.image(myVida.thresholdImage, 320, 240);

      // let's describe the displayed images
      
      /*DRAWING*/
      // define size of the drawing

      /*ACTIVE ZONES*/
      for(var i = 0; i < myVida.activeZones.length; i++) {
        //code

        /*DETECT MOTION*/
        if(myVida.activeZones[i].isChangedFlag) {
          if(myVida.activeZones[i].isMovementDetectedFlag) {
            //the state changed from noMovement to movement
            //take snapshot and upload it to a public folder
            snapshot();
          };
        };
      }
      s.pop(); // restore memorized drawing style and font
    }
    else {
      s.background(255, 0, 0);
    }
  }
}
exports.sketch = sketch;

感谢您的宝贵时间, 芥末整形器

P5.js 不能在浏览器之外使用。但是,如果必须,它在技术上可以工作。我在下面发布了一个示例(您也可以通过我的 Repl.it project 查看和 运行)。但请注意,不能保证这适用于您的用例。对于这个例子来说,只是让 canvas 的图像数据写入文件是一个巨大的痛苦,所以你的里程可能会有所不同。

index.js

const Window = require('window');
const fs = require('fs');
const { Blob } = require('./blob.js');

// globals expected to exist by p5js (must come before the import)
global.window = new Window();
// Override JSDOM's horrible Blob implementations
global.window.Blob = Blob;
global.document = global.window.document;
global.screen = global.window.screen;
global.navigator = global.window.navigator;

const p5 = require('p5');

const inst = new p5(p => {
  p.setup = function() {
    console.log('rendering');
    let canvas = p.createCanvas(200, 200);
    p.background('gray');
    p.fill('crimson');
    p.circle(p.width / 2, p.height / 2, 100);
    canvas.elt.toBlob(
      data => {
        let writeStream = fs.createWriteStream('./out.png')
        writeStream.on('finish', () => {
          // All writes are now complete.
          done();
        });
        writeStream.on('error', (err) => {
          console.error(err);
        });

        console.log('file size: ' + data.size);
        writeStream.write(data.arrayBuffer());
        writeStream.end();
      },
      'image/png'
    );
  };
});

function done() {
  console.log('done!');
  inst.remove();
  process.exit(0);
}

blob.js:

"use strict";

const { Readable } = require('stream');

exports.Blob = class Blob {
  constructor(parts, options) {
    this._buffer = Buffer.concat(parts);

    this.type = options.type;
  }

  get size() {
    return this._buffer.length;
  }

  arrayBuffer() {
    return this._buffer;
  }

  stream() {
    return Readable.from(this._buffer);
  }

  slice(start, end, contentType) {
    const { size } = this;

    let relativeStart, relativeEnd, relativeContentType;

    if (start === undefined) {
      relativeStart = 0;
    } else if (start < 0) {
      relativeStart = Math.max(size + start, 0);
    } else {
      relativeStart = Math.min(start, size);
    }
    if (end === undefined) {
      relativeEnd = size;
    } else if (end < 0) {
      relativeEnd = Math.max(size + end, 0);
    } else {
      relativeEnd = Math.min(end, size);
    }

    if (contentType === undefined) {
      relativeContentType = "";
    } else {
      // sanitization (lower case and invalid char check) is done in the
      // constructor
      relativeContentType = contentType;
    }

    const span = Math.max(relativeEnd - relativeStart, 0);

    const slicedBuffer = this._buffer.slice(
      relativeStart,
      relativeStart + span
    );

    return new Blob([slicedBuffer], { type: relativeContentType });
  }
};

package.json:

{
  "name": "p5js-test",
  "version": "1.0.0",
  "description": "Test p5.js Node.js app.",
  "main": "./index.js",
  "bin": {
    "p5js-test": "./index.js"
  },
  "scripts": {
    "start": "node index.js"
  },
  "author": "Paul Wheeler",
  "license": "MIT",
  "dependencies": {
    "canvas": "^2.7.0",
    "p5": "^1.3.1",
    "window": "^4.2.7",
    "jsdom": "^16.5.3"
  },
  "devDependencies": {}
}