P5 with react at 60 FPS

孤者浪人 提交于 2019-12-08 11:09:21

问题


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>
)

How the starfield tile actually looks (2 tiles).

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


回答1:


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.



来源:https://stackoverflow.com/questions/50826209/p5-with-react-at-60-fps

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