Skip to content

Instantly share code, notes, and snippets.

@dennyferd
Created November 5, 2022 08:57
Show Gist options
  • Save dennyferd/a5974f662390ed23642be29412492339 to your computer and use it in GitHub Desktop.
Save dennyferd/a5974f662390ed23642be29412492339 to your computer and use it in GitHub Desktop.
Snap.svg Menu animation
<!-- Cette source est librement inspirée du bon article tympanus https://tympanus.net/codrops/2014/12/15/elastic-svg-elements/
-->
<nav class="nav">
<button class="nav-toggle"><span>Menu</span></button>
<ul class="nav-menu">
<li>Home</li>
<li>Favorites</li>
</ul>
<div class="nav-morph"
data-open="M 300,-1.9235101 C 947.48798,352.73374 368.08761,564.6745 301.42857,1052.3622"
data-close="M 300,-1.9235101 C -43.940589,374.16231 223.80189,644.6745 301.42857,1052.3622">
<svg width="100%" height="100%" viewBox="0 0 600 800" preserveAspectRatio="none">
<path fill="none" d="M 300,-1.9235101 C 304.63084,565.59088 299.51618,538.96021 301.42857,1052.3622"/>
</svg>
</div>
</nav>
// Snap.svg http://snapsvg.io/
function configToggleAnimation() {
var toggle = document.querySelector('.nav-toggle'),
nav = document.querySelector('.nav'),
snap = Snap(document.querySelector('.nav-morph svg')),
nav_morph = document.querySelector('.nav-morph'),
path = snap.select('path'),
reset = path.attr('d'),
open = nav_morph.getAttribute('data-open'),
close = nav_morph.getAttribute('data-close'),
speed = 250,
speed_back = 800,
easing = mina.easeinout,
easing_back = mina.elastic,
isOpen = false;
toggle.addEventListener('click', function() {
// si ouvert on ferme
if (isOpen) {
path.stop().animate({
'path': close
}, speed, easing, function() {
path.animate({
'path': reset
}, speed_back, easing_back);
isOpen = false;
});
nav.classList.remove('nav--open');
} else {
path.stop().animate({
'path': open
}, speed, easing, function() {
path.animate({
'path': reset
}, speed_back, easing_back);
isOpen = true;
});
nav.classList.add('nav--open');
}
});
}
function initialize() {
configToggleAnimation();
}
document.addEventListener('DOMContentLoaded', initialize);
<script src="https://cdn.jsdelivr.net/snap.svg/0.4.1/snap.svg-min.js"></script>
@import "compass";
$menu-color:#F06292;
* {
@include box-sizing("border-box");
}
html,
body {
margin: 0;
}
body {
font-family: "Roboto", sans-serif;
}
.nav {
position: fixed;
width: 300px;
top: 3em;
bottom: 3em;
left: 0;
z-index: 100;
overflow: hidden;
transform: translate3d(-150px, 0, 0);
transition: transform 0.6s;
}
.nav-menu {
position: relative;
list-style: none;
width: calc(100% + 25px);
height: 100%;
padding: 0 140px 2em 25px;
overflow-y: auto;
z-index: 100;
}
.nav--open {
transform: translate3d(0, 0, 0);
.nav-toggle span {
opacity: 0;
}
.nav-toggle::before {
transform: rotate3d(0, 0, 1, 45deg);
}
.nav-toggle::after {
transform: rotate3d(0, 0, 1, -45deg);
}
}
.nav-morph {
position: absolute;
width: 240px;
height: 100%;
top: 0;
right: 0;
}
.nav-morph svg path {
stroke: $menu-color;
stroke-width: 5px;
}
/* NAV TOGGLE */
.nav-toggle {
position: absolute;
top: 3px;
right: 70px;
width: 30px;
height: 24px;
padding: 0;
background: transparent;
border: none;
cursor: pointer;
outline: none;
z-index: 2000;
&::before,
&::after {
content: '';
position: absolute;
height: 2px;
width: 100%;
left: 0;
top: 50%;
background: $menu-color;
transform-origin: 50% 50%;
transition: transform 0.25s;
}
&::before {
transform: translate3d(0, -10px, 0);
}
&::after {
transform: translate3d(0, 10px, 0);
}
span {
position: absolute;
width: 100%;
height: 2px;
background: $menu-color;
left: 0;
overflow: hidden;
text-indent: 200%;
transition: opacity 0.25s;
}
}
<link href="https://fonts.googleapis.com/css?family=Roboto:400,300" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment