<h2>fancyBox - Morphing modal overlay</h2>
<div style="display: none;" id="hidden-content">
<h2>Hello!</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ergo, inquit, tibi Q. At hoc in eo M. Non semper, inquam; Duo Reges: constructio interrete. Bonum liberi: misera orbitas. </p>
<p>Que Manilium, ab iisque M. De illis, cum volemus. Hunc vos beatum; Bestiarum vero nullum iudicium puto. </p>
<p>Itaque fecimus. Ut pulsi recurrant? Quis non odit sordidos, vanos, leves, futtiles? Recte, inquit, intellegis. Verum hoc idem saepe faciamus. </p>
</div>
<a data-morphing class="btn" data-src="#hidden-content" href="javascript:;">Open demo</a>
/* Styling for element used in example */
#hidden-content {
margin: 0;
position: relative;
background: transparent;
color: #fff;
width: 50vw;
padding: 5vh 10vw;
line-height: 2;
z-index: 3;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
#hidden-content a {
color: #fff;
}
/* fancyMorph */
.morphing-btn-wrap {
text-align: center;
display: inline-block;
position: relative;
}
.morphing-btn {
-webkit-transition: color 0.2s 0.3s, width 0.2s 0s;
-moz-transition: color 0.2s 0.3s, width 0.2s 0s;
-o-transition: color 0.2s 0.3s, width 0.2s 0s;
transition: color 0.2s 0.3s, width 0.2s 0s;
white-space: nowrap;
will-change: width, color;
transform: translate3d(0, 0, 0);
}
.morphing-btn_circle {
color: transparent;
padding-left: 0;
padding-right: 0;
width: 35.6px !important; /* Override inline style rule */
-webkit-transition: color 0.2s 0s, width .3s 0.2s;
-moz-transition: color 0.2s 0s, width .3s 0.2s;
-o-transition: color 0.2s 0s, width .3s 0.2s;
transition: color 0.2s 0s, width .3s 0.2s;
}
.morphing-btn-clone {
position: fixed;
background: #FF6666;
width: 3em;
height: 3em;
border-radius: 50%;
z-index: 3;
font-size: 0.875em;
-webkit-transition: all 0.6s cubic-bezier(.65,.05,.36,1);
-moz-transition: all 0.6s cubic-bezier(.65,.05,.36,1);
-o-transition: all 0.6s cubic-bezier(.65,.05,.36,1);
transition: all 0.6s cubic-bezier(.65,.05,.36,1);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.morphing-btn-clone_visible {
-webkit-transform : scale(1) !important;
-moz-transform : scale(1) !important;
-ms-transform : scale(1) !important;
-o-transform : scale(1) !important;
transform : scale(1) !important;
}
.morphing-close {
position: fixed;
top: 5%;
right: 5%;
background: rgba(0,0,0,0.2);
text-indent: -9999px;
width: 50px;
height: 50px;
border-radius: 50%;
border: 0;
overflow: hidden;
transition: background-color 0.2s ease 0s, transform .2s ease-in-out;;
z-index: 99993;
cursor: pointer;
outline: none;
}
.morphing-close:active {
margin-top: -1px;
}
.morphing-close:before,
.morphing-close:after {
content: "";
position: absolute;
left: 12px;
top: 24px;
width: 26px;
height: 1.5px;
background: #fff;
}
.morphing-close:before {
-ms-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.morphing-close:after {
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
var Morphing = function( $btn ) {
this._init( $btn );
};
Morphing.prototype._init = function( $btn ) {
var that = this;
that.$btn = $btn.width( $btn.width() ).addClass('morphing-btn');
// Add wrapping element and set initial width used for positioning
$btn.wrap(function() {
var $wrap = $('<div class="morphing-btn-wrap"></div>');
$wrap.width( $(this).outerWidth( true ) );
return $wrap;
});
that.$clone = $('<div />')
.hide()
.addClass('morphing-btn-clone')
.insertAfter( $btn );
$btn.on('click', function(e) {
e.preventDefault();
that.open();
});
};
Morphing.prototype.open = function() {
var that = this;
if ( that.$btn.hasClass('morphing-btn_circle') ) {
return;
}
// First, animate button to the circle
that.$btn.one("transitionend.fm webkitTransitionEnd.fm oTransitionEnd.fm MSTransitionEnd.fm", function(e) {
if ( e.originalEvent.propertyName !== 'width' ) {
return;
}
$(this).off(".fm");
that._animate();
});
that.$btn.width( that.$btn.width() ).addClass('morphing-btn_circle');
};
Morphing.prototype._animate = function() {
var that = this;
var $btn = that.$btn;
var $clone = that.$clone;
var scale = this._retrieveScale( $btn );
var pos = $btn[0].getBoundingClientRect();
$clone.css({
top : pos.top + $btn.outerHeight() * 0.5 - ( $btn.outerHeight() * scale * 0.5 ),
left : pos.left + $btn.outerWidth() * 0.5 - ( $btn.outerWidth() * scale * 0.5 ),
width : $btn.outerWidth() * scale,
height : $btn.outerHeight() * scale,
transform : 'scale(' + 1 / scale + ')'
});
$clone.one("transitionend.fm webkitTransitionEnd.fm oTransitionEnd.fm MSTransitionEnd.fm", function(e) {
$(this).off(".fm");
// Open fancyBox
$.fancybox.open({ src : $btn.data('src') || $btn.attr('href') }, {
infobar : false,
buttons : false,
smallBtn : false,
touch : false,
margin : 0,
onInit : function( instance ) {
instance.$refs.slider_wrap.append('<button class="morphing-close" data-fancybox-close>X</button>');
instance.$refs.bg.remove();
},
afterClose : function() {
that.close();
}
});
});
// Trigger expanding of the cloned element
$clone.show().addClass('morphing-btn-clone_visible');
};
Morphing.prototype.close = function() {
var that = this;
var $btn = that.$btn;
var $clone = that.$clone;
var scale = that._retrieveScale( $btn );
var pos = $btn[0].getBoundingClientRect();
$clone.css({
top : pos.top + $btn.outerHeight() * 0.5 - ( $btn.outerHeight() * scale * 0.5 ),
left : pos.left + $btn.outerWidth() * 0.5 - ( $btn.outerWidth() * scale * 0.5 ),
width : $btn.outerWidth() * scale,
height : $btn.outerHeight() * scale,
transform : 'scale(' + ( 1 / scale ) + ')'
});
$clone.one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) {
$clone.hide();
$btn.removeClass('morphing-btn_circle');
});
$clone.removeClass('morphing-btn-clone_visible');
};
Morphing.prototype._retrieveScale = function( $btn ) {
var rez = Math.max( $(window).height() * 3 / $btn.height() , $(window).width() * 3 / $btn.width() );
return rez;
};
$.fn.fancyMorph = function( duration ) {
this.each(function() {
var $this = $(this);
if ( !$this.data('morphing') ) {
$this.data('morphing', new Morphing( $this ));
}
});
return this;
};
$("[data-morphing]").fancyMorph();