- var w=400,h=400;
body
main
svg#svg(width=w, height=h)
circle#circle.circles(cx=0, cy=0, r=0, fill="#FD554F")
circle#circle.circles(cx=0, cy=0, r=0, fill="#FD554F")
circle#circle.circles(cx=0, cy=0, r=0, fill="#FD554F")
circle#circle.circles(cx=0, cy=0, r=0, fill="#FD554F")
circle#circle.circles(cx=0, cy=0, r=0, fill="#FD554F")
text.text(
x=w / 2,
y=h / 2,
text-anchor="middle",
stroke="red",
stroke-width="1px",
alignment-baseline="middle",
style="opacity: 0",
dy="3px"
) 😍
text.text(
x=w / 2,
y=h / 2,
text-anchor="middle",
stroke="red",
stroke-width="1px",
alignment-baseline="middle",
style="opacity: 0",
dy="3px"
) 👌
text.text(
x=w / 2,
y=h / 2,
text-anchor="middle",
stroke="red",
stroke-width="1px",
alignment-baseline="middle",
style="opacity: 0",
dy="3px"
) 😳
text.text(
x=w / 2,
y=h / 2,
text-anchor="middle",
stroke="red",
stroke-width="1px",
alignment-baseline="middle",
style="opacity: 0",
dy="3px"
) 👀
text.text(
x=w / 2,
y=h / 2,
text-anchor="middle",
stroke="red",
stroke-width="1px",
alignment-baseline="middle",
style="opacity: 0",
dy="3px"
) 🤩
circle#menu(
cx=w / 2,
cy=h / 2,
fill="#FD554F",
r=0,
style="cursor: pointer"
)
g#icon(
transform="translate(188.5,188.5)",
style="opacity: 0; transform-origin: 7px 7px; cursor: pointer"
)
path(
d="M12 5.5V19.5",
stroke="#fff",
stroke-width="3",
stroke-linecap="round",
stroke-linejoin="round"
)
path(
d="M5 12.5H19",
stroke="#fff",
stroke-width="3",
stroke-linecap="round",
stroke-linejoin="round"
)
#desc Draw Some Circles
br
#equation1.eq
#equation2.eq
#options
button#left.button <
#step 0
button#right.button >
View Compiled
body {
background: #192734;
display: flex;
font-family: Consolas, monospace;
justify-content: center;
flex-direction: column;
}
#svg {
margin: 0 auto;
display: block;
background: #192734;
}
#options {
margin-top: 20px;
display: flex;
align-items: center;
justify-content: center;
#step {
margin: 0 5px;
color: white;
}
}
#desc,
.eq {
color: white;
text-align: center;
font-size: 20px;
font-weight: bold;
width: 70%;
margin: 0 auto;
display: block;
}
View Compiled
const $ = (x) => document.querySelector(x);
let circle = $("#circle"),
step = $("#step"),
eq1 = $("#equation1"),
eq2 = $("#equation2"),
desc = $("#desc"),
w = 400,
h = 400,
stepNo = 0;
function clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == "37") {
stepNo--;
stepNo = clamp(stepNo, 0, 4);
step.innerText = stepNo;
animate();
} else if (e.keyCode == "39") {
stepNo++;
stepNo = clamp(stepNo, 0, 4);
step.innerText = stepNo;
animate();
}
}
$("#left").addEventListener("click", () => {
stepNo--;
stepNo = clamp(stepNo, 0, 4);
step.innerText = stepNo;
animate();
});
$("#right").addEventListener("click", () => {
stepNo++;
stepNo = clamp(stepNo, 0, 4);
step.innerText = stepNo;
animate();
});
gsap.defaults({
ease: Elastic.easeOut.config(0.1, 0.5),
duration: 0.9
});
gsap.to(".circles", { r: 15 });
animate();
function eqFadeIn() {
gsap.fromTo(
".eq",
{ opacity: 0, y: "100%" },
{
opacity: 1,
y: "0%"
}
);
}
function animate() {
switch (stepNo) {
case 0: {
gsap.to(".circles", { cx: 0, cy: 0, stagger: 0.1 });
desc.innerText = "Draw Some Circles";
eqFadeIn();
eq1.innerText = "(use left and right arrows to goto next step)👇";
eq2.innerText = "";
break;
}
case 1: {
gsap.to(".circles", { cx: w / 2, cy: h / 2, stagger: 0.1 });
desc.innerText = "Center the Circles";
eqFadeIn();
eq1.innerText = "x = width/2";
eq2.innerText = "y = height/2";
break;
}
case 2: {
let angStep = (2 * Math.PI) / 5;
gsap.to(".circles", {
cx: (idx) => w / 2 + Math.cos(idx * angStep),
cy: (idx) => h / 2 + Math.sin(idx * angStep),
stagger: 0.1
});
desc.innerText = "Add sin and cos with angles 0 to 2*PI for each circle";
eqFadeIn();
eq1.innerText = "x = width/2 + Math.cos(angle)";
eq2.innerText = "y = height/2 + Math.sin(angle)";
break;
}
case 3: {
let angStep = (2 * Math.PI) / 5;
gsap.to("#menu", { r: 0 });
gsap.to("#icon", { rotate: 0, opacity: 0 });
gsap.to(".text", { opacity: 0 });
gsap.to(".circles", {
cx: (idx) => w / 2 + 50 * Math.cos(idx * angStep),
cy: (idx) => h / 2 + 50 * Math.sin(idx * angStep),
stagger: 0.1
});
desc.innerText = "Add a multiplier/radius";
eqFadeIn();
eq1.innerText = "x = width/2 + 50*Math.cos(angle)";
eq2.innerText = "y = height/2 + 50*Math.sin(angle)";
break;
}
case 4: {
let angStep = (2 * Math.PI) / 5;
gsap.to("#menu", { r: 25 });
gsap.to("#icon", { rotate: 360 - 45, opacity: 1 });
gsap.to(".circles", {
cx: (idx) => w / 2 + 70 * Math.cos(idx * angStep),
cy: (idx) => h / 2 + 70 * Math.sin(idx * angStep),
stagger: 0.1
});
gsap.to(".text", {
opacity: 1,
x: (idx) => 70 * Math.cos(idx * angStep),
y: (idx) => 70 * Math.sin(idx * angStep),
stagger: 0.1
});
desc.innerText =
"Tada 🎉 You've got a radial menu! ✨ Try clicking on the center button";
eqFadeIn();
eq1.innerText = "x = width/2 + 70*Math.cos(angle)";
eq2.innerText = "y = height/2 + 70*Math.sin(angle)";
break;
}
}
}
function toggleOpen() {
isOpen = !isOpen;
if (isOpen) {
let angStep = (2 * Math.PI) / 5;
gsap.to("#icon", { rotate: 360 - 45, opacity: 1 });
gsap.to(".circles", {
cx: (idx) => w / 2 + 70 * Math.cos(idx * angStep),
cy: (idx) => h / 2 + 70 * Math.sin(idx * angStep),
stagger: 0.05
});
gsap.to(".text", {
opacity: 1,
x: (idx) => 70 * Math.cos(idx * angStep),
y: (idx) => 70 * Math.sin(idx * angStep),
stagger: 0.05
});
eqFadeIn();
eq1.innerText = "x = width/2 + 70*Math.cos(angle)";
eq2.innerText = "y = height/2 + 70*Math.sin(angle)";
} else {
gsap.to("#icon", { rotate: 360, opacity: 1 });
gsap.to(".circles", {
cx: (idx) => w / 2,
cy: (idx) => h / 2,
stagger: 0.05
});
gsap.to(".text", {
x: (idx) => 0,
y: (idx) => 0,
stagger: 0.05
});
eqFadeIn();
eq1.innerText = "x = width/2";
eq2.innerText = "y = height/2";
}
}
let isOpen = true;
$("#menu").addEventListener("click", () => {
toggleOpen();
});
$("#icon").addEventListener("click", () => {
toggleOpen();
});
This Pen doesn't use any external CSS resources.