JSFiddle - React, Tailwind, and code Playground
by Lazaro Contreras
HTML
<div id="menu">
<svg>
<path fill="white">
<animate attributeName="d" dur="0.15s"/>
</path>
</svg>
</div>
CSS
* {
margin: 0;
}
html,
body {
background: #333639;
}
div#menu {
display: inline-block;
width: 300px;
height: 100vh;
background: transparent;
transform: translateX(-250px);
position: relative;
transition: all 0.15s linear;
}
div#menu.active {
transform: none;
}
div#menu svg {
width: 100%;
height: 100%;
overflow: unset;
}
JavaScript
var w = menu.offsetWidth,
h = menu.offsetHeight,
open = false,
anioff = false
var svg = menu.querySelector("svg");
svg.setAttribute("viewbox", "0 0 " + w + " " + h);
var ani = menu.querySelector("svg path animate");
var box = menu.querySelector("svg path");
box.setAttribute("d", "M 0 0 L0 " + h + " L" + w + " " + h + " Q " + w + " " + (h / 2) + " " + w + " 0 Z");
menu.addEventListener("touchstart", () => {
window.addEventListener("touchmove", move);
})
window.addEventListener("touchend", () => {
terAni("touchmove");
if (anioff) {
menu.classList.toggle("active");
open = !open
anioff = !anioff
}
})
menu.addEventListener("mousedown", () => {
window.addEventListener("mousemove", move);
})
window.addEventListener("mouseup", () => {
terAni("mousemove");
if (anioff) {
menu.classList.toggle("active");
open = !open
anioff = !anioff
}
})
function terAni(s) {
window.removeEventListener(s, move);
box.setAttribute("d", "M 0 0 L0 " + h + " L" + w + " " + h + " Q " + w + " " + (h / 2) + " " + w + " 0 Z");
ani.beginElement();
ani.setAttribute("to", "M 0 0 L0 " + h + " L" + w + " " + h + " Q " + w + " " + (h / 2) + " " + w + " 0 Z");
setTimeout(() => {
ani.setAttribute("from", "M 0 0 L0 " + h + " L" + w + " " + h + " Q " + w + " " + (h / 2) + " " + w + " 0 Z");
}, 150);
}
function move(e) {
let x = e.clientX,
y = e.clientY;
if (open) {
if (x < w && x > w * 0.5) {
anioff = false
box.setAttribute("d", "M 0 0 L0 " + h + " L" + w + " " + h + " Q " + x + " " + y + " " + w + " 0 Z");
ani.setAttribute("from", "M 0 0 L0 " + h + " L" + w + " " + h + " Q " + x + " " + y + " " + w + " 0 Z");
} else if (x < w) {
box.setAttribute("d", "M 0 0 L0 " + h + " L" + w + " " + h + " Q " + w * 0.5 + " " + y + " " + w + " 0 Z");
ani.setAttribute("from", "M 0 0 L0 " + h + " L" + w + " " + h + " Q " + w * 0.5 + " " + y + " " + w + " 0 Z");
anioff = true
}
} else {
x += 250
...