custom seek bar implemented

This commit is contained in:
NikolaBorislavovHristov 2018-11-12 13:38:20 +02:00
parent a8ff78e0f2
commit 5db81dc1a0
4 changed files with 131 additions and 29 deletions

View file

@ -14,6 +14,7 @@
"dependencies": {
"classnames": "2.2.6",
"events": "1.1.1",
"lodash.debounce": "4.0.8",
"prop-types": "15.6.2",
"react": "16.6.0",
"react-dom": "16.6.0",

View file

@ -1,38 +1,97 @@
import React, { Component } from 'react';
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import debounce from 'lodash.debounce';
import Icon from 'stremio-icons/dom';
import styles from './styles';
class ControlBar extends Component {
onSeekRequested = (event) => {
this.props.seek(event.target.value);
class ControlBar extends PureComponent {
constructor(props) {
super(props);
this.state = {
seekTime: -1
};
}
componentWillUnmount() {
this.resetSeekTime.cancel();
}
resetSeekTime = debounce(() => {
this.setState({ seekTime: -1 });
}, 3000)
calculateSeekTime = (mouseX, seekBarElement) => {
const { left, width } = seekBarElement.getBoundingClientRect();
const position = Math.min(Math.max(mouseX - left, 0), width);
const seekTime = Math.floor((position / width) * this.props.duration);
return seekTime;
}
onStartSliding = ({ currentTarget, clientX, button }) => {
if (button !== 0) {
return;
}
const mousemove = ({ clientX }) => {
this.setState({ seekTime: this.calculateSeekTime(clientX, currentTarget) });
};
const mouseup = ({ clientX }) => {
window.removeEventListener('mousemove', mousemove);
window.removeEventListener('mouseup', mouseup);
document.body.style['pointer-events'] = 'initial';
currentTarget.classList.remove(styles['active']);
const seekTime = this.calculateSeekTime(clientX, currentTarget);
this.props.seek(seekTime);
this.resetSeekTime();
};
window.addEventListener('mousemove', mousemove);
window.addEventListener('mouseup', mouseup);
document.body.style['pointer-events'] = 'none';
currentTarget.classList.add(styles['active']);
this.setState({ seekTime: this.calculateSeekTime(clientX, currentTarget) });
this.resetSeekTime.cancel();
}
renderPlayPauseButton() {
return (
<div className={styles['button']} onClick={this.props.paused ? this.props.play : this.props.pause}>
<Icon
className={styles['icon']}
icon={this.props.paused ? 'ic_play' : 'ic_pause'}
/>
</div>
);
}
renderSeekBar() {
if (this.props.time === null || this.props.duration === null) {
return null;
}
const thumbPosition = this.state.seekTime !== -1 ?
this.state.seekTime / this.props.duration
:
this.props.time / this.props.duration;
return (
<div className={styles['seek-bar']} onMouseDown={this.onStartSliding}>
<div className={styles['seek-line']} />
<div className={styles['thumb-container']} style={{ left: `calc(100% * ${thumbPosition})` }}>
<div className={styles['thumb']} />
</div>
</div>
);
}
render() {
return (
<div className={classnames(this.props.className, styles['root-container'])}>
<div className={styles['button']} onClick={this.props.paused ? this.props.play : this.props.pause}>
<Icon
className={styles['icon']}
icon={this.props.paused ? 'ic_play' : 'ic_pause'}
/>
</div>
{
this.props.time !== null && this.props.duration !== null
?
<input
className={styles['seek-bar']}
type={'range'}
step={1000}
min={0}
max={this.props.duration}
value={this.props.time}
onChange={this.onSeekRequested}
/>
:
null
}
{this.renderPlayPauseButton()}
{this.renderSeekBar()}
{this.renderPlayPauseButton()}
</div>
);
}

View file

@ -1,13 +1,13 @@
@import 'stremio-colors';
@control-bar-height: 56px;
@control-bar-height: 52px;
.root-container {
height: @control-bar-height;
top: initial !important;
display: flex;
flex-direction: row;
background-color: @colorprimlight60;
align-items: center;
.button {
height: @control-bar-height;
@ -24,11 +24,53 @@
.icon {
width: 66%;
height: 66%;
fill: @colorwhite;
}
}
.seek-bar {
flex: 1
height: round((@control-bar-height * 0.5));
flex: 1;
position: relative;
.seek-line {
position: absolute;
z-index: 0;
left: 0;
right: 0;
top: round((@control-bar-height * 0.2));
height: round((@control-bar-height * 0.1));
background-color: @colorprim80;
}
.thumb-container {
position: absolute;
z-index: 1;
width: round((@control-bar-height * 0.5));
height: round((@control-bar-height * 0.5));
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transform: translateX(-50%);
.thumb {
width: round((@control-bar-height * 0.4));
height: round((@control-bar-height * 0.4));
border-radius: 50%;
background-color: @colorprimlight;
}
&:hover {
background-color: @colorprimlight60;
}
}
&.active {
.thumb-container {
background-color: @colorprimlight60;
}
}
}
}

View file

@ -4638,7 +4638,7 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
lodash.debounce@^4.0.8:
lodash.debounce@4.0.8, lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=