diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2020-09-23 16:08:26 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2020-09-23 16:08:26 +0200 |
| commit | 9f707dfa8c0b2d38d4d81c1cf0df38df494a49b2 (patch) | |
| tree | 2c8af745d62fcfd7002bc66939b31b408bc85c3c /animism-align/frontend | |
| parent | 41052dd5b95cf2813662d8201b206ad2af78da40 (diff) | |
new video UI
Diffstat (limited to 'animism-align/frontend')
6 files changed, 136 insertions, 68 deletions
diff --git a/animism-align/frontend/app/views/viewer/nav/nav.css b/animism-align/frontend/app/views/viewer/nav/nav.css index daa90e1..a5c19d0 100644 --- a/animism-align/frontend/app/views/viewer/nav/nav.css +++ b/animism-align/frontend/app/views/viewer/nav/nav.css @@ -197,13 +197,11 @@ stroke: #000; stroke-width: 0.5; } -.fullscreen-element.video .volume path, .viewer-nav.hovering-nav .volume path, .viewer-nav.black .volume path, .nav-open .volume path { fill: #fff; } -.fullscreen-element.video .volume.muted path, .viewer-nav.hovering-nav .volume.muted path, .viewer-nav.black .volume.muted path, .nav-open .volume.muted path { @@ -222,8 +220,6 @@ .playToggle polygon { fill: #000; } -.fullscreen-element.video .playToggle path, -.fullscreen-element.video .playToggle polygon, .viewer-nav.hovering-nav .playToggle path, .viewer-nav.hovering-nav .playToggle polygon, .viewer-nav.black .playToggle path, diff --git a/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.video.js b/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.video.js index a196ee5..929daef 100644 --- a/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.video.js +++ b/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.video.js @@ -3,7 +3,7 @@ import { connect } from 'react-redux' import VimeoPlayer from 'app/utils/vendor/vimeo' import actions from 'app/actions' -import { PlayButton, PlayerTime, VolumeControl } from 'app/views/viewer/nav/viewer.icons' +import { VideoScrubber } from '../components.media' class FullscreenVideo extends Component { state = { @@ -15,24 +15,10 @@ class FullscreenVideo extends Component { } constructor(props) { super(props) - this.scrubberRef = React.createRef() this.handlePlay = this.handlePlay.bind(this) this.handlePause = this.handlePause.bind(this) this.handleTimeUpdate = this.handleTimeUpdate.bind(this) this.handleEnd = this.handleEnd.bind(this) - this.handleScrubBarClick = this.handleScrubBarClick.bind(this) - 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) - this.setState({ scrubbing: false }) } componentDidUpdate(prevProps) { if (Math.abs(this.props.play_ts - prevProps.play_ts) > 2.0) { @@ -51,31 +37,13 @@ class FullscreenVideo extends Component { } handleTimeUpdate(timing) { - this.setState(timing) - } - handleScrubBarClick(e) { - e.stopPropagation() - const bounds = this.scrubberRef.current.getBoundingClientRect() - const percent = (e.pageX - bounds.left) / bounds.width - const seconds = percent * this.state.duration - actions.audio.seek(this.props.element.start_ts + seconds) - this.setState({ percent, seconds }) - // actions.audio.seek(clamp(play_ts - 5.0, start_ts, end_ts)) - } - handleScrubDotMouseDown(e) { - e.stopPropagation() - this.setState({ scrubbing: true }) - } - handleScrubDotMouseMove(e) { - e.stopPropagation() - if (!this.state.scrubbing) return - } - handleScrubDotMouseUp(e) { - e.stopPropagation() - this.setState({ scrubbing: false }) + if (!this.state.scrubbing || ('scrubbing' in timing)) { + this.setState(timing) + } } + render() { - const { element, media, transitionDuration, playing, volume } = this.props + const { element, media, transitionDuration, playing } = this.props const { duration, percent, seconds } = this.state const { color } = element const item = media.lookup[element.settings.media_id] @@ -84,7 +52,6 @@ class FullscreenVideo extends Component { color: color.textColor, transitionDuration, } - // console.log(item) return ( <div className='fullscreen-element video' @@ -106,18 +73,12 @@ class FullscreenVideo extends Component { onEnd={this.handleEnd} /> </div> - <div - className='video-scrubber' - onClick={this.handleScrubBarClick} - ref={this.scrubberRef} - > - <div className='scrub-bar' /> - <div - className='scrub-dot' - style={{ left: (100 * this.state.percent) + "%" }} - onMouseDown={this.handleScrubDotMouseDown} - /> - </div> + <VideoScrubber + start_ts={element.start_ts} + playing={playing} + timing={this.state} + onScrub={this.handleTimeUpdate} + /> </div> ) } @@ -127,7 +88,6 @@ const mapStateToProps = state => ({ viewer: state.viewer, play_ts: state.audio.play_ts, playing: state.audio.playing, - volume: state.audio.volume, }) export default connect(mapStateToProps)(FullscreenVideo) 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 ( + <div className='video-scrubber'> + <div className='start-controls'> + <PlayButton playing={playing} /> + </div> + <div + className='scrub-bar-container' + onMouseDown={this.handleScrubDotMouseDown} + ref={this.scrubberRef} + > + <div className='scrub-bar' /> + <div + className='scrub-dot' + style={{ left: (100 * timing.percent) + "%" }} + /> + </div> + <div className='end-controls'> + <div className='playerTime'> + {timestamp(clamp(timing.seconds, 0, timing.duration))} + </div> + <VolumeControl volume={volume} /> + </div> + </div> + ) + } +} + +const mapStateToProps = state => ({ + playing: state.audio.playing, + volume: state.audio.volume, +}) + +export default connect(mapStateToProps)(VideoScrubber) diff --git a/animism-align/frontend/app/views/viewer/player/player.fullscreen.css b/animism-align/frontend/app/views/viewer/player/player.fullscreen.css index 36e4a76..c9a1e48 100644 --- a/animism-align/frontend/app/views/viewer/player/player.fullscreen.css +++ b/animism-align/frontend/app/views/viewer/player/player.fullscreen.css @@ -59,6 +59,7 @@ .viewer-fullscreen .video { position: relative; align-items: flex-start; + user-select: none; } iframe { |
