user11114318
user11114318

Reputation:

How to use React with p5.js

I really like p5.js and react.js so i wondered how to combine these two together, and i was unable to do it so I need your help. I cant really provide you with some code samples because I have no clue how to start.

So what I want to do : 1. create-react-app 2.render a canvas using p5.js (i dont need the p5.dom and p5.sound)

Upvotes: 11

Views: 24583

Answers (3)

Chris Schuller
Chris Schuller

Reputation: 71

This can also be done without any third party library and function components.

Installation :

After running create-react-app, Install the p5 package using npm install p5.

Code :

In the App.js file

import './App.css';
import { useEffect, useRef } from 'react';
import p5 from 'p5';

function sketch(p) {
    // p is a reference to the p5 instance this sketch is attached to
    p.setup = function() {
        p.createCanvas(400, 400);
        p.background(0);
        p.circle(200, 200, 400);
    }

    p.draw = function() {
        // your draw code here
    }
}

function App() {
    // create a reference to the container in which the p5 instance should place the canvas
    const p5ContainerRef = useRef();

    useEffect(() => {
        // On component creation, instantiate a p5 object with the sketch and container reference 
        const p5Instance = new p5(sketch, p5ContainerRef.current);

        // On component destruction, delete the p5 instance
        return () => {
            p5Instance.remove();
        }
    }, []);

    return (
        <div className="App" ref={p5ContainerRef} />
    );
}

export default App;

Further Explanation:

When the App component gets created, it sets the reference p5ContainerRef.current to itself. The useEffect hook is run and creates a new p5 instance p5Instance with the sketch function and the containing node p5ContainerRef.current as parameters. By returning a function that runs p5Instance.remove(), the p5Instance is destroyed when the App component gets destroyed or re-rendered. This prevents having multiple p5 instances with their own canvases.

This code is showing what libraries like react-p5 are doing in its core. They make sure a p5 instance is attached to a wrapper container and that p5 instances are destroyed when its wrapper component gets destroyed or re-rendered.

Side note :

You can rename the App component to something like P5Component and import it into any existing React App.

Upvotes: 6

user11722559
user11722559

Reputation:

react-p5

This Component lets you integrate p5 Sketches into your React App. DEMO, Documentation

For Advanced Usage pls read this Blog Post

Installation

npm i react-p5

Usage

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

export default class App extends Component {
  x = 50
  y = 50

  setup = (p5, parent) => {
    p5.createCanvas(500, 500).parent(parent)
  }
  draw = p5 => {
    p5.background(0)
    p5.ellipse(this.x, this.y, 70, 70)
    this.x++
  }

  render() {
    return <Sketch setup={this.setup} draw={this.draw} />
  }
}

Upvotes: 8

Julian
Julian

Reputation: 1297

First thing that needs to be done is install the create-react-app tool. Once it's up and running the p5.js and the react-p5-wrapper packages can be included; assuming a package manager like npm is being used, this can be done by executing npm install p5 react-p5-wrapper with whatever flags are considered necessary.

The react-p5-wrapper is a wrapper component that receives a reference (instance mode) to the sketch and uses some of the react component "lifecycle methods" to manipulate it accordingly, mainly by executing a method called myCustomRedrawAccordingToNewPropsHandler(props) that needs to be defined within said sketch.

To give it a try and see it running, the contents of the App.js file could be modified like this:

import React, { Component } from 'react';
import P5Wrapper from 'react-p5-wrapper';
import sketch from './sketches/sketch';
import './App.css';

class App extends Component {
  constructor(){
    super();
    this.state = {color:[Math.random()*255, Math.random()*255, Math.random()*255]};
    this.randomColor = this.randomColor.bind(this);
  }

  randomColor(){
    this.setState({color:[Math.random()*255, Math.random()*255, Math.random()*255]}
    )
  }

  render() {
    return (
      <div>
        <button onClick={this.randomColor}>Random Color</button>
        <P5Wrapper sketch={sketch} color={this.state.color}></P5Wrapper>
      </div>
    );
  }
}

export default App;

Where sketch is imported from sketch.js which is located in another folder, in this case called sketches:

export default function sketch(p){
    let canvas;

    p.setup = () => {
      canvas = p.createCanvas(300, 200);
      p.noStroke();
    }

    p.draw = () => {
      p.background('orangered');
      p.ellipse(150, 100, 100, 100);
    }

    p.myCustomRedrawAccordingToNewPropsHandler = (newProps) => {
      if(canvas) //Make sure the canvas has been created
        p.fill(newProps.color);
    }
}

If everything is working, a button and a sketch should be on screen and every time the button is pressed the circle in the sketch changes colors randomly.

It should be noted that the myCustomRedrawAccordingToNewPropsHandler function is called in the componentDidMount and the componentWillReceiveProps "lifecycle methods" of the wrapper, the latter being currently classified as unsafe.

Upvotes: 11

Related Questions