p5.js && ecmascript6 notation

别来无恙 提交于 2021-02-08 11:18:41

问题


I want use p5.js function inside a class with ECMAScript notation.

How to fix this code?

class Sketch {
    constructor(p, params) {
        // generate vars use in class with object
        if (typeof params !== 'undefined') {
            for (let key in params) this[key] = params[key];
        }
        // p5.js object
        this.p = p;
    }
    // p5.js setup method
    setup() {
        this.p.createCanvas();
    }
    // p5.js draw method
    draw() {
    }
}
sketch = new Sketch(p5,{});

Error:

this.p.createCanvas is not a function


回答1:


The docs say that you must instantiate p5 and pass your initialiser function that creates the method on p:

const myp5 = new p5(p => {
    p.setup = () => {
        p.createCanvas();
    };
    …
});

See also the Global and instance mode tutorial.

This is a really weird construction however. Although it's not documented, in ES6 it should be possible to subclass p5:

class Sketch extends p5 {
    constructor(params) {
        super(p => {
            // do any setup in here that needs to happen before the sketch starts
            // (e.g. create event handlers)
            // `p` refers to the instance that becomes `this` after the super() call
            // so for example
            if (typeof params == 'object' && params != null)
                for (let key in params)
                    p[key] = params[key];
        });

        // `this` itself is the p5.js object
    }
    // p5.js setup method
    setup() {
        this.createCanvas();
    }
    // p5.js draw method
    draw() {
    }
}
const myp5 = new Sketch({});

Notice that the p5 constructor will invoke your methods; you don't have to do myp5.setup() yourself.




回答2:


Tinkering with this issue. I was able to implement inheritance of p5 kinda like so:

import p5 from 'p5';

const MIN_RAD = 150;
const MAX_RAD = 250;
const ITEM_COLOR = 'red';
const BG = 'rgba(50,50,50,.05)';
const VELOCITY = 1;

export default class Sketch extends p5 {

    constructor(sketch = ()=>{}, node = false, sync = false) {
        super(sketch, node, sync);
        console.log('Sketch [this:%o]', this);

        this.setup = this.setup.bind(this);
        this.draw = this.draw.bind(this);
        this.render = this.render.bind(this);
        this.increment = this.increment.bind(this);
        this.windowResized = this.windowResized.bind(this);
    }

    setup() {
        console.log('setup', this.windowWidth, this.windowHeight);
        this.createCanvas(this.windowWidth, this.windowHeight, p5.WEBGL);

        this.bg = this.color(BG);
        this.itemColor = this.color(ITEM_COLOR);
        this.rad = MIN_RAD;
        this.grow = true;
        this.frame = 0;
    }

    draw() {
        this.increment();
        this.render();
    }

    render() {
        let x = this.windowWidth / 2;
        let y = this.windowHeight / 2;

        this.background(this.bg);
        this.fill(this.itemColor);
        this.stroke(this.itemColor);
        this.ellipse(x, y, this.rad, this.rad);
    }

    increment() {
        this.rad = this.grow ? this.rad + VELOCITY : this.rad - VELOCITY;

        if (this.rad > MAX_RAD) {
            this.grow = false;
        };

        if (this.rad < MIN_RAD) {
            this.grow = true;
        }

        this.frame++;
    }

    // EVENTS

    windowResized() {
        console.log('windowResized', this.windowWidth, this.windowHeight);
        this.resizeCanvas(this.windowWidth, this.windowHeight);
    }
}

This class can be imported normally, and instantiated by invoking the constructor.

import Sketch from './sketch';
...
const sketch = new Sketch();

Digging through the source code a little, there are two critical states that auto-magically activate the so-called 'global' mode, where p5 dumps its guts onto window (to be avoided).

  • 1) at init.js#L21, if draw and setup both exist on the window
  • 2) on core.js#L496, if the sketch argument is falsey

p5/Core uses these conditions to set its internal _isGlobal prop which is used to define context as either window or this, and conditionally acts on this throughout. EG:core.js#L271

Just expanding on the selected answer (which is correct, except I get errors passing in an empty object).

Frankly, both of the documented construction methods are unsatisfactory. This is an improvement, but we still have to do extra work to manage scope.



来源:https://stackoverflow.com/questions/43079407/p5-js-ecmascript6-notation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!