Updated Video Component x2
• Updated: - Video Component x2 - Smooth seek transition with linear - Hide large center play, volume slider, pip on mobile - Update to buffering
This commit is contained in:
parent
2b69ddc849
commit
5665094fd0
@ -13,13 +13,16 @@ import { displayMedia } from '../initial_state'
|
|||||||
import {
|
import {
|
||||||
CX,
|
CX,
|
||||||
POPOVER_VIDEO_STATS,
|
POPOVER_VIDEO_STATS,
|
||||||
|
BREAKPOINT_EXTRA_SMALL,
|
||||||
} from '../constants'
|
} from '../constants'
|
||||||
|
import Responsive from '../features/ui/util/responsive_component'
|
||||||
import Button from './button'
|
import Button from './button'
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
import Text from './text'
|
import Text from './text'
|
||||||
|
|
||||||
// check every 50 ms (do not use lower values)
|
// check every 50 ms for buffer
|
||||||
const checkInterval = 50.0
|
const checkInterval = 50
|
||||||
|
const FIXED_VAR = 6
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
play: { id: 'video.play', defaultMessage: 'Play' },
|
play: { id: 'video.play', defaultMessage: 'Play' },
|
||||||
@ -37,7 +40,7 @@ const messages = defineMessages({
|
|||||||
const formatTime = (secondsNum) => {
|
const formatTime = (secondsNum) => {
|
||||||
let hours = Math.floor(secondsNum / 3600)
|
let hours = Math.floor(secondsNum / 3600)
|
||||||
let minutes = Math.floor((secondsNum - (hours * 3600)) / 60)
|
let minutes = Math.floor((secondsNum - (hours * 3600)) / 60)
|
||||||
let seconds = secondsNum - (hours * 3600) - (minutes * 60)
|
let seconds = Math.floor(secondsNum) - (hours * 3600) - (minutes * 60)
|
||||||
|
|
||||||
if (hours < 10) hours = '0' + hours
|
if (hours < 10) hours = '0' + hours
|
||||||
if (minutes < 10) minutes = '0' + minutes
|
if (minutes < 10) minutes = '0' + minutes
|
||||||
@ -203,12 +206,11 @@ class Video extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkBuffering = () => {
|
checkBuffering = () => {
|
||||||
const { isBuffering, paused } = this.state
|
const { isBuffering, paused, currentTime } = this.state
|
||||||
const { currentTime } = this.video
|
|
||||||
|
|
||||||
// checking offset should be at most the check interval
|
// checking offset should be at most the check interval
|
||||||
// but allow for some margin
|
// but allow for some margin
|
||||||
let offset = (checkInterval - 20) / 1000
|
let offset = checkInterval / 1000
|
||||||
|
|
||||||
// if no buffering is currently detected,
|
// if no buffering is currently detected,
|
||||||
// and the position does not seem to increase
|
// and the position does not seem to increase
|
||||||
@ -279,7 +281,10 @@ class Video extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handlePause = () => {
|
handlePause = () => {
|
||||||
this.setState({ paused: true })
|
this.setState({
|
||||||
|
paused: true,
|
||||||
|
isBuffering: false,
|
||||||
|
})
|
||||||
|
|
||||||
clearInterval(this.bufferCheckInterval)
|
clearInterval(this.bufferCheckInterval)
|
||||||
}
|
}
|
||||||
@ -287,8 +292,8 @@ class Video extends ImmutablePureComponent {
|
|||||||
handleTimeUpdate = () => {
|
handleTimeUpdate = () => {
|
||||||
const { currentTime, duration } = this.video
|
const { currentTime, duration } = this.video
|
||||||
this.setState({
|
this.setState({
|
||||||
currentTime: Math.floor(currentTime),
|
currentTime: currentTime.toFixed(FIXED_VAR),
|
||||||
duration: Math.floor(duration),
|
duration: duration.toFixed(FIXED_VAR),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,7 +364,7 @@ class Video extends ImmutablePureComponent {
|
|||||||
|
|
||||||
handleMouseMove = throttle(e => {
|
handleMouseMove = throttle(e => {
|
||||||
const { x } = getPointerPosition(this.seek, e)
|
const { x } = getPointerPosition(this.seek, e)
|
||||||
const currentTime = Math.floor(this.video.duration * x)
|
const currentTime = parseFloat(this.video.duration * x).toFixed(FIXED_VAR)
|
||||||
|
|
||||||
if (!isNaN(currentTime)) {
|
if (!isNaN(currentTime)) {
|
||||||
this.video.currentTime = currentTime
|
this.video.currentTime = currentTime
|
||||||
@ -576,6 +581,7 @@ class Video extends ImmutablePureComponent {
|
|||||||
z3: 1,
|
z3: 1,
|
||||||
alignItemsCenter: 1,
|
alignItemsCenter: 1,
|
||||||
justifyContentCenter: 1,
|
justifyContentCenter: 1,
|
||||||
|
videoEase: 1,
|
||||||
opacity0: !dragging,
|
opacity0: !dragging,
|
||||||
opacity1: dragging || hovered,
|
opacity1: dragging || hovered,
|
||||||
})
|
})
|
||||||
@ -595,6 +601,7 @@ class Video extends ImmutablePureComponent {
|
|||||||
mt10: 1,
|
mt10: 1,
|
||||||
posAbs: 1,
|
posAbs: 1,
|
||||||
height4PX: 1,
|
height4PX: 1,
|
||||||
|
videoEase: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
const volumeControlClasses = CX({
|
const volumeControlClasses = CX({
|
||||||
@ -654,15 +661,17 @@ class Video extends ImmutablePureComponent {
|
|||||||
<div className={overlayClasses}>
|
<div className={overlayClasses}>
|
||||||
{
|
{
|
||||||
paused && !isBuffering &&
|
paused && !isBuffering &&
|
||||||
<button
|
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||||
onClick={this.togglePlay}
|
<button
|
||||||
className={[_s.default, _s.outlineNone, _s.cursorPointer, _s.alignItemsCenter, _s.justifyContentCenter, _s.posAbs, _s.bgBlackOpaque, _s.circle, _s.height60PX, _s.width60PX].join(' ')}
|
onClick={this.togglePlay}
|
||||||
>
|
className={[_s.default, _s.outlineNone, _s.cursorPointer, _s.alignItemsCenter, _s.justifyContentCenter, _s.posAbs, _s.bgBlackOpaque, _s.circle, _s.height60PX, _s.width60PX].join(' ')}
|
||||||
<Icon id='play' size='24px' className={_s.fillWhite} />
|
>
|
||||||
</button>
|
<Icon id='play' size='24px' className={_s.fillWhite} />
|
||||||
|
</button>
|
||||||
|
</Responsive>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
isBuffering &&
|
!paused && isBuffering &&
|
||||||
<Icon id='loading' size='40px' className={[_s.default, _s.posAbs].join(' ')} />
|
<Icon id='loading' size='40px' className={[_s.default, _s.posAbs].join(' ')} />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -801,20 +810,22 @@ class Video extends ImmutablePureComponent {
|
|||||||
buttonRef={this.setSettingsBtnRef}
|
buttonRef={this.setSettingsBtnRef}
|
||||||
title='Video stats'
|
title='Video stats'
|
||||||
/>
|
/>
|
||||||
{
|
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||||
pipAvailable &&
|
{
|
||||||
<Button
|
pipAvailable &&
|
||||||
isNarrow
|
<Button
|
||||||
backgroundColor='none'
|
isNarrow
|
||||||
aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)}
|
backgroundColor='none'
|
||||||
onClick={this.togglePip}
|
aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)}
|
||||||
icon='pip'
|
onClick={this.togglePip}
|
||||||
iconSize='20px'
|
icon='pip'
|
||||||
iconClassName={_s.fillWhite}
|
iconSize='20px'
|
||||||
className={[_s.px10, _s.pr0].join(' ')}
|
iconClassName={_s.fillWhite}
|
||||||
title='Picture in Picture'
|
className={[_s.px10, _s.pr0].join(' ')}
|
||||||
/>
|
title='Picture in Picture'
|
||||||
}
|
/>
|
||||||
|
}
|
||||||
|
</Responsive>
|
||||||
<Button
|
<Button
|
||||||
isNarrow
|
isNarrow
|
||||||
backgroundColor='none'
|
backgroundColor='none'
|
||||||
|
@ -827,6 +827,10 @@ body {
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.videoEase {
|
||||||
|
transition: left 0.25s linear, width 0.25s linear;
|
||||||
|
}
|
||||||
|
|
||||||
.videoPlayerControlsBackground {
|
.videoPlayerControlsBackground {
|
||||||
background: linear-gradient(0deg, rgba(0,0,0,.85), rgba(0,0,0,.45) 60%, transparent);
|
background: linear-gradient(0deg, rgba(0,0,0,.85), rgba(0,0,0,.45) 60%, transparent);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user