[英]Why does changing state (useState) break my p5.js code? (React + p5.js application)
我使用 p5.js 和 React 创建了一个音频可视化器,我需要一些帮助。
我试图在歌曲开始播放时将按钮输入文本的状态从Play
更改为Stop
”,并在用户决定在那一刻停止歌曲时将“ Stop
”更改为Play
”。
我正在使用react-p5
库,并且在用户单击播放按钮时我setState
之前一切正常。 由于这会导致重新渲染,它会破坏我的画布。
有没有办法只重新渲染按钮元素? 我不太确定如何在不更改状态的情况下更改按钮的内部文本?
import React, { useState } from 'react';
import Sketch from 'react-p5';
import 'p5/lib/addons/p5.sound';
import Beat from '../../instrumental.mp3';
const App = () => {
let width = 900;
let height = 600;
let song;
let fft;
const [flag, setFlag] = useState(true);
const preload = (p) => {
p.soundFormats('mp3');
song = p.loadSound(Beat);
}
const setup = (p, canvasParentRef) => {
// react-p5 conveniently initializes window.p5 thats why all the other p5's
// have been changed to p in order to create an FFT object
fft = new p5.FFT();
// console.log(p.point)
// use parent to render the canvas in this ref
// without it p5 will render the canvas outside of this component
const canvas = p.createCanvas(width, height).parent(canvasParentRef);
}
const playStop = () => {
if (song.isPlaying()) {
song.pause();
setFlag(true);
//p.noLoop();
} else {
song.play();
setFlag(false);
//p.loop();
}
}
const draw = p => {
p.background(0);
// by default the stroke color is black
// we need to change this in order to see the wave
p.stroke(255, 204, 0);
// no fill in between waves
p.noFill();
// returns an array with 1024 elements
let wave = fft.waveform();
p.beginShape();
// By looping through the waveform data, we are able
// to draw the waveform across the canvas
for (let i = 0; i < width; i++) {
// create an index that maps the for loop variable
// to the index of the wave we want
// value must be integer thats we we use floor
let index = p.floor(p.map(i, 0, width, 0, wave.length));
let x = i;
let y = wave[index] * 100 + height / 2;
p.vertex(x, y);
}
p.endShape();
}
return (
<div className='outerbox'>
<h1>Audio Visualizer</h1>
<Sketch preload={preload} setup={setup} draw={draw}/>
{flag ? <button onClick={playStop}>Play</button> : <button onClick={playStop}>Stop</button>}
</div>
);
}
export default App;
可悲的是没有很多可用的资源,包括 react + p5.js
如果有人想花时间克隆这个存储库以查看问题可能是什么,我将非常感激。
回购链接: https ://github.com/imperium11/audio-visualizer
npm i
npm run dev-build
npm start
这里的问题是,每次更新功能组件中的状态时,都会再次调用该函数。 结果,每次状态更改时,您都重新声明
preload<\/code> \/
setup<\/code> \/
draw<\/code> ,由于
react-p5<\/code>的工作方式,正在运行的草图将开始使用您更新的
draw<\/code>功能。
但是,更新后的绘图函数需要定义
fft<\/code> ,但新
draw<\/code>函数引用的
fft<\/code>变量的版本未定义。
为了解决这个问题,您可以将草图使用的任何局部变量变成状态变量。 在本例中,我将所有本地人打包到一个对象中:
这可能有点小技巧,但它的优点是可以快速更新局部变量(如果您在draw()<\/code>函数中更改局部变量,我的理解是您不希望将它们变成状态变量,因为高频状态更新可能会影响性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.