Я делаю панель громкости, но по какой-то причине ползунок появляется за пределами временной шкалы. Вместо этого я бы хотел, чтобы он отображался в верхней части индикатора выполнения.
// мой компонент громкости:
import React from 'react';
class AudioVolume extends React.Component {
constructor(props) {
super(props);
this.state = {
volume: 1,
mute: false
};
this.handlePosition = this.handlePosition.bind(this);
this.mouseMove = this.mouseMove.bind(this);
this.mouseDown = this.mouseDown.bind(this);
this.mouseUp = this.mouseUp.bind(this);
this.mute = this.mute.bind(this);
}
componentDidMount() {
const { volume } = this.props;
this.setState({ volume });
this.handle.style.width = this.timeline.offsetWidth + "px";
this.handleCircle.style.marginLeft = this.timeline.offsetWidth + "px";
}
handlePosition(position) {
let handleLeft = position - this.timeline.offsetLeft;
if (handleLeft > this.timeline.offsetWidth || this.state.volume === 1) {
this.handle.style.width = this.timeline.offsetWidth + "px";
this.handleCircle.style.marginLeft = this.timeline.offsetWidth + "px";
}
if (handleLeft >= 0 && handleLeft <= this.timeline.offsetWidth) {
this.handle.style.width = handleLeft + "px";
this.handleCircle.style.marginLeft = handleLeft + "px";
}
if (handleLeft < 0) {
this.handle.style.width = "0px";
this.handleCircle.style.marginLeft = "0px";
}
}
mouseMove(e) {
this.handlePosition(e.pageX);
this.setState({ mute: false });
let volume = ((e.pageX - this.timeline.offsetLeft) / this.timeline.offsetWidth) * 1;
if (volume >= 1) {
volume = 1;
} else if (volume <= 0) {
volume = 0;
}
this.setState({ volume });
this.props.receiveVolume(this.state.volume);
}
mouseDown(e) {
window.addEventListener('mousemove', this.mouseMove);
window.addEventListener('mouseup', this.mouseUp);
}
mouseUp(e) {
window.removeEventListener('mousemove', this.mouseMove);
window.removeEventListener('mouseup', this.mouseUp);
}
mute() {
if (!this.state.mute) {
this.setState({ mute: true });
this.props.receiveVolume(0);
} else {
this.setState({ mute: false });
this.props.receiveVolume(this.state.volume);
}
}
render() {
let volumeClass;
if (this.state.volume >= 0.6) {
volumeClass = "ap-volume-high";
} else if (this.state.volume > 0) {
volumeClass = "ap-volume-low";
} else if (this.state.volume === 0) {
volumeClass = "ap-volume-off";
}
if (this.state.mute) volumeClass = 'ap-volume-off';
return (
<div className="ap-volume-controls">
<div className="ap-volume-icon"><i className={volumeClass}></i></div>
<div id="ap-volume-timeline" onClick={this.mouseMove} ref={(timeline) => { this.timeline = timeline }}>
<div id="ap-volume-handle" onMouseDown={this.mouseDown} ref={(handle) => { this.handle = handle }} />
<div id="ap-volume-handle-circle" onMouseDown={this.mouseDown} ref={(handleCircle) => { this.handleCircle = handleCircle }} />
</div>
</div>
);
}
}
export default AudioVolume;
// мой индикатор громкости CSS:
.ap-volume-controls {
display: flex;
flex-direction: row;
justify-content: center;
width: 100px;
margin-top: 25px;
margin-left: 130px;
.ap-volume-icon {
margin-right: 10px;
.ap-volume-high {
content: image_url('audio_player/audio_volume_high.png');
width: 17px;
height: 14px;
}
.ap-volume-low {
content: image_url('audio_player/audio_volume_low.png');
width: 14px;
height: 13px;
}
.ap-volume-off {
content: image_url('audio_player/audio_volume_off.png');
width: 17px;
height: 13px;
}
}
#ap-volume-timeline {
margin-top: 5px;
width: 85px;
height: 4px;
border-radius: 15px;
background: $audio-slider-gray;
#ap-volume-handle {
width: 0;
height: 4px;
background: $green;
}
#ap-volume-handle-circle {
width: 12px;
height: 12px;
border-radius: 50%;
background: $white;
margin-top: -8px;
}
}
}
Вот что я имею в виду:
Как сделать так, чтобы кнопка ползунка отображалась в верхней части индикатора выполнения, а не рядом с ним?
А для ясности, шкала времени - это серая полоса, а ручка - зеленая полоса: