HLS-compatible video player
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.VideoButtons { | |
text-align: center; | |
margin: 3em auto 5.5em auto; | |
} | |
.VideoButtons span { | |
margin: 1em; | |
} | |
@media only screen and (max-width: 550px) { | |
.VideoButtons span { | |
display: block; | |
margin: 2em auto; | |
} | |
} | |
#posterWrapper { | |
position: relative; | |
} | |
#posterWrapper:hover svg { | |
cursor: pointer; | |
} | |
#posterWrapper:hover path { | |
fill: #6F3CD1; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { PureComponent } from 'react' | |
import Hls from 'hls.js' | |
import './styles.css' | |
import VideoPosterImg from '../images/VideoPosterImg' | |
import media from '../../media/HiomeDemo.mp4' | |
class Video extends PureComponent { | |
componentDidMount() { | |
const video = document.getElementById('heroVid') | |
const src = '/hls/WelcomeHiome.m3u8' | |
if (video.canPlayType('application/vnd.apple.mpegurl')) { | |
// native HLS support | |
video.src = src | |
} else if (Hls.isSupported()) { | |
// fallback to hls.js | |
const hls = new Hls(); | |
hls.loadSource(src) | |
hls.attachMedia(video) | |
} else { | |
// fallback to downloading whole media file like a chump | |
video.src = media | |
} | |
} | |
getElementY(element) { | |
const el = element.getBoundingClientRect() | |
// center video in screen | |
return window.pageYOffset + el.top + (el.bottom - el.top)/2 - window.innerHeight/2 | |
} | |
doScrolling(element, duration) { | |
const startingY = window.pageYOffset | |
const elementY = this.getElementY(element) | |
// If element is close to page's bottom then window will scroll only to some position above the element. | |
const targetY = document.body.scrollHeight - elementY < window.innerHeight ? document.body.scrollHeight - window.innerHeight : elementY | |
const diff = targetY - startingY | |
if (!diff) return | |
// Easing function: easeInOutCubic from https://gist.github.com/gre/1650294 | |
const easing = (t) => ( t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 ) | |
let start | |
// Bootstrap our animation - it will get called right before next frame shall be rendered. | |
window.requestAnimationFrame(function step(timestamp) { | |
if (!start) start = timestamp | |
// Elapsed miliseconds since start of scrolling. | |
const time = timestamp - start | |
// Get percent of completion in range [0, 1]. | |
let percent = Math.min(time / duration, 1) | |
// Apply the easing. | |
percent = easing(percent) | |
// Do the scroll. | |
window.scrollTo(0, startingY + diff * percent) | |
// Proceed to next step if there's time left. | |
if (time < duration) { | |
window.requestAnimationFrame(step) | |
} | |
}) | |
} | |
play = () => { | |
this.playing() | |
this.doScrolling(document.getElementById("heroVid"), 1000) | |
} | |
playing = () => { | |
const poster = document.getElementById('posterWrapper') | |
const video = document.getElementById('heroVid') | |
poster.style.display = 'none' | |
video.style.display = 'block' | |
video.play() | |
const watchBtn = document.getElementById('watch') | |
watchBtn.style.transition = "background-color 1s ease-in-out, color 1s ease-in-out, border-color 1s ease-in-out" | |
watchBtn.classList.add('disabled') | |
} | |
renderButton() { | |
return ( | |
<div className="VideoButtons"> | |
<span> | |
<button id="watch" className="secondary" onClick={this.play}>Watch Video</button> | |
</span> | |
<span> | |
<a className="primary" href="/order" title="I'm ready to smarten my home!">Order Now</a> | |
</span> | |
</div> | |
) | |
} | |
render() { | |
return ( | |
<> | |
{this.renderButton()} | |
<div id="posterWrapper" onClick={this.playing}> | |
<img src={VideoPosterImg} alt="Welcome Hiome" style={{ | |
width: `100%`, | |
height: `auto`, | |
paddingBottom: `56.25%`, | |
boxShadow: `2px 2px 15px #ccc`, | |
backgroundColor: `#ccc` | |
}} /> | |
<svg fill="#000" style={{ | |
position: `absolute`, | |
top: `40%`, | |
left: `45%`, | |
width: `10%` | |
}} xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 100 100"><g><g><path d="M50,2.5C23.8,2.5,2.5,23.8,2.5,50S23.8,97.5,50,97.5c26.2,0,47.5-21.3,47.5-47.5S76.2,2.5,50,2.5z M65.3,52.4L42.9,67.3 c-1.9,1.3-4.5-0.1-4.5-2.4V35.1c0-2.3,2.6-3.7,4.5-2.4l22.4,14.9C67,48.7,67,51.3,65.3,52.4z"></path></g></g></svg> | |
</div> | |
<video controls width="100%" preload="auto" id="heroVid" style={{ | |
boxShadow: `2px 2px 15px #ccc`, | |
marginBottom: `2rem`, | |
backgroundColor: `#ccc`, | |
display: `none` | |
}}> | |
Sorry, your browser doesn't support embedded videos. <a href="https://www.youtube.com/watch?v=PLBdi5frOGA">Watch it on YouTube</a>. | |
</video> | |
</> | |
) | |
} | |
} | |
export default Video |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment