我在React中创建了一个自定义音频播放器,该音频播放器使用基于播放器持续时间的值来更新音频文件(进度条)的所谓“清理程序”。一切正常,除了如果在间隔更新时按下播放/暂停按钮(mousedown-> interval updates state-> mouseup),则单击按钮不会触发。
import React, { Component } from 'react';
import ReactSVG from 'react-svg';
import VolumeButton from 'components/VolumeButton/VolumeButton.jsx';
import play from 'img/icons/play.svg';
import pause from 'img/icons/pause.svg';
import './AudioPlayer.css';
class AudioPlayer extends Component {
constructor(props) {
super(props);
this.state = {
currentTime: '00:00',
endTime: '00:00',
intervalsInitiated: false,
player: null,
playing: false,
progressBar: null
};
this.handleResize = this.handleResize.bind(this);
}
initIntervals = () => {
let intervals = setInterval(() => {
this.updateScrubber(this.state.player.currentTime);
this.updateTime(this.state.player.currentTime);
}, 100);
this.setState({
intervals: intervals,
intervalsInitiated: true
});
};
setUpAudioTime = player => {
console.log('setup time');
let playerCurrentTime = player.currentTime;
let currentTime = this.calculateTime(playerCurrentTime);
this.setState({
currentTime: currentTime,
endTime: this.calculateTime(player.duration)
});
this.updateScrubber(playerCurrentTime);
};
initPlayer = () => {
console.log('initPlayer');
// Add resize listener for showing volume on desktop
this.addResize();
this.handleResize();
// Setup correct player
let player = new Audio(this.props.audioPath);
let progressBar = document.querySelector('.ProgressBar');
// Add event for audio stopped for play button
player.addEventListener('ended', () => this.toggleAudioPlay());
// Set state to correct player
// TODO: Do this in update aswell going from one to another
this.setState({
player: player,
progressBar: progressBar
});
player.addEventListener('loadedmetadata', () =>
this.setUpAudioTime(player)
);
};
toggleAudioPlay = () => {
console.log('toggling audio');
if (!this.state.player) {
return;
}
!this.state.intervalsInitiated
? this.initIntervals()
: this.resetComponent();
this.state.playing
? this.state.player.pause()
: this.state.player.play();
this.setState({
playing: !this.state.playing
});
};
updateScrubber = playerCurrentTime => {
if (!this.state.player || !this.state.progressBar) {
return;
}
let prog = this.state.progressBar;
prog.value = playerCurrentTime / this.state.player.duration;
this.setState({
progressBar: prog
});
};
updateTime = playerCurrentTime => {
this.setState({
currentTime: this.calculateTime(playerCurrentTime)
});
};
calculateTime = lengthInSeconds => {
let minutes = Math.floor(lengthInSeconds / 60);
let seconds = Math.floor(lengthInSeconds) - minutes * 60;
let time =
(minutes < 10 ? '0' + minutes : minutes) +
':' +
(seconds < 10 ? '0' + seconds : seconds);
return time;
};
seek = event => {
if (!this.state.player || !this.state.progressBar) {
return;
}
let percent =
event.nativeEvent.offsetX / this.state.progressBar.offsetWidth;
let prog = this.state.progressBar;
prog.value = percent;
this.setState({ progressBar: prog });
let newTime = percent * this.state.player.duration;
let player = this.state.player;
player.currentTime = newTime;
this.setState({
player: player
});
this.updateTime(newTime);
};
resetComponent() {
console.log('reset component');
clearInterval(this.state.intervals);
this.setState({
intervalsInitiated: false
});
}
componentDidMount() {
this.initPlayer();
}
render() {
return (
<div
className={`AudioPlayer ${
this.state.width < 800 ? 'AudioPlayer--extended' : ''
}`}
>
<audio className="MarkerAudio" preload="metadata">
<source src={this.props.audioPath} type="audio/mp3" />
Your device doesnt support audio format.
</audio>
<div className="PlayerControls">
<div className="PlayButton" onClick={this.toggleAudioPlay}>
{this.state.playing ? (
<ReactSVG
className="AudioIcon"
svgStyle={{ height: '100%', width: '100%' }}
path={pause}
/>
) : (
<ReactSVG
className="AudioIcon"
svgStyle={{
height: '100%',
left: '2px',
position: 'relative',
width: '100%'
}}
path={play}
/>
)}
</div>
<span className="CurrentTime">
{this.state.currentTime}
</span>
<progress
onClick={this.seek}
className="ProgressBar"
value="0"
min="0"
max="1"
/>
<span>{this.state.endTime}</span>
</div>
</div>
);
}
}
export default AudioPlayer;
但是,如果我确定要进行“快速单击”或未启动间隔,则单击仍然有效。关于如何处理的任何想法?我应该使用onMouseDown还是其他方式?还是有办法确保间隔和状态更改不会干扰onClick?
答案 0 :(得分:0)
所以对于任何想知道它有什么作用的人,在状态更新时单击该图标都无法正常冒泡。为了解决这个问题,我要做的就是在图标上添加pointer-events: none;
,以便直接在div而不是图标上触发点击。