Animation
by maxell4o
HTML
<div class="box">
<div class="pin"></div>
<div class="menu">
<div class="link">link 1</div>
<div class="link">link text 2</div>
<div class="link">link 3</div>
</div>
</div>
SCSS
.box{
position: fixed;
top: 100px;
right: 0;
cursor: grab;
&:not(.open) .pin {
transform: translate(-100%, -50%);
}
&.open .menu {
transform: translate(-100%, -50%);
}
}
.pin {
width: 50px;
height: 50px;
margin-left: 3px;
background-color: red;
position: absolute;
transition: transform 500ms;
transition-timing-function: cubic-bezier(0,.5,.1,1.2);
transform: translate(0, -50%);
z-index: 2;
}
.menu {
margin-left: 5px;
position: absolute;
transition: transform 500ms;
transform: translate(0, -50%);
transition-timing-function: cubic-bezier(0,.5,.1,1.2);
z-index: 1;
.link {
color: #fff;
line-height: 40px;
border-radius: 20px;
background: black;
margin: 5px 10px;
padding: 0 10px;
min-width: 100px;
white-space: nowrap;
}
}
JavaScript
let box = document.querySelector('.box');
let menu = box.querySelector('.menu');
let active = false;
let currentY;
let initialY;
let yOffset = window.innerHeight / 2;
const getClientY = e => (e.type === 'touchmove' || e.type === 'touchmove') ? e.touches[0].clientY : e.clientY;
const setPosition = (y, el) => el.style.top = y+'px';
box.addEventListener('click', e => {
e.currentTarget.classList.toggle('open');
});
document.addEventListener("touchstart", dragStart, false);
document.addEventListener("touchend", dragEnd, false);
document.addEventListener("touchmove", drag, false);
document.addEventListener("mousedown", dragStart, false);
document.addEventListener("mouseup", dragEnd, false);
document.addEventListener("mousemove", drag, false);
setPosition(yOffset, box);
function dragStart(e) {
initialY = getClientY(e) - yOffset;
active = e.target.closest('.box') === box;
}
function dragEnd(e) {
initialY = currentY;
active = false;
}
function drag(e) {
if (active) {
e.preventDefault();
let minY = menu.clientHeight / 2;
let maxY = window.innerHeight - (menu.clientHeight / 2);
currentY = getClientY(e) - initialY;
yOffset = currentY <= minY ? minY : currentY >= maxY ? maxY : currentY;
setPosition(yOffset, box);
}
}