javascript 当将p5.js与React一起使用时,P5.js方法在全局上下文中不可用

8aqjt8rx  于 2023-05-05  发布在  Java
关注(0)|答案(1)|浏览(317)

当尝试将p5适配为react-p5时,我可以使用两个setup & draw方法创建一个简单的草图。
当尝试设置一个更复杂的示例时,在p5.js画布中显示一些实体,我需要p5.js方法在画布中绘制它。
按照react-p5的教程,它是says
如果你需要在Sketch方法之外的react-p5使用的P5示例,那么你可以从window.p5中获得它。
这里的行为令人惊讶:当我尝试访问p5全局示例时,我可以访问一些方法,如window.p5.Vector.random2D(),但有些方法不可用,如window.p5.stroke(_, _);。而window.p5示例与p5示例的类型相同,作为草图的绘制和设置函数中的参数传递。
我的问题是:如何获得全局可用的完整示例?我需要这个来画我的粒子。现在我可以访问P5的全局示例,但它不能满足所有需求。
下面是sketch with stackblitz的工作示例

下面是所涉及的代码:

import React from "react";
import Sketch from "react-p5";
import p5Types, { Vector } from "p5"; 

class Particle {
    acceleration: Vector;
    velocity: Vector;
    position: Vector;
    lifespan : number;

    constructor(position : Vector) {
        // window.p5.Vector.random2D method is accessible
        this.acceleration = window.p5.Vector.random2D();
        this.velocity = window.p5.Vector.random2D();
        this.position = position.copy();
        this.lifespan = 255;
    }

    update() {
        this.velocity.add(this.acceleration);
        this.position.add(this.velocity);
        this.lifespan -= 2;
    }

    display() {
        // the four methods below are not accessible from p5 instance
        window.p5.stroke(200, this.lifespan);
        window.p5.strokeWeight(2);
        window.p5.fill(127, this.lifespan);
        window.p5.ellipse(this.position.x, this.position.y, 12, 12);
    }

    run() {
        this.update();
        this.display();
    }

    isDead() {
        return this.lifespan < 0;
    }
}

let particle : Particle;

function setup(p5: p5Types, canvasParentRef: Element) {
  p5.createCanvas(720, 400).parent(canvasParentRef);
  particle = new Particle(p5.createVector(50,50));
}

function draw(p5 : p5Types) {
  p5.background(51);
  particle.display();
}

export const ParticlesSketch: React.FC<{}> = () => {

  return <Sketch setup={setup} draw={draw} />;
};
yqlxgs2m

yqlxgs2m1#

react-p5库并不打算以这种方式使用。示例化的p5方法,如strokeellipse,应该在传递给drawsetup函数的示例上调用。您引用的关于使用window.p5访问全局变量的指南可能指的是像p5.Vector这样的类型,而不是绘图方法。

import React from 'react';
import Sketch from 'react-p5';
import p5Types, { Vector } from 'p5';

class Particle {
  acceleration: Vector;
  velocity: Vector;
  position: Vector;
  lifespan: number;

  constructor(position: Vector) {
    this.acceleration = Vector.random2D();
    this.velocity = Vector.random2D();
    this.position = position.copy();
    this.lifespan = 255;
  }

  update() {
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);
    this.lifespan -= 2;
  }

  display(p: p5Types) {
    p.stroke(200, this.lifespan);
    p.strokeWeight(2);
    p.fill(127, this.lifespan);
    p.ellipse(this.position.x, this.position.y, 12, 12);
  }

  run(p: p5Types) {
    this.update();
    this.display(p);
  }

  isDead() {
    return this.lifespan < 0;
  }
}

let particle: Particle;

function setup(p: p5Types, canvasParentRef: Element) {
  p.createCanvas(720, 400).parent(canvasParentRef);
  particle = new Particle(p.createVector(50, 50));
}

function draw(p: p5Types) {
  p.background(51);
  particle.display(p);
}

export const ParticlesSketch: React.FC<{}> = () => {
  return <Sketch setup={setup} draw={draw} />;
};

话虽如此,理论上你可以让它与像这样的东西一起工作:

function setup(p: p5Types, canvasParentRef: Element) {
  p.createCanvas(720, 400).parent(canvasParentRef);
  particle = new Particle(p.createVector(50, 50));
  // pure haxin
  // expose all p5.js methods and fields on window (may break things/have unintended consequences)
  const members: any = {};
  for (const key of Object.keys(Object.getPrototypeOf(p))) {
    const member = p[key];
    if (typeof member === 'function') {
      members[key] = member.bind(p);
    } else {
      members[key] = member;
    }
  }
  Object.assign(window, members);
}

加上文件顶部的类型声明:

declare global {
  interface Window extends p5Types {}
}

相关问题