[英]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.