Пишем SVG c HTML:
Пишем наш стиль:
Пишем js:
Смотрим наш результат:
HTML:
<div class="btn">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 32">
<g id="Layer_2" data-name="Layer 2">
<g id="icon-container">
<g id="pumpkin">
<g id="p-back">
<path d="M27 7c-3-2-6-2-10-2S10 5 7 7l10 1 10-1z" fill="#ff931e" />
<path d="M27 8c-3-2-6-2-10-2S10 6 7 8l10 1 10-1z" fill="#3e1c11" />
</g>
<g id="p-face">
<path d="M27 7L17 8 7 7c-4 2-7 6-7 11 0 10 8 14 17 14s17-4 17-14c0-5-3-9-7-11z" fill="#ff931e" />
<path d="M28 9a12 12 0 00-3-2l-1 1a12 12 0 013 2 14 14 0 013 9 11 11 0 01-4 8 17 17 0 01-4 3 23 23 0 01-3 1 9 9 0 01-1 1 19 19 0 009-4 12 12 0 004-4 12 12 0 001-5 14 14 0 00-4-10z" fill="#f17f24" />
<path d="M21 30a10 10 0 003-3 17 17 0 001-8 21 21 0 00-1-8 12 12 0 00-2-3h-1a13 13 0 012 3 25 25 0 011 8 22 22 0 010 3 15 15 0 01-1 4 10 10 0 01-5 6l1-1a9 9 0 002-1z" fill="#f17f24" />
<path d="M8 27a11 11 0 01-4-8 13 13 0 014-9 12 12 0 013-2l-1-1a12 12 0 00-3 2 14 14 0 00-4 10 11 11 0 001 5 12 12 0 004 4 17 17 0 002 2 21 21 0 002 1 26 26 0 006 1 33 33 0 01-5-2 17 17 0 01-5-3z" fill="#f17f24" />
<path d="M13 26a21 21 0 01-1-7 28 28 0 011-8 14 14 0 011-3h-1a13 13 0 00-1 3 23 23 0 00-2 8 18 18 0 002 7 11 11 0 002 4 8 8 0 004 2 10 10 0 01-5-6z" fill="#f17f24" />
<path id="p-mouth1" d="M28 21v1l-2 2v-2a23 23 0 01-4 1l-1 2h-2v-2h-2v2h-3v-2l-4-1v2H8l-1-2-3-1c15 19 26-1 26-1a15 15 0 01-2 1z" fill="#3e1c11" />
<circle cx="11.1" cy="15" r="2.9" fill="#3e1c11" />
<circle cx="22.9" cy="15" r="2.9" fill="#3e1c11" />
<path fill="#3e1c11" d="M17 15l-3 5h6l-3-5z" />
</g>
<g id="p-top">
<path d="M27 7c-3-2-6-2-10-2S10 5 7 7l10 1 10-1z" fill="#ff931e" />
<path d="M19 6a3 3 0 011 0 10 10 0 014 2l1-1a11 11 0 00-2-1 10 10 0 00-4 0z" fill="#f17f24" />
<path d="M20 6a10 10 0 00-1 0 4 4 0 012 2h1V7a5 5 0 00-2-1z" fill="#f17f24" />
<path d="M18 6a6 6 0 011 0 3 3 0 00-1 0z" fill="#f17f24" />
<path d="M20 6a3 3 0 00-1 0 6 6 0 00-1 0 3 3 0 011 0 10 10 0 011 0z" fill="#f17f24" />
<path d="M15 6a2 2 0 011 0 10 10 0 00-4 0 12 12 0 00-3 1l2 1a11 11 0 014-2z" fill="#f17f24" />
<path d="M15 7a2 2 0 011-1h-1a5 5 0 00-1 2h-1 1a4 4 0 011-1z" fill="#f17f24" />
<path d="M17 6a2 2 0 00-1 0 6 6 0 011 0z" fill="#f17f24" />
<path d="M16 6a2 2 0 011 0 6 6 0 00-1 0 2 2 0 00-1 0h1z" fill="#f17f24" />
<path d="M17 7V3c0-2 2-3 2-3h1a12 12 0 00-2 7z" fill="#006837" />
<path d="M19 1a7 7 0 00-1 4 32 32 0 011-4z" fill="#004127" />
</g>
</g>
</g>
</g>
</svg>
<div class="emitter"></div>
</div>
<div class="text">
<div>Trick</div>
<div>Or</div>
<div>Treat!</div>
</div>
</div>
CSS:
html {
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
}
* {
box-sizing: inherit;
}
*:before, *:after {
box-sizing: inherit;
}
body {
margin: 0;
padding: 0;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-family: "Inter", Arial;
color: white;
}
.btn {
--background: #f15a24;
display: block;
padding: 0px 16px 0px 16px;
line-height: 26px;
font-weight: 600;
font-size: 14px;
border-radius: 10px;
position: relative;
cursor: pointer;
}
.btn:before {
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border-radius: 12px;
background: var(--background);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.btn .icon,
.btn .text {
display: inline-block;
vertical-align: top;
position: relative;
z-index: 1;
}
.btn svg {
overflow: visible;
}
.btn .icon {
width: 30px;
height: 25px;
margin: 7px 10px 0 0;
overflow: visible;
}
.btn .icon .emitter {
position: absolute;
left: 18px;
top: 4px;
pointer-events: none;
}
.btn .icon .emitter div {
width: 5px;
height: 3px;
margin: -2px 0 0 -2px;
border-radius: 1px;
position: absolute;
left: 0;
top: 0;
background: var(--b, none);
}
.btn .text {
overflow: hidden;
width: 40px;
height: 44px;
padding-top: 10px;
}
.btn .text div {
margin-bottom: 4px;
display: inline-block;
}
JavaScript:
console.clear();
gsap.registerPlugin(Physics2DPlugin);
const btn = document.querySelector(".btn");
gsap.set(".text", { autoAlpha: 1 });
btn.addEventListener("click", (e) => {
const btnTl = gsap
.timeline()
.to(btn, {
scale: 0.95,
transformOrigin: "center",
duration: 1
})
.to(
"#pumpkin",
{
scaleY: 0.9,
transformOrigin: "bottom"
},
"<"
)
.to(
".text div",
{
y: -30,
ease: "power3.out",
},
"<"
)
.to("#p-top", {
transformOrigin: "15% bottom",
rotate: -90,
duration: 0.3
})
.to(
"#p-mouth1",
{
ease: "elastic.out(1, .3)",
morphSVG:
"M28 21v1l-2 1v-1a23 23 0 01-4 1l-1 2h-2v-2h-2v2h-3v-2l-4-1v2H8l-1-2a31 31 0 00-3-1c10 19 27 4 26-1a14 14 0 01-2 1z"
},
"<"
)
.to(
btn,
{
scale: 1,
duration: 0.2,
ease: "elastic.out(1, .3)",
onStart() {
particles(btn.querySelector(".emitter"), 120, -4, 6, -120, -70);
}
},
"<"
)
.to(
".text div",
{
ease: "power3.out",
y: -60
},
"<"
)
.to(
"#pumpkin",
{
ease: "elastic.out(1, .3)",
scaleY: 1,
transformOrigin: "bottom"
},
"<"
)
.to(
"#p-top",
{
transformOrigin: "15% bottom",
rotate: 0
},
"+=1"
)
.set(
".text div",
{
y: 0
},
"<"
)
.to(
"#p-mouth1",
{
morphSVG: "#p-mouth1"
},
"<"
);
});
function particles(parent, quantity, x, y, minAngle, maxAngle) {
let colors = ["#DB5425", "#920783", "#080059", "#FFF33F"];
for (let i = quantity - 1; i >= 0; i--) {
let angle = gsap.utils.random(minAngle, maxAngle),
velocity = gsap.utils.random(60, 150),
dot = document.createElement("div");
dot.style.setProperty("--b", colors[Math.floor(gsap.utils.random(0, 4))]);
parent.appendChild(dot);
gsap.set(dot, {
opacity: 0,
x: x,
y: y,
scale: gsap.utils.random(0.4, 0.7)
});
gsap
.timeline({
onComplete() {
dot.remove();
}
})
.to(
dot,
{
duration: 0.05,
opacity: 1
},
0
)
.to(
dot,
{
duration: 1.8,
rotationX: `-=${gsap.utils.random(720, 1440)}`,
rotationZ: `+=${gsap.utils.random(720, 1440)}`,
physics2D: {
angle: angle,
velocity: velocity,
gravity: 100
}
},
0
)
.to(
dot,
{
duration: 1.2,
opacity: 0
},
1
);
}
}