Skip to content

Commit

Permalink
Add light prop
Browse files Browse the repository at this point in the history
  • Loading branch information
webmiraclepro committed Dec 17, 2018
1 parent 062f121 commit 8026207
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 7 deletions.
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -66,6 +66,7 @@ Prop | Description | Default
`playing` | Set to `true` or `false` to pause or play the media | `false`
`loop` | Set to `true` or `false` to loop the media | `false`
`controls` | Set to `true` or `false` to display native player controls<br />&nbsp;&nbsp;Vimeo, Twitch and Wistia player will always display controls | `false`
`light` | Set to `true` to show just the video thumbnail, which loads the full player on click<br />&nbsp;&nbsp;Pass in an image URL to override the preview image | `false`
`volume` | Set the volume of the player, between `0` and `1`<br/>&nbsp;&nbsp;`null` uses default volume on all players [`#357`](https://github.com/CookPete/react-player/issues/357) | `null`
`muted` | Mutes the player<br/>&nbsp;&nbsp;Only works if `volume` is set | `false`
`playbackRate` | Set the playback rate of the player<br />&nbsp;&nbsp;Only supported by YouTube, Wistia, and file paths | `1`
Expand Down Expand Up @@ -168,6 +169,14 @@ Method | Description

### Advanced Usage

#### Light player

The `light` prop will render a video thumbnail with simple play icon, and only load the full player once a user has interacted with the image. [Noembed](https://noembed.com) is used to fetch thumbnails for a video URL. Note that automatic thumbnail fetching for Facebook, Wistia, Mixcloud and file URLs are not supported, and ongoing support for other URLs is not guaranteed.

If you want to pass in your own thumbnail to use, set `light` to the image URL rather than `true`.

The styles for the preview image and play icon can be overridden by targeting the CSS classes `react-player__preview`, `react-player__shadow` and `react-player__play-icon`.

#### Responsive player

Set `width` and `height` to `100%` and wrap the player in a [fixed aspect ratio box](https://css-tricks.com/aspect-ratio-boxes) to get a responsive player:
Expand Down
1 change: 1 addition & 0 deletions index.d.ts
Expand Up @@ -81,6 +81,7 @@ export interface ReactPlayerProps {
progressInterval?: number;
playsinline?: boolean;
pip?: boolean;
light?: boolean | string;
wrapper?: any;
config?: Config;
soundcloudConfig?: SoundCloudConfig;
Expand Down
72 changes: 72 additions & 0 deletions src/Preview.js
@@ -0,0 +1,72 @@
import React, { Component } from 'react'

const ICON_SIZE = '64px'

export default class Preview extends Component {
state = {
image: null
}
componentDidMount () {
this.fetchImage(this.props)
}
componentWillReceiveProps (nextProps) {
if (this.props.url !== nextProps.url) {
this.fetchImage(nextProps)
}
}
fetchImage ({ url, light }) {
if (typeof light === 'string') {
this.setState({ image: light })
return
}
this.setState({ image: null })
return window.fetch(`http://noembed.com/embed?url=${url}`)
.then(response => response.json())
.then(data => {
if (data.thumbnail_url) {
const image = data.thumbnail_url.replace('height=100', 'height=480')
this.setState({ image })
}
})
}
render () {
const { onClick } = this.props
const { image } = this.state
const flexCenter = {
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
const styles = {
preview: {
width: '100%',
height: '100%',
backgroundImage: image ? `url(${image})` : undefined,
backgroundSize: 'cover',
backgroundPosition: 'center',
cursor: 'pointer',
...flexCenter
},
shadow: {
background: 'radial-gradient(rgb(0, 0, 0, 0.3), rgba(0, 0, 0, 0) 60%)',
borderRadius: ICON_SIZE,
width: ICON_SIZE,
height: ICON_SIZE,
...flexCenter
},
playIcon: {
borderStyle: 'solid',
borderWidth: '16px 0 16px 26px',
borderColor: 'transparent transparent transparent white',
marginLeft: '7px'
}
}
return (
<div style={styles.preview} className='react-player__preview' onClick={onClick}>
<div style={styles.shadow} className='react-player__shadow'>
<div style={styles.playIcon} className='react-player__play-icon' />
</div>
</div>
)
}
}
31 changes: 24 additions & 7 deletions src/ReactPlayer.js
Expand Up @@ -4,6 +4,7 @@ import { propTypes, defaultProps, DEPRECATED_CONFIG_PROPS } from './props'
import { getConfig, omit, isEqual } from './utils'
import players from './players'
import Player from './Player'
import Preview from './Preview'
import { FilePlayer } from './players/FilePlayer'
import renderPreloadPlayers from './preload'

Expand Down Expand Up @@ -38,18 +39,24 @@ export default class ReactPlayer extends Component {
return false
}
config = getConfig(this.props, defaultProps, true)
state = {
showPreview: !!this.props.light
}
componentDidMount () {
if (this.props.progressFrequency) {
const message = 'ReactPlayer: %cprogressFrequency%c is deprecated, please use %cprogressInterval%c instead'
console.warn(message, 'font-weight: bold', '', 'font-weight: bold', '')
}
}
shouldComponentUpdate (nextProps) {
return !isEqual(this.props, nextProps)
shouldComponentUpdate (nextProps, nextState) {
return !isEqual(this.props, nextProps) || !isEqual(this.state, nextState)
}
componentWillUpdate (nextProps) {
this.config = getConfig(nextProps, defaultProps)
}
onClickPreview = () => {
this.setState({ showPreview: false })
}
getDuration = () => {
if (!this.player) return null
return this.player.getDuration()
Expand Down Expand Up @@ -88,9 +95,8 @@ export default class ReactPlayer extends Component {
activePlayerRef = player => {
this.player = player
}
renderActivePlayer (url) {
renderActivePlayer (url, activePlayer) {
if (!url) return null
const activePlayer = this.getActivePlayer(url)
return (
<Player
{...this.props}
Expand All @@ -110,11 +116,22 @@ export default class ReactPlayer extends Component {
return 0
}
render () {
const { url, style, width, height, wrapper: Wrapper } = this.props
const { url, style, width, height, light, wrapper: Wrapper } = this.props
const { showPreview } = this.state
const otherProps = omit(this.props, SUPPORTED_PROPS, DEPRECATED_CONFIG_PROPS)
const activePlayer = this.renderActivePlayer(url)
const activePlayer = this.getActivePlayer(url)
const renderedActivePlayer = this.renderActivePlayer(url, activePlayer)
const preloadPlayers = renderPreloadPlayers(url, this.config)
const players = [ activePlayer, ...preloadPlayers ].sort(this.sortPlayers)
const players = [ renderedActivePlayer, ...preloadPlayers ].sort(this.sortPlayers)
if (showPreview && url) {
return (
<Preview
url={url}
light={light}
onClick={this.onClickPreview}
/>
)
}
return (
<Wrapper ref={this.wrapperRef} style={{ ...style, width, height }} {...otherProps}>
{players}
Expand Down
2 changes: 2 additions & 0 deletions src/props.js
Expand Up @@ -16,6 +16,7 @@ export const propTypes = {
progressInterval: number,
playsinline: bool,
pip: bool,
light: oneOfType([ bool, string ]),
wrapper: oneOfType([ string, func ]),
config: shape({
soundcloud: shape({
Expand Down Expand Up @@ -84,6 +85,7 @@ export const defaultProps = {
progressInterval: 1000,
playsinline: false,
pip: false,
light: false,
wrapper: 'div',
config: {
soundcloud: {
Expand Down

0 comments on commit 8026207

Please sign in to comment.