Переходы с помощью анимации на GSAP

HTML
<header class="header">
<!-- image -->
<figure>
<img class="emily" src="http://deghq.com/yapp/front-labs/codepen-assets/emily.jpg" alt="">
</figure>
<!-- image mask -->
<i class="mask mask-left"></i>
<i class="mask mask-right"></i>
<i class="mask mask-top"></i>
<i class="mask mask-bottom"></i>
<!-- trigger -->
<span class="trigger" data-toggle="closed">
</span>
<!-- content -->
<div class="outer-wrapper">
<div class="outer">
<div class="inner">
<div class="container">
<div class="row">
<div class="col-1"> </div>
<div class="col-10 text-row">
<span id="type" class="title uppercase">Type</span>
<i class="line line-long">
<span></span>
</i>
</div>
<div class="col-1"> </div>
</div>
<div class="row">
<div class="col-1"> </div>
<div class="col-10 text-row">
<span id="georgia" class="subtitle">Georgia</span>
<i class="line line-short">
<span></span>
</i>
<span id="festival" class="title">festival</span>
</div>
<div class="col-1"> </div>
</div>
<div class="row">
<div class="col-1"> </div>
<div class="col-10 text-row">
<span id="year" class="title">2015</span>
<i class="line line-long">
<span></span>
</i>
<span id="size" class="subtitle">Size 78</span>
</div>
<div class="col-1"> </div>
</div>
</div>
</div>
</div>
</div>
</header>
SCSS
//FONTS
$arial: Arial, serif, sans-serif;
$georgia: Georgia, "Times New Roman", serif;
//MIXINS
// ADDS A BROWSER PREFIX TO THE PROPERTY
@mixin css3-prefix($property, $value) {
-webkit-#{$property}: #{$value};
-khtml-#{$property}: #{$value};
-moz-#{$property}: #{$value};
-ms-#{$property}: #{$value};
-o-#{$property}: #{$value};
#{$property}: #{$value};
}
// TRANSFORM
@mixin transform($params) {
@include css3-prefix('transform', $params);
}
//CSS FILTERS
@mixin filter($filter-type,$filter-amount) {
-webkit-filter: $filter-type+unquote('(#{$filter-amount})');
-moz-filter: $filter-type+unquote('(#{$filter-amount})');
-ms-filter: $filter-type+unquote('(#{$filter-amount})');
-o-filter: $filter-type+unquote('(#{$filter-amount})');
filter: $filter-type+unquote('(#{$filter-amount})');
}
// TRANSITION
@mixin transition($what: all, $length: 1s, $easing: ease-in-out) {
@include css3-prefix('transition', $what $length $easing);
}
$typekit-fonts: "", ""; // index [1, 2]
$typekit-fallbacks: $georgia, $arial;
@mixin font($weight: 400, $style: normal, $font: 1) {
$font-weight: $weight;
$font-style: $style;
// Translate Weight
@if ($weight == 100) or ($weight == thin) or ($weight == ultralight) {
$weight: 1;
}
@if ($weight == 200) or ($weight == extralight) {
$weight: 2;
}
@if ($weight == 300) or ($weight == light) {
$weight: 3;
}
@if ($weight == 400) or ($weight == normal) or ($weight == regular) {
$weight: 4;
}
@if ($weight == 500) or ($weight == medium) {
$weight: 5;
}
@if ($weight == 600) or ($weight == semibold) or ($weight == demi) {
$weight: 6;
}
@if ($weight == 700) or ($weight == bold) {
$weight: 7;
}
@if ($weight == 800) or ($weight == extrabold) {
$weight: 8;
}
@if ($weight == 900) or ($weight == black) or ($weight == heavy) {
$weight: 9;
}
// Translate Style
@if $style == normal {
$style: n;
}
@else if $style == italic {
$style: i;
}
// Assemble $font-family
$primary-font: nth($typekit-fonts, $font) + "-" + $style + $weight;
$secondary-font: nth($typekit-fonts, $font);
$fallback-fonts: nth($typekit-fallbacks, $font);
$font-family: quote($primary-font), quote($secondary-font), $fallback-fonts;
font-family: $font-family;
font-style: $font-style;
font-weight: $font-weight;
}
@mixin font-size($psd-font-size, $psd-line-height) {
font-size: $psd-font-size;
line-height: ($psd-line-height)/$psd-font-size;
}
//VARIABLES
//Black
$black-100: rgba(0,0,0,1);
$black-90: rgba(0,0,0,0.9);
$black-80: rgba(0,0,0,0.8);
$black-70: rgba(0,0,0,0.7);
$black-60: rgba(0,0,0,0.6);
$black-50: rgba(0,0,0,0.5);
$black-40: rgba(0,0,0,0.4);
$black-30: rgba(0,0,0,0.3);
$black-20: rgba(0,0,0,0.2);
$black-10: rgba(0,0,0,0.1);
//White
$white-100: rgba(255,255,255,1);
$white-90: rgba(255,255,255,0.9);
$white-80: rgba(255,255,255,0.8);
$white-70: rgba(255,255,255,0.7);
$white-60: rgba(255,255,255,0.6);
$white-50: rgba(255,255,255,0.5);
$white-40: rgba(255,255,255,0.4);
$white-30: rgba(255,255,255,0.3);
$white-20: rgba(255,255,255,0.2);
$white-10: rgba(255,255,255,0.1);
//Invisible
$transparent: rgba(255,255,255,0);
$yellow: #fbdb45;
//ANIMATIONS stuff
$hover: all, 0.2s, ease-in;
$slide: all, 0.3s, cubic-bezier(.55,0,.1,1);
$slide-slow: all, 0.5s, cubic-bezier(.55,0,.1,1);
$zoom: all, 1s, cubic-bezier(.55,0,.1,1);
$zoom-slow: all, 2.4s, cubic-bezier(.55,0,.1,1);
//GRID
$max-width: 970px; // set page max-width
$column-width: 8.3333%; // set column width
$gutter-width: 0%; // set gutter width
$maximum-columns: 12; // set max number of columns
@mixin clearfix {
zoom: 1;
&:before, &:after {
content: "";
display: table;
}
&:after {
clear: both;
}
}
@mixin border-box {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
@function columns($columns, $container-columns: $maximum-columns) {
$width: $columns * $column-width;
$container-width: $container-columns * $column-width;
@return percentage($width / $container-width);
}
@function gutter($container-columns: $maximum-columns, $gutter: $gutter-width) {
$container-width: $container-columns * $column-width + ($container-columns - 1) * $gutter-width;
@return percentage($gutter / $container-width);
}
@function newgutter($columns, $container-columns: $maximum-columns) {
$width: $columns * $column-width;
$container-width: $container-columns * $column-width;
@return percentage($width / $container-width / 2);
}
@function calcPercentage($a) {
@return percentage($a);
}
@mixin nesting {
padding: 0; // no padding so nested elements fit
& > div { // affect only immediate children
float: left;
margin-right: gutter;
@include border-box; // math is hard. let’s use border-box
}
}
@mixin row {
width: 100%; // make sure to fill its container
max-width: $max-width; // but no more than our max width
margin: 0 auto;
@include clearfix; // clear our floats
@include nesting; // add nesting styles to rows
}
@function offset-columns($columns) {
$margin:
$columns * $column-width + $columns * $gutter-width;
@return $margin;
}
@mixin offset($columns, $from-direction: left) {
@if $from-direction == left {
float: left;
margin-left: offset-columns($columns);
}
@if $from-direction == right {
float: right;
margin-right: offset-columns($columns);
}
}
@mixin last {
margin-right: 0;
float: right;
}
/*****************************************************/
.container {
margin-left: auto;
margin-right: auto;
width: $max-width;
@include border-box;
}
.row {
@include row();
}
$i: 1;
@while $i < ($maximum-columns + 1) {
.col-#{$i} {
width: columns($i);
padding-left: gutter();
padding-right: gutter();
}
$i: $i + 1;
}
//STYLE
.header {
position: relative;
height: 100%;
width: 100%;
overflow: hidden;
figure {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
img {
position: absolute;
top: 0;
left: 50%;
height: auto;
width: 110%;
@include transform(translateX(-50%));
}
}
}
.blur-emily {
@include filter(blur, 12px);
}
.mask {
position: absolute;
display: block;
background-color: lighten($black-100, 10%);
z-index: 2;
&.mask-top {
top: 0;
left: 0;
width: 100%;
height: 7%;
}
&.mask-bottom {
bottom: 0;
left: 0;
width: 100%;
height: 7%;
}
&.mask-left {
left: 0;
top: 0;
height: 100%;
width: 0;
}
&.mask-right {
right: 0;
top: 0;
height: 100%;
width: 0;
}
}
.blur-mask {
position: absolute;
display: block;
background-color: lighten($black-100, 10%);
z-index: 2;
&.mask-top {
top: 0;
left: 0;
width: 100%;
height: 5%;
}
&.mask-bottom {
bottom: 0;
left: 0;
width: 100%;
height: 5%;
}
&.mask-left {
left: 0;
top: 0;
height: 100%;
width: 50%;
}
&.mask-right {
right: 0;
top: 0;
height: 100%;
width: 50%;
}
}
.trigger {
position: absolute;
top: 10%;
right: 5%;
display: block;
width: 35px;
height: 35px;
border: 1px solid $white-100;
z-index: 4;
cursor: pointer;
&:before {
position: absolute;
content: "";
top: 0;
right: 0;
display: block;
width: 100%;
height: 100%;
@include transform(scale(0.5));
background-color: $yellow;
@include transition($slide);
}
&:hover {
&:before {
@include transform(scale(0.45));
}
}
}
.text-row {
padding: 15px 0;
text-align: left;
margin: 0 auto !important;
}
.title {
display: inline-block;
vertical-align: middle;
font-family: $georgia;
font-size: 78px;
line-height: 1em;
color: $white-100;
opacity: 0;
letter-spacing: 0.1em;
&.uppercase {
text-transform: uppercase;
}
}
.subtitle {
display: inline-block;
vertical-align: middle;
font-family: $georgia;
font-size: 23px;
line-height: 1em;
color: $white-100;
opacity: 0;
}
.line {
display: inline-block;
vertical-align: middle;
width: 100%;
max-width: 160px;
margin: 0 60px 0 30px;
span {
height: 6px;
display: block;
width: 0;
background-color: $yellow;
}
&.line-short {
max-width: 40px;
}
}
//GENERAL STUFF
html {
height: 100% !important;
width: 100%;
}
body {
height: 100%;
width: 100%;
@include font(300, normal, 2);
@include font-size(13px, 30px);
color: $white-100;
position: relative;
}
.main-wrapper {
height: 100%;
width: 100%;
position: relative;
}
/*TABLE POSITIONING STUFF*/
.outer-wrapper {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
.outer {
display: table;
height: 100% !important;
left: 0;
min-height: 100%;
position: absolute;
right: 0;
table-layout: fixed;
top: 0;
width: 100%;
z-index: 2;
.inner {
display: table-cell;
text-align: center;
vertical-align: middle;
width: 100%;
position: relative;
}
}
JS
Для работы потребуется jQuery и TweenMax//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js
//cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js
Сам скрипт/**
* DAnimation object is used to animate ease with bezier functions
* example: TweenMax.to($('selector'), 1.5, {left:"80%", ease: DAnimation.bezier(0.04,0.86,0.8,1)});
*
* Used: https://github.com/rdallasgray/bez
*/
var DAnimation = ({
start: 0,
bezier: function(p0, p1, p2, p3){
return DAnimation.polyBez([p0, p1], [p2, p3]);
},
polyBez: function(p1, p2) {
var A = [null, null], B = [null, null], C = [null, null],
bezCoOrd = function(t, ax) {
C[ax] = 3 * p1[ax], B[ax] = 3 * (p2[ax] - p1[ax]) - C[ax], A[ax] = 1 - C[ax] - B[ax];
return t * (C[ax] + t * (B[ax] + t * A[ax]));
},
xDeriv = function(t) {
return C[0] + t * (2 * B[0] + 3 * A[0] * t);
},
xForT = function(t) {
var x = t, i = 0, z;
while (++i < 14) {
z = bezCoOrd(x, 0) - t;
if (Math.abs(z) < 1e-3) break;
x -= z / xDeriv(x);
}
return x;
};
return function(t) {
return bezCoOrd(xForT(t), 1);
}
}
});
//CUSTOM JS CODE
(function ($) {
'use strict';
//VIEWPORT
var w = $( window );
//ANIMATION
var animationTrigger = $('.trigger');
var maskTop = $('.mask-top');
var maskBottom = $('.mask-bottom');
var maskLeft = $('.mask-left');
var maskRight = $('.mask-right');
var emily = $('.emily');
var lineLong = $('.line-long').find(' span ');
var lineShort = $('.line-short').find(' span ');
var type = $('#type');
var georgia = $('#georgia');
var festival = $('#festival');
var year = $('#year');
var size = $('#size');
var main = {
init: function () {
var self = this;
//GSAP ANIMATE
main.animate();
},
//GSAP ANIMATION
animate: function (){
//OPEN
function openAnimation() {
TweenMax.to(maskTop, 1.4,
{
height: "10%", ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(maskBottom, 1.4,
{
height: "10%", ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(maskLeft, 1.4,
{
width: "40%", ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(maskRight, 1.2,
{
//width: "20%", ease: Expo.easeInOut
width: "20%", ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(emily, 1.8,
{
scale: 1.1, top: "-5%", left: "55%", ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(lineLong, 1,
{
width: "100%", delay: 0.4, ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(lineShort, 1,
{
width: "100%", delay: 1, ease: Power3.easeOut
}
);
TweenMax.fromTo(type, 1.8,
{
x: -200, opacity: 0
},
{
x: 0, opacity: 1, delay: 0.8, ease: Power3.easeOut
}
);
TweenMax.fromTo(year, 1.8,
{
x: -200, opacity: 0
},
{
x: 0, opacity: 1, delay: 0.8, ease: Power3.easeOut
}
);
TweenMax.fromTo(georgia, 2,
{
x: -200, opacity: 0
},
{
x: 0, opacity: 1, delay: 1, ease: Power3.easeOut
}
);
TweenMax.fromTo(festival, 1.8,
{
x: 200, opacity: 0
},
{
x: 0, opacity: 1, delay: 0.8, ease: Power3.easeOut
}
);
TweenMax.fromTo(size, 2,
{
x: 200, opacity: 0
},
{
x: 0, opacity: 1, delay: 1, ease: Power3.easeOut
}
);
}
//CLOSE
function closeAnimation() {
TweenMax.to(maskTop, 1,
{
height: "7%", ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(maskBottom, 1,
{
height: "7%", ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(maskLeft, 1,
{
width: 0, ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(maskRight, 1,
{
width: 0, ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(emily, 1.8,
{
scale: 1, top: 0, left: "50%", delay: 0., ease: Expo.easeOut
}
);
TweenMax.to(lineLong, 0.8,
{
width: 0, delay: 0.4, ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.to(lineShort, 0.8,
{
width: 0, delay: 0.4, ease: DAnimation.bezier(0.930, 0.035, 0.350, 0.815)
}
);
TweenMax.fromTo(type, 1,
{
x: 0, opacity: 1
},
{
x: -200, opacity: 0, ease: Power3.easeIn
}
);
TweenMax.fromTo(year, 1,
{
x: 0, opacity: 1
},
{
x: -200, opacity: 0, ease: Power3.easeIn
}
);
TweenMax.fromTo(georgia, 0.6,
{
x: 0, opacity: 1
},
{
x: -200, opacity: 0, ease: Power3.easeIn
}
);
TweenMax.fromTo(festival, 1,
{
x: 0, opacity: 1
},
{
x: 200, opacity: 0, ease: Power3.easeIn
}
);
TweenMax.fromTo(size, 0.6,
{
x: 0, opacity: 1
},
{
x: 200, opacity: 0, ease: Power3.easeIn
}
);
}
animationTrigger.click(function(){
if($(this).attr('data-toggle') == 'closed') {
$(this).attr('data-toggle', 'opened');
openAnimation();
}
else if($(this).attr('data-toggle', 'opened')) {
$(this).attr('data-toggle', 'closed');
closeAnimation();
}
});
}
};
$(window).resize(function () {
});
return main.init();
}($));