From 9f707dfa8c0b2d38d4d81c1cf0df38df494a49b2 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 23 Sep 2020 16:08:26 +0200 Subject: new video UI --- .../views/viewer/player/components.media/index.js | 2 + .../views/viewer/player/components.media/media.css | 51 ++++++++++---- .../player/components.media/video.scrubber.js | 82 ++++++++++++++++++++++ 3 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 animism-align/frontend/app/views/viewer/player/components.media/video.scrubber.js (limited to 'animism-align/frontend/app/views/viewer/player/components.media') diff --git a/animism-align/frontend/app/views/viewer/player/components.media/index.js b/animism-align/frontend/app/views/viewer/player/components.media/index.js index 37f6f64..04b7f03 100644 --- a/animism-align/frontend/app/views/viewer/player/components.media/index.js +++ b/animism-align/frontend/app/views/viewer/player/components.media/index.js @@ -13,6 +13,7 @@ import { } from './media.gallery' import Carousel from './media.carousel' +import VideoScrubber from './video.scrubber' import { Grid @@ -24,4 +25,5 @@ export { Gallery, Carousel, Grid, + VideoScrubber, } \ No newline at end of file diff --git a/animism-align/frontend/app/views/viewer/player/components.media/media.css b/animism-align/frontend/app/views/viewer/player/components.media/media.css index 32d35d0..653a53b 100644 --- a/animism-align/frontend/app/views/viewer/player/components.media/media.css +++ b/animism-align/frontend/app/views/viewer/player/components.media/media.css @@ -302,29 +302,56 @@ .video-scrubber { position: absolute; - bottom: 5rem; - left: 50%; - width: 300px; - height: 16px; - margin-left: -150px; + bottom: 4rem; + left: 1rem; + width: calc(100% - 2rem); + height: 3rem; + background: white; + border-radius: 1.5rem; + display: flex; + align-items: center; +} +.video-scrubber .start-controls { + width: 3rem; + display: flex; + align-items: center; + justify-content: center; +} +.video-scrubber .scrub-bar-container { + flex: 1; + height: 3rem; + display: flex; + align-items: center; + position: relative; cursor: pointer; } .video-scrubber .scrub-bar { - position: absolute; - top: 7px; - left: 0; + position: relative; width: 100%; height: 2px; - background: white; + margin-top: 1px; + background: black; } .video-scrubber .scrub-dot { position: absolute; - top: 0; + top: 50%; left: 0; width: 16px; height: 16px; + margin-top: -7px; margin-left: -8px; border-radius: 50%; - background: white; - cursor: pointer; + background: black; + pointer-events: none; +} +.video-scrubber .end-controls { + width: 7rem; + display: flex; + flex-direction: row; + justify-content: center; + color: black; } +.video-scrubber .playerTime { + display: flex; + align-items: center; +} \ No newline at end of file diff --git a/animism-align/frontend/app/views/viewer/player/components.media/video.scrubber.js b/animism-align/frontend/app/views/viewer/player/components.media/video.scrubber.js new file mode 100644 index 0000000..7bbbc07 --- /dev/null +++ b/animism-align/frontend/app/views/viewer/player/components.media/video.scrubber.js @@ -0,0 +1,82 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' + +import actions from 'app/actions' +import { clamp, timestamp } from 'app/utils' +import { PlayButton, VolumeControl } from 'app/views/viewer/nav/viewer.icons' + +class VideoScrubber extends Component { + constructor(props) { + super(props) + this.scrubberRef = React.createRef() + this.handleScrubDotMouseDown = this.handleScrubDotMouseDown.bind(this) + this.handleScrubDotMouseMove = this.handleScrubDotMouseMove.bind(this) + this.handleScrubDotMouseUp = this.handleScrubDotMouseUp.bind(this) + } + componentDidMount() { + window.addEventListener('mousemove', this.handleScrubDotMouseMove) + window.addEventListener('mouseup', this.handleScrubDotMouseUp) + } + componentWillUnmount() { + window.removeEventListener('mousemove', this.handleScrubDotMouseMove) + window.removeEventListener('mouseup', this.handleScrubDotMouseUp) + } + scrub(x, scrubbing) { + const { timing, start_ts, onScrub } = this.props + const bounds = this.scrubberRef.current.getBoundingClientRect() + const percent = clamp((x - bounds.left) / bounds.width, 0, 1) + const seconds = percent * timing.duration + actions.audio.seek(start_ts + seconds) + onScrub({ + seek: seconds, + percent, seconds, scrubbing + }) + } + handleScrubDotMouseDown(e) { + e.stopPropagation() + this.scrub(e.pageX, true) + } + handleScrubDotMouseMove(e) { + e.stopPropagation() + if (!this.props.timing.scrubbing) return + this.scrub(e.pageX, true) + } + handleScrubDotMouseUp(e) { + e.stopPropagation() + this.props.onScrub({ scrubbing: false }) + } + render() { + const { playing, volume, timing } = this.props + return ( +
+
+ +
+
+
+
+
+
+
+ {timestamp(clamp(timing.seconds, 0, timing.duration))} +
+ +
+
+ ) + } +} + +const mapStateToProps = state => ({ + playing: state.audio.playing, + volume: state.audio.volume, +}) + +export default connect(mapStateToProps)(VideoScrubber) -- cgit v1.2.3-70-g09d2