0

To get P5 to work with React, I am using the P5Wrapper import.

I got a simple starfield animation to work on my tile, but the performance is an issue. The animation slows to a crawl at 512 "star" objects, so I scaled it back to 128. However, even at 128, the FPS seems much too low, averaging below 30 FPS. I am looking for ways to speed up P5's performance in React so that the animations can run closer to 60 FPS.

P5 code:

function sketch (p) {

  const star = () => {
    const x = p.random(-TILE_SIZE/2, TILE_SIZE/2)
    const y = p.random(-TILE_SIZE/2, TILE_SIZE/2)
    const z = p.random(TILE_SIZE)
    return { x, y, z }
  }

  const stars = new Array(128)

  p.setup = () => {
    p.createCanvas(TILE_SIZE, TILE_SIZE)

    for (let i = 0; i < stars.length; i++) {
      stars[i] = star()
    }
  }

  const update = (coord) => {
    const { z } = coord
    let newZ = z - 8
    if (newZ < 1) {
      newZ = p.random(TILE_SIZE)
    }
    return { ...coord, z: newZ }
  }

  const show = (coord) => {
    const { x, y, z } = coord
    p.fill(255)
    p.noStroke()

    const sx = p.map(x / z, 0, 1, 0, TILE_SIZE)
    const sy = p.map(y / z, 0, 1, 0, TILE_SIZE)

    const r = p.map(z, 0, TILE_SIZE, 4, 0)
    p.ellipse(sx, sy, r, r)
  }

  p.draw = () => {
    p.background(0)
    p.translate(TILE_SIZE/2, TILE_SIZE/2)
    for (let i = 0; i < stars.length; i++) {
      stars[i] = update(stars[i])
      show(stars[i])
    }
  }
}

How P5Wrapper is used:

import P5Wrapper from 'react-p5-wrapper'

...
render (
 <ItemContainer key={uuidv4()}>
   <header>
     {name}
     <p>{description}</p>
   </header>
   <P5Wrapper sketch={sketch} />
 </ItemContainer>
)

Sample of performance

How the starfield tile actually looks (2 tiles).

enter image description here

I am planning to add more animations depending on performance. Or switching to SVG.

Dan
  • 2,455
  • 3
  • 19
  • 53

1 Answers1

3

Resolved the frame-rate issue without changing the actual animation logic. There could still be plenty of performance optimization that is still needed.

I noticed that the animation gets progressively slower as I un-mount and re-mount the component. Digging into the Github issue results in this post about performance degradation. The poster provided a PR and commit that was never merged and the repository haven't been updated for over a year.

Instead, it's better to remove the package and just create your own component following the poster's update:

import React from 'react'
import p5 from 'p5'

export default class P5Wrapper extends React.Component {
  componentDidMount() {
    this.canvas = new p5(this.props.sketch, this.wrapper)
    if( this.canvas.myCustomRedrawAccordingToNewPropsHandler ) {
      this.canvas.myCustomRedrawAccordingToNewPropsHandler(this.props)
    }
  }

  componentWillReceiveProps(newprops) {
    if(this.props.sketch !== newprops.sketch){
      this.canvas.remove()
      this.canvas = new p5(newprops.sketch, this.wrapper)
    }
    if( this.canvas.myCustomRedrawAccordingToNewPropsHandler ) {
      this.canvas.myCustomRedrawAccordingToNewPropsHandler(newprops)
    }
  }

  componentWillUnmount() {
    this.canvas.remove()
  }

  render() {
    return <div ref={wrapper => this.wrapper = wrapper}></div>
  }
}

This at the very least resolved the performance degradation issue for mounting and unmounting the component. Additionally, my frames have jumped from sub 30 to nearly 60 FPS. This could be because I also imported the latest P5 package since I no longer rely on react-p5-wrapper to do the imports.

enter image description here

Dan
  • 2,455
  • 3
  • 19
  • 53
  • Did you do any more work on this? I switched to your version of P5Wrapper, but it still runs much slower than standalone (without react). I like react so far, but this is a blocker for me. Please halp! – SpaceBear Mar 20 '19 at 23:59
  • No sorry. This is where I stopped. – Dan Mar 21 '19 at 00:30
  • No worries. Bummer, because react is pretty nice and I love p5. What did you end up doing for your project if you don't mind me asking? Switch to SVG? – SpaceBear Mar 21 '19 at 01:00
  • I just wanted to test different tech and libraries. I haven't dug too deeply into each, but the hope is to try out each new tech at a basic level. The next one should be a-frame or some such. – Dan Mar 21 '19 at 17:10