<section class="demo">
<div class="demo__menu" id="menu">
<button type="button" class="demo__item" data-i="0">A</button>
<button type="button" class="demo__item" data-i="1">B</button>
<button type="button" class="demo__item" data-i="2">C</button>
<button type="button" class="demo__item" data-i="3">D</button>
<button type="button" class="demo__item" data-i="4">E</button>
<button type="button" class="demo__core" id="core">Menu</button>
</div>
</section>.demo {
min-height: 100dvh;
display: grid;
place-items: center;
background: #08080a;
font-family: "Helvetica Neue", system-ui, sans-serif;
}
.demo__menu {
position: relative;
width: 220px;
height: 220px;
}
.demo__core,
.demo__item {
position: absolute;
border: 1px solid rgba(255, 255, 255, 0.1);
background: #121216;
color: #f4f4f2;
cursor: pointer;
}
.demo__core {
left: 50%;
top: 50%;
width: 72px;
height: 72px;
margin: -36px 0 0 -36px;
border-radius: 50%;
font: 11px/1 "Helvetica Neue", system-ui, sans-serif;
letter-spacing: 0.16em;
text-transform: uppercase;
z-index: 2;
}
.demo__item {
left: 50%;
top: 50%;
width: 42px;
height: 42px;
margin: -21px 0 0 -21px;
border-radius: 50%;
font: 12px/1 "Helvetica Neue", system-ui, sans-serif;
}const items = gsap.utils.toArray(".demo__item");
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
let open = false;
const RADIUS = 84;
function setOpen(next) {
open = next;
items.forEach(function (item, index) {
const angle = (index / items.length) * Math.PI * 2 - Math.PI / 2;
gsap.to(item, {
x: open ? Math.cos(angle) * RADIUS : 0,
y: open ? Math.sin(angle) * RADIUS : 0,
scale: open ? 1 : 0.4,
opacity: open ? 1 : 0.35,
pointerEvents: open ? "auto" : "none",
duration: reduce ? 0.15 : 0.55,
ease: "back.out(1.6)",
delay: reduce ? 0 : index * 0.03,
});
});
}
document.querySelector("#core").addEventListener("click", function () {
setOpen(!open);
});
gsap.set(items, { scale: 0.4, opacity: 0.35 });
gsap.delayedCall(0.35, function () { setOpen(true); });