React.js에서의 사운드 재생
import React, { Component } from 'react'
import { Button, Input, Icon,Dropdown,Card} from 'semantic-ui-react'
import { Link } from 'react-router-dom'
import $ from 'jquery'
import styles from './Home.scss'
import Modal from './Modal.jsx'
import MakeChannelModal from './MakeChannelModal.jsx'
class Music extends React.Component {
constructor(props) {
super(props);
this.state = {
play: false,
pause: true
};
this.url = "http://streaming.tdiradio.com:8000/house.mp3";
this.audio = new Audio(this.url);
}
play(){
this.setState({
play: true,
pause: false
});
console.log(this.audio);
this.audio.play();
}
pause(){
this.setState({ play: false, pause: true });
this.audio.pause();
}
render() {
return (
<div>
<button onClick={this.play}>Play</button>
<button onClick={this.pause}>Pause</button>
</div>
);
}
}
export default Music
리액트 앱에서 url(this.url)로 사운드를 재생하기 위해 사용하는 코드입니다.재생 버튼을 누르면 오류가 발생합니다.
Uncaughed TypeError: 정의되지 않은 속성 'setState'를 읽을 수 없습니다.
미정의 상태가 보이지 않기 때문에 왜 이런 일이 일어나는지 모르겠습니다.A;; 주가 선언되었습니다.
제가 반응을 처음이라 뭔가 중요한 걸 놓치고 있는 것 같아요.
도와주세요!
ES6 클래스 속성 구문
class Music extends React.Component {
state = {
play: false
}
audio = new Audio(this.props.url)
componentDidMount() {
audio.addEventListener('ended', () => this.setState({ play: false }));
}
componentWillUnmount() {
audio.removeEventListener('ended', () => this.setState({ play: false }));
}
togglePlay = () => {
this.setState({ play: !this.state.play }, () => {
this.state.play ? this.audio.play() : this.audio.pause();
});
}
render() {
return (
<div>
<button onClick={this.togglePlay}>{this.state.play ? 'Pause' : 'Play'}</button>
</div>
);
}
}
export default Music;
후크 버전(React 16.8+):
import React, { useState, useEffect } from "react";
const useAudio = url => {
const [audio] = useState(new Audio(url));
const [playing, setPlaying] = useState(false);
const toggle = () => setPlaying(!playing);
useEffect(() => {
playing ? audio.play() : audio.pause();
},
[playing]
);
useEffect(() => {
audio.addEventListener('ended', () => setPlaying(false));
return () => {
audio.removeEventListener('ended', () => setPlaying(false));
};
}, []);
return [playing, toggle];
};
const Player = ({ url }) => {
const [playing, toggle] = useAudio(url);
return (
<div>
<button onClick={toggle}>{playing ? "Pause" : "Play"}</button>
</div>
);
};
export default Player;
업데이트 20년 3월 16일: 여러 플레이어 동시 실행
@Cold_Class의 코멘트에 대한 응답:
유감스럽게도 이러한 컴포넌트를 여러 개 사용해도 다른 컴포넌트의 음악이 재생을 시작할 때마다 재생이 중지되지 않습니다.이 문제에 대한 간단한 해결책을 제안해 주시겠습니까?
코드베이스의 .Player
는 a a a a to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to to로 올려야 하기 때문입니다.MultiPlayer
대로 설정합니다.toggle
사용자가 직접 대화한 플레이어가 아닌 다른 플레이어를 일시 중지할 수 있는 기능입니다.
한 가지 해결책은 후크 자체를 변경하여 여러 오디오소스를 동시에 관리하는 것입니다.다음으로 구현 예를 제시하겠습니다.
import React, { useState, useEffect } from 'react'
const useMultiAudio = urls => {
const [sources] = useState(
urls.map(url => {
return {
url,
audio: new Audio(url),
}
}),
)
const [players, setPlayers] = useState(
urls.map(url => {
return {
url,
playing: false,
}
}),
)
const toggle = targetIndex => () => {
const newPlayers = [...players]
const currentIndex = players.findIndex(p => p.playing === true)
if (currentIndex !== -1 && currentIndex !== targetIndex) {
newPlayers[currentIndex].playing = false
newPlayers[targetIndex].playing = true
} else if (currentIndex !== -1) {
newPlayers[targetIndex].playing = false
} else {
newPlayers[targetIndex].playing = true
}
setPlayers(newPlayers)
}
useEffect(() => {
sources.forEach((source, i) => {
players[i].playing ? source.audio.play() : source.audio.pause()
})
}, [sources, players])
useEffect(() => {
sources.forEach((source, i) => {
source.audio.addEventListener('ended', () => {
const newPlayers = [...players]
newPlayers[i].playing = false
setPlayers(newPlayers)
})
})
return () => {
sources.forEach((source, i) => {
source.audio.removeEventListener('ended', () => {
const newPlayers = [...players]
newPlayers[i].playing = false
setPlayers(newPlayers)
})
})
}
}, [])
return [players, toggle]
}
const MultiPlayer = ({ urls }) => {
const [players, toggle] = useMultiAudio(urls)
return (
<div>
{players.map((player, i) => (
<Player key={i} player={player} toggle={toggle(i)} />
))}
</div>
)
}
const Player = ({ player, toggle }) => (
<div>
<p>Stream URL: {player.url}</p>
<button onClick={toggle}>{player.playing ? 'Pause' : 'Play'}</button>
</div>
)
export default MultiPlayer
»App.js
MultiPlayer
★★★★★★★★★★★★★★★★★★:
import React from 'react'
import './App.css'
import MultiPlayer from './MultiPlayer'
function App() {
return (
<div className="App">
<MultiPlayer
urls={[
'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3',
'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3',
'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3',
]}
/>
</div>
)
}
export default App
2개의 병렬 어레이를 관리하는 것이 목적입니다.
- 소스(「」에서)
urls
컴포넌트에 ; 모모컴컴컴컴 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;.urls
URL)입니다. - 각 플레이어의 상태를 추적하는 배열
toggle
을 다음합니다.
- 현재 활성 상태인 플레이어가 있고(즉, 오디오가 재생 중) 이 활성 플레이어가 토글 메서드의 대상이 아닌 경우 해당 플레이어의 재생 상태를 false로 되돌리고 대상 플레이어의 재생 상태를 true로 설정합니다. [다른 오디오 스트림이 이미 재생 중일 때 '재생'을 클릭했습니다]
- 현재 활성 상태인 플레이어가 전환 방식의 대상 플레이어인 경우 대상 플레이어의 플레이 상태를 false로 되돌리기만 하면 됩니다. ['클릭'을 클릭했습니다.
- 현재 활성화된 플레이어가 없는 경우 대상 플레이어의 상태를 true로 설정하십시오(현재 재생 중인 오디오 스트림이 없을 때 '재생'을 클릭했습니다).
에 주의:toggle
소스 플레이어의 인덱스(즉, 해당 버튼이 클릭된 하위 구성요소의 인덱스)를 받아들이도록 메서드가 큐레이션됩니다.
는 '오디오 오브젝트 제어로 .useEffect
원래 후크에서는 그렇지만 업데이트 할 때마다 오디오 오브젝트 전체를 반복해야 하기 때문에 조금 더 복잡합니다.
에 대한 는 두 'ended' 됩니다.useEffect
원래 후크에서와 같으나 이러한 단일 객체가 아닌 오디오 객체의 배열을 처리하도록 업데이트되었습니다.
됩니다.MultiPlayer
컴포넌트플레이어를 는, 의 플레이어에 맵 .Player
및 를 사용합니다 (a) "URL"은 플레이어의 현재 상태와 소스 스트리밍 URL을 포함합니다.
할 요, 아, 아, 아, 아, 아.useSound
이를 수행하려면 먼저 npm 패키지를 설치합니다.
npm install use-sound
Import:
import useSound from 'use-sound'
import mySound from '../assets/sounds/yourSound.mp3' // Your sound file path here
사용 예 1
심플한 어프로치..
function MyButton(){
const [playSound] = useSound(mySound)
return (
<button onClick={() => playSound()}>
Play Sound
</button>
)
}
사용 예 2
이 설정에서는 볼륨을 제어할 수 있습니다.ㅇㅇㅇㅇ.playSound()
라고 합니다.handleClick()
클릭만으로 소리를 재생하는 것보다 더 많은 작업을 수행할 수 있습니다.
function MyButton(){
const [playSound] = useSound(mySound, { volume: 0.7 }) // 70% of the original volume
const handleClick = () => {
playSound()
// maybe you want to add other things here?
}
return (
<button onClick={() => handleClick()}>
Play Sound
</button>
)
}
나는 이 답변의 구현에 대해 다른 문제에 직면했다.
브라우저는 리렌더 할 때마다 계속 소리를 다운로드하려고 하는 것 같습니다.
나는 결국 그것을 이용하게 되었다.useMemo
의존관계가 없는 Audio의 경우 후크가 Audio를 한 번만 생성하고 재생성하지 않도록 합니다.
import {useMemo, useEffect, useState} from "react";
const useAudio = url => {
const audio = useMemo(() => new Audio(url), []);
const [playing, setPlaying] = useState(false);
const toggle = () => setPlaying(!playing);
useEffect(() => {
playing ? audio.play() : audio.pause();
},
[playing]
);
useEffect(() => {
audio.addEventListener('ended', () => setPlaying(false));
return () => {
audio.removeEventListener('ended', () => setPlaying(false));
};
}, []);
return [playing, toggle];
};
export default useAudio;
오디오가 HTMlement 태그이기 때문에 Next Js로 작업할 때 몇 가지 문제가 있었습니다.결국, 큰 에러를 일으키고 있었기 때문에, 저는 더 공부하기로 결정했고, 그 결과는 다음과 같습니다.
//inside your component function.
const [audio] = useState( typeof Audio !== "undefined" && new Audio("your-url.mp3")); //this will prevent rendering errors on NextJS since NodeJs doesn't recognise HTML tags neither its libs.
const [isPlaying, setIsPlaying] = useState(false);
플레이어를 처리하기 위해 useEffect를 만들었습니다.
useEffect(() => {
isPlaying ? audio.play() : audio.pause();
}, [isPlaying]);
지금까지 만든 기능에 따라 "isPlaying" 상태를 관리합니다.
Uncaughed TypeError: 정의되지 않은 속성 'setState'를 읽을 수 없습니다.
이 에러는, 이 키워드가 JavaScript 로 동작하기 때문에 발생합니다.이 문제를 해결하면 오디오가 제대로 재생될 것 같습니다.
에 ㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇ.console.log(this)
에 inside inside inside play()
곧 알게 될 것이다this
정의되어 있지 않기 때문에 에러가 발생합니다.this.setState()
.기본적으로 가치this
안에서.play()
그 기능이 어떻게 호출되느냐에 따라 달라집니다.
React에는 다음 두 가지 일반적인 솔루션이 있습니다.
constructor(props) {
super(props);
this.play() = this.play.bind(this);
}
- 자체 바인딩을 제공하지 않는 화살표 기능 사용
<button onClick={() => {this.play()}}>Play</button>
이제 다음 항목에 액세스할 수 있습니다.this.setState
그리고.this.audio
안에서.play()
에 대해서도 마찬가지입니다.pause()
.
나는 여기 파티에 조금 늦었지만 '토마스 헤네스'는 뒷걸음질쳤다.
이것을 보는 사람들이 직면하게 될 한 가지 문제는, 만약 당신이 이 코드를 여러 페이지가 있는 앱에서 말 그대로 사용하려고 한다면, 그들은 즐거운 시간을 보내지 못할 것이라는 것이다.상태는 컴포넌트에서 관리되므로 재생, 탐색 및 재생이 가능합니다.
컴포넌트의 상태를 App.js에 푸시하고 관리하려면 컴포넌트의 상태를 App.js로 변경합니다.
내가 무슨 말을 하는지 보여줄게.
플레이어의 컴포넌트는 다음과 같습니다.
import React, { Component } from 'react'
class MusicPlayer extends Component {
render() {
const { playing } = this.props.player;
return (
<div>
<button onClick={this.props.toggleMusic.bind(this, playing)}>{playing ? "Pause" : "Play"}</button>
</div>
);
}
};
export default MusicPlayer;
그런 다음 App.js에서는 다음과 같이 표시됩니다(TODO 목록 샘플 앱 사용).
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom'
import './App.css';
import Header from './componets/layout/Header'
import Todos from './componets/Todos'
import AddTodo from './componets/AddTodo'
import About from './componets/pages/About'
import MusicPlayer from './componets/MusicPlayer'
import axios from 'axios';
class App extends Component {
constructor(props) {
super(props);
this.state = { playing: false, todos: [] }
this.audio = new Audio('<YOUR MP3 LINK HERE>');
}
componentDidMount(){
axios.get('https://jsonplaceholder.typicode.com/todos')
.then(res => this.setState({ playing: this.state.playing, todos: res.data }))
}
toggleComplete = (id) => {
this.setState({ playing: this.state.playing, todos: this.state.todos.map(todo => {
if (todo.id === id){
todo.completed = !todo.completed
}
return todo
}) });
}
delTodo = (id) => {
axios.delete(`https://jsonplaceholder.typicode.com/todos/${id}`)
.then(res => this.setState({ playing: this.state.playing, todos: [...this.state.todos.filter(todo => todo.id !== id)] }));
}
addTodo = (title) => {
axios.post('https://jsonplaceholder.typicode.com/todos', {
title,
completed: false
})
.then(res => this.setState({ playing: this.state.playing, todos: [...this.state.todos, res.data]}))
}
toggleMusic = () => {
this.setState({ playing: !this.state.playing, todos: this.state.todos}, () => {
this.state.playing ? this.audio.play() : this.audio.pause();
});
}
render() {
return (
<Router>
<div className="App">
<div className="container">
<Header />
<Route exact path="/" render={props => (
<React.Fragment>
<AddTodo addTodo={this.addTodo} />
<Todos todos={this.state.todos} toggleComplete={this.toggleComplete} delTodo={this.delTodo} />
</React.Fragment>
)} />
<Route path="/About" render={props => (
<React.Fragment>
<About />
<MusicPlayer player={this.state} toggleMusic={this.toggleMusic} />
</React.Fragment>
)} />
</div>
</div>
</Router>
);
}
}
export default App;
이거 한번 해봐, 나한테는 잘 돼
var tinung = `${window.location.origin}/terimakasih.ogg`;
var audio = document.createElement("audio");
audio.autoplay = true;
audio.load();
audio.addEventListener(
"load",
function() {
audio.play();
},
true
);
audio.src = tinung;
언급URL : https://stackoverflow.com/questions/47686345/playing-sound-in-react-js
'programing' 카테고리의 다른 글
AngularJS - 지시사항을 지정하는 요소를 동적으로 작성합니다. (0) | 2023.03.25 |
---|---|
JSON Postgres 데이터 유형 열에서 특정 문자열을 검색하려면 어떻게 해야 합니까? (0) | 2023.03.25 |
리스트 정렬을 애니메이션화하는 리액션.js 친화적인 방법은 무엇입니까? (0) | 2023.03.25 |
python에서 json 배열을 필터링하는 방법 (0) | 2023.03.25 |
AngularJS: $리소스(솔루션)를 사용하여 파일 업로드 (0) | 2023.03.25 |