useEffect 没有持续触发
useEffect is not firing consistently
该组件正在 3D 场景中创建一个 positionalAudio,并且可以使用 leva 调整音频对象。该对象正在按应有的方式创建,并且调整位置和旋转效果很好。无法正常工作的是改变音量。在 leva UI 中,我可以拖动音量的手柄进行更改,但没有发生任何效果(我假设这是因为 useEffect 在释放手柄之前触发并且实际上值没有变化尚未发生。在我释放句柄之前,至少会显示一个控制台日志)。当我将新值放入输入字段时,按回车键 useEffect 正在触发并且音量正在改变。不过只有这一次有效,以后就不行了。
import * as THREE from 'three'
import React, { Suspense, useRef, useEffect, useState } from 'react'
import { useThree, useLoader } from '@react-three/fiber'
import { PositionalAudioHelper } from 'three/examples/jsm/helpers/PositionalAudioHelper.js'
import { useControls } from 'leva'
function Sound({ url, volume }) {
const sound = useRef()
const { camera } = useThree()
const [listener] = useState(() => new THREE.AudioListener())
const buffer = useLoader(THREE.AudioLoader, url)
useEffect(() => {
sound.current.setBuffer(buffer)
sound.current.setRefDistance(1)
sound.current.setRolloffFactor(0)
sound.current.setDirectionalCone(180, 230, 0.1)
sound.current.setLoop(true)
sound.current.play()
const helper = new PositionalAudioHelper(sound.current)
sound.current.add(helper)
camera.add(listener)
return () => camera.remove(listener)
}, [])
useEffect(() => {
sound.current.setVolume(volume)
}, [sound.current])
return (
<positionalAudio ref={sound} args={[listener]} />
)
}
export default function App({ url, position}) {
const { posXRight, posYRight, posZRight, rotationYRight, volumeRight } = useControls({
posXRight: {
value: position[0],
min: -20,
max: 20,
step: 1
},
posYRight: {
value: position[1],
min: -20,
max: 20,
step: 1
},
posZRight: {
value: position[2],
min: -20,
max: 20,
step: 1
},
rotationYRight: {
value: 0,
min: 0,
max: Math.PI * 2,
step: Math.PI * 0.25
},
volumeRight: {
value: 1,
min: 0,
max: 1,
step: 0.05
}
})
return (
<Suspense fallback={null}>
<mesh position={[posXRight, posYRight, posZRight]} rotation={[0, rotationYRight, 0]}>
<sphereGeometry args={[0.1, 32, 32]} />
<meshStandardMaterial color="white" />
<Sound url={url} volume={volumeRight} />
</mesh>
</Suspense>
)
}
useEffect(() => {
sound.current.setVolume(volume)
}, [sound.current])
这个钩子在初始渲染和每次 sound.current
改变时触发(可能永远不会)。您应该将其更改为 [volume]
该组件正在 3D 场景中创建一个 positionalAudio,并且可以使用 leva 调整音频对象。该对象正在按应有的方式创建,并且调整位置和旋转效果很好。无法正常工作的是改变音量。在 leva UI 中,我可以拖动音量的手柄进行更改,但没有发生任何效果(我假设这是因为 useEffect 在释放手柄之前触发并且实际上值没有变化尚未发生。在我释放句柄之前,至少会显示一个控制台日志)。当我将新值放入输入字段时,按回车键 useEffect 正在触发并且音量正在改变。不过只有这一次有效,以后就不行了。
import * as THREE from 'three'
import React, { Suspense, useRef, useEffect, useState } from 'react'
import { useThree, useLoader } from '@react-three/fiber'
import { PositionalAudioHelper } from 'three/examples/jsm/helpers/PositionalAudioHelper.js'
import { useControls } from 'leva'
function Sound({ url, volume }) {
const sound = useRef()
const { camera } = useThree()
const [listener] = useState(() => new THREE.AudioListener())
const buffer = useLoader(THREE.AudioLoader, url)
useEffect(() => {
sound.current.setBuffer(buffer)
sound.current.setRefDistance(1)
sound.current.setRolloffFactor(0)
sound.current.setDirectionalCone(180, 230, 0.1)
sound.current.setLoop(true)
sound.current.play()
const helper = new PositionalAudioHelper(sound.current)
sound.current.add(helper)
camera.add(listener)
return () => camera.remove(listener)
}, [])
useEffect(() => {
sound.current.setVolume(volume)
}, [sound.current])
return (
<positionalAudio ref={sound} args={[listener]} />
)
}
export default function App({ url, position}) {
const { posXRight, posYRight, posZRight, rotationYRight, volumeRight } = useControls({
posXRight: {
value: position[0],
min: -20,
max: 20,
step: 1
},
posYRight: {
value: position[1],
min: -20,
max: 20,
step: 1
},
posZRight: {
value: position[2],
min: -20,
max: 20,
step: 1
},
rotationYRight: {
value: 0,
min: 0,
max: Math.PI * 2,
step: Math.PI * 0.25
},
volumeRight: {
value: 1,
min: 0,
max: 1,
step: 0.05
}
})
return (
<Suspense fallback={null}>
<mesh position={[posXRight, posYRight, posZRight]} rotation={[0, rotationYRight, 0]}>
<sphereGeometry args={[0.1, 32, 32]} />
<meshStandardMaterial color="white" />
<Sound url={url} volume={volumeRight} />
</mesh>
</Suspense>
)
}
useEffect(() => {
sound.current.setVolume(volume)
}, [sound.current])
这个钩子在初始渲染和每次 sound.current
改变时触发(可能永远不会)。您应该将其更改为 [volume]