Reputation:
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
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
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
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