Skip to content

Instantly share code, notes, and snippets.

@itrelease
Created March 5, 2018 13:54
Show Gist options
  • Save itrelease/0ffefaff546fa157b24398935832cc52 to your computer and use it in GitHub Desktop.
Save itrelease/0ffefaff546fa157b24398935832cc52 to your computer and use it in GitHub Desktop.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import throttle from 'lodash.throttle';
import makeClassName from 'src-utils/makeClassName';
import { ProgressTypeEnums } from './constants';
const styles = require('./Progress.css');
/* eslint-disable react/prefer-stateless-function */
class Progress extends Component {
static propTypes = {
type: PropTypes.oneOf([ProgressTypeEnums.CIRCLE, ProgressTypeEnums.PANEL])
.isRequired,
styleContext: PropTypes.string,
userInteracted: PropTypes.bool.isRequired,
episodeUrl: PropTypes.string.isRequired,
progress: PropTypes.number.isRequired,
possibleProgress: PropTypes.number,
rewind: PropTypes.func.isRequired
};
static defaultProps = {
possibleProgress: null,
styleContext: null
};
state = {
rewinding: false
};
handleMouseDown = event => {
const { currentTarget, clientX } = event;
this.setState({ rewinding: true }, () => {
this.calcProgress(currentTarget, clientX);
});
};
handleMouseMove = event => {
const { rewinding } = this.state;
if (!rewinding) {
return;
}
this.calcProgress(event.currentTarget, event.clientX);
};
handleMouseUp = () => {
this.setState({ rewinding: false });
};
calcProgress = throttle((currentTarget, clientX) => {
const { episodeUrl, rewind } = this.props;
if (!currentTarget || !clientX) {
return;
}
const elRect = currentTarget.getBoundingClientRect();
const percent = (clientX - elRect.left) * 100 / elRect.width;
rewind(episodeUrl, percent);
}, 100);
renderProgress() {
const { type, progress, possibleProgress, userInteracted } = this.props;
switch (type) {
case ProgressTypeEnums.CIRCLE: {
const strokeOffset = !userInteracted ? 339 : progress * 339 / 100;
return (
<svg viewBox="0 0 120 120" className={styles.circleWrap}>
<circle className={styles.track} cx="60" cy="60" r="54" />
<circle
className={styles.played}
cx="60"
cy="60"
r="54"
style={{
strokeDasharray: 339,
strokeDashoffset: 339 - strokeOffset
}}
/>
</svg>
);
}
default:
/* eslint-disable jsx-a11y/no-static-element-interactions */
return (
<div
className={styles.track}
onMouseDown={this.handleMouseDown}
onMouseMove={this.handleMouseMove}
onMouseUp={this.handleMouseUp}
>
<div
className={styles.played}
style={{
width: possibleProgress
? `${possibleProgress}%`
: `${progress}%`
}}
/>
<div
className={styles.knob}
style={{
left: possibleProgress ? `${possibleProgress}%` : `${progress}%`
}}
/>
</div>
);
/* eslint-enable jsx-a11y/no-static-element-interactions */
}
}
render() {
const { type, styleContext } = this.props;
return (
<div
className={makeClassName([
[styles[type], !!type && !!styles[type]],
[styles[styleContext], !!styleContext && !!styles[styleContext]]
])}
>
{this.renderProgress()}
</div>
);
}
}
/* eslint-enable react/prefer-stateless-function */
export default Progress;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment