Skip to content

Instantly share code, notes, and snippets.

@CodeMyUI
Created January 3, 2020 21:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CodeMyUI/04ea796c88bf1397a74b6e36fe89688d to your computer and use it in GitHub Desktop.
Save CodeMyUI/04ea796c88bf1397a74b6e36fe89688d to your computer and use it in GitHub Desktop.
Egg Toggle Switch Morph 🍳 => πŸ₯š
<button class="switch">
<div class="switch__background"></div>
<svg class="egg" xmlns="http://www.w3.org/2000/svg">
<defs>
</defs>
<g class="egg__mainGroup">
<path class="egg__white -fried" d="M 67.254 7.183 C 67.254 7.183 42.919 -7.163 30.081 4.695 C 17.243 16.553 -16.134 54.902 9.313 84.817 C 19.285 93.772 29.336 96.076 43.999 96.349 C 73.363 99.935 75.215 91.591 94.133 61.592 C 113.051 31.593 67.254 7.183 67.254 7.183 Z" fill="#fefdfb"/>
<circle class="egg__yolk" cx="58.5" cy="43.5" r="25.5" fill="#facf37"/>
<ellipse class="egg__yolkShadow" cx="8" cy="13.5" rx="8" ry="13.5" transform="translate(72.557 39.322) rotate(60)" fill="#f7a721"/>
<path class="egg__yolkShadow" d="M690.365,785.646s-7.478,5.525-6.931,14.66" transform="translate(-643 -756)" fill="none" stroke="rgba(255,255,255,0.4)" stroke-linecap="round" stroke-width="3.5"/>
<path class="egg__yolkShadow" d="M701.481,782.382h0a21.465,21.465,0,0,0-6.366,1.112" transform="translate(-643 -756.381)" fill="none" stroke="rgba(255,255,255,0.4)" stroke-linecap="round" stroke-width="3.5" />
<path class="egg__white -middle -hidden" d="M 50.812 17.156 C 50.812 17.156 41.587 16.271 30.728 20.391 C 19.869 24.511 7.378 33.636 0.846 53.657 C -5.251 79.707 22.691 86.701 50.812 86.701 C 84.851 86.701 101.263 75.568 98.15 53.58 C 89.481 16.599 50.812 17.156 50.812 17.156 Z" />
<path class="egg__white -raw -hidden" d="M 40.95 0.03 C 35.525 -0.22 28.261 0.995 20.985 7.482 C 13.71 13.97 6.423 25.73 0.951 46.573 C -7.876 93.594 47.033 110.593 70.702 80.501 C 82.537 65.455 80.648 45.555 73.026 29.307 C 65.404 13.06 52.049 0.465 40.95 0.03 Z" />
</g>
</svg>
</button>
const switchButton = document.querySelector('.switch');
const switchBackground = switchButton.querySelector('.switch__background');
const egg = switchButton.querySelector('.egg');
const eggMainGroup = egg.querySelector('.egg__mainGroup');
const eggWhite = egg.querySelector('.egg__white.-fried');
const eggWhiteMiddle = egg.querySelector('.egg__white.-middle');
const eggWhiteRaw = egg.querySelector('.egg__white.-raw');
const yolk = egg.querySelector('.egg__yolk');
const yolkShadows = Array.from(egg.querySelectorAll('.egg__yolkShadow'));
const EGG_RAW_PATH = eggWhiteRaw.getAttribute('d');
const EGG_MIDDLE_PATH = eggWhiteMiddle.getAttribute('d');
const EGG_FRIED_PATH = eggWhite.getAttribute('d');
const SWITCH_PADDING = Number(
getComputedStyle(eggMainGroup).transform.split(',')[4]
);
const {
switchBackgroundCoords,
eggCoords,
eggWhiteCoords,
eggWhiteRawCoords,
eggWhiteMiddleCoords,
yolkCoords,
} = (() => {
const elements = { switchBackground, egg, eggWhite, eggWhiteRaw, eggWhiteMiddle, yolk };
return Object.keys(elements).reduce((previous, elementName) => {
return { ...previous, [`${elementName}Coords`]: elements[elementName].getBoundingClientRect() };
}, {});
})();
let isAnimating = false;
const toggleAnimationController = () => { isAnimating = !isAnimating; };
const toggleEggWhite = isOff => {
const scaleMiddle = 0.7;
const xMiddle = eggCoords.width / 2 - (eggWhiteCoords.width * scaleMiddle) / 2;
new TimelineLite()
.to(eggWhite, 0.25, {
x: xMiddle,
y: eggWhiteMiddleCoords.height / 4,
scale: scaleMiddle,
ease: Circ.easeIn,
attr: {
d: EGG_MIDDLE_PATH
}
})
.to(eggWhite, 0.25, {
x: isOff ? '0%' : eggCoords.width - eggWhiteRawCoords.width - SWITCH_PADDING * 2,
y: '0%',
scale: 1,
ease: Back.easeOut.config(1.7),
attr: {
d: isOff ? EGG_FRIED_PATH : EGG_RAW_PATH
}
});
};
const toggleYolk = isOff => {
const xMiddle = eggCoords.width / 2 - yolkCoords.width;
const xRaw =
eggCoords.width - eggWhiteRawCoords.width - yolkCoords.width - SWITCH_PADDING / 2;
new TimelineLite()
.to(yolk, 0.25, {
x: xMiddle,
y: 10,
ease: Circ.easeIn,
opacity: 0
})
.to(yolk, 0.25, {
x: isOff ? '0%' : xRaw,
fill: isOff ? '#facf37' : '#FDDD71',
y: isOff ? '0%' : 15,
opacity: 1,
ease: Back.easeOut.config(1.7)
});
};
const toggleYolkShadows = isOff => {
const toggleShadow = item => {
new TweenLite(item, 0.1, {
...isOff ? { delay: 0.35 } : {},
opacity: isOff ? 1 : 0,
})
}
yolkShadows.forEach(toggleShadow);
};
const toggleSwitchMovement = isOff => {
new TweenLite(switchButton, 0.4, {
x: isOff ? '0%' : '3vw',
ease: Power1.easeInOut
});
};
const toggleSwitchBackground = isOff => {
const x = isOff ? '0%' : eggCoords.width - switchBackgroundCoords.width;
new TweenMax(switchBackground, 0.5, {
x,
ease: Back.easeOut.config(1.7),
onComplete: toggleAnimationController,
});
};
const toggle = () => {
if (isAnimating) return;
toggleAnimationController();
const isOff = switchButton.classList.contains('-off');
switchButton.classList.toggle('-off');
toggleSwitchBackground(isOff);
toggleEggWhite(isOff);
toggleYolk(isOff);
toggleYolkShadows(isOff);
toggleSwitchMovement(isOff);
};
switchButton.addEventListener('click', toggle);
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
font-size: 62.5%;
}
html, body {
height: 100%;
}
body {
background: #f1f5fe;
display: flex;
justify-content: center;
align-items: center;
}
.switch {
background: transparent;
outline: none;
border: none;
cursor: pointer;
position: relative;
background: #3B3364;
border-radius: 100rem;
-webkit-tap-highlight-color: transparent;
}
.switch__background {
position: absolute;
top: 0;
left: 0;
background: #3B3364;
border-radius: 100rem;
width: 20rem;
height: 100%;
z-index: -1;
}
.egg {
height: 14.4rem;
width: 32.4rem;
}
.egg__mainGroup {
transform: translate(2.2rem, calc(2.2rem + 1.2px));
}
.egg__white.-hidden {
visibility: hidden;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment