Skip to content

Instantly share code, notes, and snippets.

@maxxcrawford
Created September 30, 2015 19:50
Show Gist options
  • Save maxxcrawford/2ae447829d174ef959b8 to your computer and use it in GitHub Desktop.
Save maxxcrawford/2ae447829d174ef959b8 to your computer and use it in GitHub Desktop.
Morph Button
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Video Player</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
*, *:before, *:after {
box-sizing: border-box;
}
html, body {
height: 100%;
}
body {
margin: 0;
}
section {
height: 300px;
text-align: center;
line-height: 300px;
background: #eee;
outline: 1px solid #e0e0e0;
}
section button {
display: inline-block;
font: normal 18px "adobe-caslon-pro-n4","adobe-caslon-pro",Georgia,Palatino,"Palatino Linotype",Times,"Times New Roman",serif;
color: #f8f8f5;
text-align: center;
text-transform: uppercase;
transition: background 0.1s ease-in-out 0s, border 0.1s ease-in-out 0s;
white-space: nowrap;
border: 1px solid #f8f8f5;
background: rgba(71,71,71,0.15);
cursor: pointer;
}
.morph-video-button {
position: relative;
display: inline-block;
min-width: 150px;
margin: 0 auto;
line-height: 1;
}
.morph-video-button > button {
position: relative;
z-index: 1000;
padding: 0.75em 1.5em;
width: 100%;
height: 100%;
}
.morph-video-button > button:hover {
color: #f8f8f5;
border-color: #c1311d;
background-color: #c1311d;
}
#video-container {
position: fixed;
opacity: 0;
overflow: hidden;
background-color: #c1311d;
-webkit-transition: opacity 0.3s 0.5s, width 0.4s 0.1s, height 0.4s 0.1s, top 0.4s 0.1s, left 0.4s 0.1s, background-color 0.4s 0.1s;
transition: opacity 0.3s 0.5s, width 0.4s 0.1s, height 0.4s 0.1s, top 0.4s 0.1s, left 0.4s 0.1s, background-color 0.4s 0.1s;
}
#video-container.open {
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
opacity: 1;
background-color: #000;
-webkit-transition: opacity 0.3s, width 0.4s 0.1s, height 0.4s 0.1s, top 0.4s 0.1s, left 0.4s 0.1s, background-color 0.4s 0.1s;
transition: opacity 0.3s, width 0.4s 0.1s, height 0.4s 0.1s, top 0.4s 0.1s, left 0.4s 0.1s, background-color 0.4s 0.1s;
}
#video-container.active {
z-index: 2000;
}
#video-container .video-btn-close {
position: absolute;
z-index: 5;
top: 0;
right: 0;
width: 50px;
height: 50px;
opacity: 0;
background: url("close.png") no-repeat center center;
cursor: pointer;
-webkit-transition: opacity 0.3s 0.2s;
transition: opacity 0.3s 0.2s;
}
#video-container.open .video-btn-close {
opacity: 1;
}
.no-transition {
-webkit-transition: none !important;
transition: none !important;
}
.noscroll {
overflow: hidden;
}
.hide {
display: none;
}
.invisible {
visibility: hidden;
}
</style>
<script src="http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
<!--[if lt IE 9]>
<script src="http://cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<main class="foundation">
<section>
<div class="morph-video-button">
<button type="button" class="video-btn" data-vimeo="106299509">Play</button>
</div>
</section>
<section>
<div class="morph-video-button">
<button type="button" class="video-btn" data-vimeo="106299507">Play</button>
</div>
</section>
<section>
<div class="morph-video-button">
<button type="button" class="video-btn" data-vimeo="106301490">Play</button>
</div>
</section>
<section>
<div class="morph-video-button">
<button type="button" class="video-btn" data-vimeo="106301494">Play</button>
</div>
</section>
</main>
<script src="//code.jquery.com/jquery.min.js"></script>
<script src="//f.vimeocdn.com/js/froogaloop2.min.js"></script>
<script>
(function($) {
/*
1. check for video player buttons (length)
2. if found, add single video container
3. add click event to video player buttons
4. open video container
5. remove scrollbars; save scroll position
6. inject vimeo video <iframe>
7. on video completion, remove <iframe>, add scrollbars
8. close video container
*/
$.videoPlayer = function(element, options) {
// ~~~~~ options ~~~~~
var defaults = {
onBeforeOpen : function() { return false; },
onAfterOpen : function() { return false; },
onBeforeClose : function() { return false; },
onAfterClose : function() { return false; }
};
var $element = $(element),
plugin = this;
plugin.settings = {};
plugin.isAnimating = false;
var transEndEventNames = {
'WebkitTransition': 'webkitTransitionEnd',
'MozTransition': 'transitionend',
'OTransition': 'oTransitionEnd',
'msTransition': 'MSTransitionEnd',
'transition': 'transitionend'
};
var transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ];
var support = { transitions : Modernizr.csstransitions };
var docElem = window.document.documentElement;
var video = {
player: [], // vimeo iframe container
$container: [], // the video.container DOM element, once injected on the page
container: '<div id="video-container"><div class="video-btn-close"></div></div>',
iframe: '<iframe id="video1" width="100%" height="100%" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen>',
url: '//player.vimeo.com/video/{id}?api=1&player_id=video1&autoplay=1&badge=0&byline=0&portrait=0&title=0',
activeBtn: [] // which button was clicked to trigger the video player?
}
plugin.init = function() {
plugin.settings = $.extend({}, defaults, options);
if(!plugin.settings.trigger.length){ return; }
// add video container
if(!video.$container.length){
video.$container = $(video.container).appendTo('body');
}
plugin.settings.trigger.on('touchstart click', toggle);
video.$container.on('touchstart click', '.video-btn-close', toggle);
}
/* PUBLIC
--------------------------------------------------------------------------- */
plugin.open = function() {
plugin.settings.onBeforeOpen();
};
plugin.close = function() {
plugin.settings.onBeforeClose();
player.remove();
toggle();
};
/* PRIVATE
--------------------------------------------------------------------------- */
// ~~~~~ Video Player ~~~~~~
var player = {
add: function(){
var id = video.activeBtn.find('.video-btn').data('vimeo');
$video_player = $(video.iframe).attr('src', video.url.replace('{id}', id)).appendTo(video.$container);
// Remove white flash when iframe loads
$video_player.addClass('invisible').on('load', function(){
$(this).removeClass('invisible');
});
// Vimeo API event listeners
video.player = $f($video_player.get(0));
video.player.addEvent('ready', function() {
$video_player.removeClass('invisible');
video.player.addEvent('finish', plugin.close);
});
},
remove: function(){
video.$container.find('iframe').remove();
}
}
// ~~~~~ Enable / Disable Scrolling ~~~~~
// trick to prevent scrolling when opening / closing button
var scroll = {
didScroll: false,
position: {},
lock: function() {
window.scrollTo( scroll.position ? scroll.position.x : 0, scroll.position ? scroll.position.y : 0 );
},
unlock: function() {
$(window).on('scroll', scroll.scrollHandler);
},
enable: function() {
$(window).off('scroll', scroll.lock);
scroll.unlock();
},
disable: function() {
$(window).off('scroll', scroll.scrollHandler);
$(window).on('scroll', scroll.lock);
},
scrollHandler: function() {
if( !scroll.didScroll ) {
scroll.didScroll = true;
setTimeout( function() { scroll.page(); }, 60 );
}
},
page: function() {
scroll.position = { x : window.pageXOffset || docElem.scrollLeft, y : window.pageYOffset || docElem.scrollTop };
scroll.didScroll = false;
}
};
scroll.unlock();
// ~~~~~ Overlay Transition ~~~~~
var onEndTransition = function(event){
if( support.transitions ) {
video.$container.off(transEndEventName);
}
plugin.isAnimating = false;
// ~~~~ callback ~~~~~
if(video.$container.is('.open')) {
plugin.settings.onAfterOpen();
player.add();
$('body').addClass('noscroll');
scroll.enable();
}
else {
plugin.settings.onAfterClose();
video.$container.removeClass('active').addClass('invisible').removeAttr('style');
scroll.enable();
}
}
// ~~~~~ Open / Close the Overlay ~~~~~
var toggle = function() {
var _this = this;
if( plugin.isAnimating ){ return false; }
// ~~~~ callback ~~~~~
if(video.$container.is('.open')) {
plugin.settings.onBeforeClose();
player.remove();
$('body').removeClass('noscroll');
scroll.disable();
}
else {
plugin.settings.onBeforeOpen();
// don't allow to scroll
scroll.disable();
}
plugin.isAnimating = true;
if(support.transitions) {
video.$container.on(transEndEventName, onEndTransition);
} else {
setTimeout(onEndTransition, 75);
}
var isVideoBtn = $(_this).is('.morph-video-button');
if(isVideoBtn){
video.activeBtn = $(_this);
video.$container.addClass('no-transition').css({ top: 'auto', left: 'auto', width: 'auto', height: 'auto' });
}
// add/remove class "open" to the video.container
setTimeout(function() {
if(isVideoBtn){
var offset = _this.getBoundingClientRect();
video.$container.css({ top: offset.top+'px', left: offset.left+'px', width:offset.width+'px', height: offset.height+'px' });
}
if(video.$container.is('.open')) {
video.$container.removeClass('open no-transition invisible');
}
else {
setTimeout( function() {
video.$container.addClass('open active').removeClass('no-transition invisible');
}, 25);
}
}, 25);
};
plugin.init();
};
// add the plugin to the jQuery.fn object
$.fn.videoPlayer = function(options) {
return this.each(function() {
if (undefined == $(this).data('videoPlayer')) {
var plugin = new $.videoPlayer(this, options);
$(this).data('videoPlayer', plugin);
}
});
}
})(jQuery);
$('.foundation').videoPlayer({
trigger: $('.morph-video-button')
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment