更改音频源后 属性,之前设置的流继续播放
After changing audio source property, previously set stream continues to play
使用 Chromium 版本的 Edge:93.0.961.38
我正在用 React 构建一个音乐播放器应用程序。当用户按下要播放的 select 按钮时,它将通过呈现具有自动播放属性集和子 [=13] 的 <audio>
控件来自动播放 MP3 URL =] 元素与指定的 URL.
从无播放过渡到第一个 selected 节目时一切正常。但我希望它的工作方式是,如果用户主动更改他收听的节目,它将自动播放新的 selected 节目。
我可以从控制台日志中看到,当按下另一个显示按钮时,<MediaPlayer>
元素肯定会使用新 selected URL 重新呈现。我什至让它在组件本身中渲染 URL 。我可以在 F12 工具(DOM 检查器)中看到 <source>
元素上的 src
属性 肯定已更新。但是之前的节目一直在播放。
几乎足够好的解决方法是引入一个停止按钮,该按钮在没有任何 <audio>
控制的情况下重新呈现。然后按下另一个节目的按钮肯定会播放。
在下面的示例代码中,单击“环境”开始第一个节目。然后在开始播放后,单击“重金属”按钮。 “环境”音乐一直在播放。单击“停止”,然后再次按“重金属”——您将听到另一个节目。
有解决办法吗?或者我应该放弃使用内置音频 DOM 控件并使用 new Audio
with state?
import './App.css';
import {useState, createContext, useContext, useEffect, useMemo} from 'react';
const AMBIENT = "https://www.selbie.com/samples/atmospherics.mp3";
const METAL = "https://www.selbie.com/samples/wrekage.mp3";
const MediaPlayer = (props) => {
if (props.src) {
console.log("Url selected for playback: ", props.src);
}
else {
console.log("Nothing ready to play");
}
return (props.src ? (<div><audio controls autoPlay><source src={props.src} /></audio><br/>{props.src}</div>)
: (<div>Nothing yet to play</div>)
);
};
function App() {
const [show, setShow] = useState(null);
return (
<div>
<MediaPlayer src={show}/>
<p></p>
<button onClick={()=>setShow(AMBIENT)}>{"\u25B6\uFE0F Ambient"}</button><br/>
<button onClick={()=>setShow(METAL)}>{"\u25B6\uFE0F Heavy Metal"}</button><br/>
<button onClick={()=>setShow(null)}>{"\u23F9\uFE0F Stop"}</button><br/>
</div>
);
}
export default App;
根据 DBS 的评论,.load()
需要在更改源后对音频元素调用。这很容易通过 useEffect
完成,并在 useRef
的帮助下访问 <audio>
元素。
将 MediaPlayer 组件更新为:
const MediaPlayer = (props) => {
const audioRef = useRef(); // ADDED THIS
if (props.src) {
console.log("Url selected for playback: ", props.src);
}
else {
console.log("Nothing ready to play");
}
// ADDED useEffect
useEffect(()=> {
console.log("useEffect invoked");
if (props.src) {
let audio = audioRef.current;
if (audio) {
audio.load();
}
}
}, [props.src]);
// ADDED ref={audioRef} as attribute
return (props.src ? (<div><audio ref={audioRef} controls autoPlay><source src={props.src} /></audio><br/>{props.src}</div>)
: (<div>Nothing yet to play</div>)
);
};
使用 Chromium 版本的 Edge:93.0.961.38
我正在用 React 构建一个音乐播放器应用程序。当用户按下要播放的 select 按钮时,它将通过呈现具有自动播放属性集和子 [=13] 的 <audio>
控件来自动播放 MP3 URL =] 元素与指定的 URL.
从无播放过渡到第一个 selected 节目时一切正常。但我希望它的工作方式是,如果用户主动更改他收听的节目,它将自动播放新的 selected 节目。
我可以从控制台日志中看到,当按下另一个显示按钮时,<MediaPlayer>
元素肯定会使用新 selected URL 重新呈现。我什至让它在组件本身中渲染 URL 。我可以在 F12 工具(DOM 检查器)中看到 <source>
元素上的 src
属性 肯定已更新。但是之前的节目一直在播放。
几乎足够好的解决方法是引入一个停止按钮,该按钮在没有任何 <audio>
控制的情况下重新呈现。然后按下另一个节目的按钮肯定会播放。
在下面的示例代码中,单击“环境”开始第一个节目。然后在开始播放后,单击“重金属”按钮。 “环境”音乐一直在播放。单击“停止”,然后再次按“重金属”——您将听到另一个节目。
有解决办法吗?或者我应该放弃使用内置音频 DOM 控件并使用 new Audio
with state?
import './App.css';
import {useState, createContext, useContext, useEffect, useMemo} from 'react';
const AMBIENT = "https://www.selbie.com/samples/atmospherics.mp3";
const METAL = "https://www.selbie.com/samples/wrekage.mp3";
const MediaPlayer = (props) => {
if (props.src) {
console.log("Url selected for playback: ", props.src);
}
else {
console.log("Nothing ready to play");
}
return (props.src ? (<div><audio controls autoPlay><source src={props.src} /></audio><br/>{props.src}</div>)
: (<div>Nothing yet to play</div>)
);
};
function App() {
const [show, setShow] = useState(null);
return (
<div>
<MediaPlayer src={show}/>
<p></p>
<button onClick={()=>setShow(AMBIENT)}>{"\u25B6\uFE0F Ambient"}</button><br/>
<button onClick={()=>setShow(METAL)}>{"\u25B6\uFE0F Heavy Metal"}</button><br/>
<button onClick={()=>setShow(null)}>{"\u23F9\uFE0F Stop"}</button><br/>
</div>
);
}
export default App;
根据 DBS 的评论,.load()
需要在更改源后对音频元素调用。这很容易通过 useEffect
完成,并在 useRef
的帮助下访问 <audio>
元素。
将 MediaPlayer 组件更新为:
const MediaPlayer = (props) => {
const audioRef = useRef(); // ADDED THIS
if (props.src) {
console.log("Url selected for playback: ", props.src);
}
else {
console.log("Nothing ready to play");
}
// ADDED useEffect
useEffect(()=> {
console.log("useEffect invoked");
if (props.src) {
let audio = audioRef.current;
if (audio) {
audio.load();
}
}
}, [props.src]);
// ADDED ref={audioRef} as attribute
return (props.src ? (<div><audio ref={audioRef} controls autoPlay><source src={props.src} /></audio><br/>{props.src}</div>)
: (<div>Nothing yet to play</div>)
);
};