Skip to content

Instantly share code, notes, and snippets.

@aldoyh
Created September 11, 2024 15:19
Show Gist options
  • Save aldoyh/9a2aa4e56c355295d1c15d9654dea09b to your computer and use it in GitHub Desktop.
Save aldoyh/9a2aa4e56c355295d1c15d9654dea09b to your computer and use it in GitHub Desktop.
GSAP GRID
<div id="print_container">
<div id="grid_container">
<!-- Following Eye -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<defs>
<clipPath id="clip-mask">
<path fill="none" d="M95.86 50S75.33 79.47 50 79.47 4.14 50 4.14 50 24.67 20.53 50 20.53 95.86 50 95.86 50Z" />
</clipPath>
</defs>
<path fill="var(--color-blue)" d="M0 0h100v100H0z" />
<g class="eye">
<path fill="var(--color-white)" d="M95.86 50S75.33 79.47 50 79.47 4.14 50 4.14 50 24.67 20.53 50 20.53 95.86 50 95.86 50Z" />
<g clip-path="url(#clip-mask)">
<circle class="eye-pupil" cx="50" cy="50" r="20.91" fill="var(--color-black)" />
</g>
</g>
</svg>
</div>
</div>
<!-- ROTATING STARS -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path fill="var(--color-blue)" d="M0 0h100v100H0z" />
<path class="star" d="M42.74 25.48c-10.29 0-18.64-8.34-18.64-18.64 0 10.29-8.34 18.64-18.64 18.64 10.29 0 18.64 8.34 18.64 18.64 0-10.29 8.34-18.64 18.64-18.64Z" fill="var(--color-white)" />
<path class="star" d="M94.54 25.48c-10.29 0-18.64-8.34-18.64-18.64 0 10.29-8.34 18.64-18.64 18.64 10.29 0 18.64 8.34 18.64 18.64 0-10.29 8.34-18.64 18.64-18.64Z" fill="var(--color-white)" />
<path class="star" d="M42.74 74.52c-10.29 0-18.64-8.34-18.64-18.64 0 10.29-8.34 18.64-18.64 18.64 10.29 0 18.64 8.34 18.64 18.64 0-10.29 8.34-18.64 18.64-18.64Z" fill="var(--color-white)" />
<path class="star" d="M94.54 74.52c-10.29 0-18.64-8.34-18.64-18.64 0 10.29-8.34 18.64-18.64 18.64 10.29 0 18.64 8.34 18.64 18.64 0-10.29 8.34-18.64 18.64-18.64Z" fill="var(--color-white)" />
</svg>
</div>
</div>
<!-- MORPHING BOXES -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 200">
<defs>
<clipPath id="a">
<path fill="none" d="M0 0h100v100H0z" />
</clipPath>
</defs>
<path fill="var(--color-blue)" d="M0 0h100v100H0z" />
<g clip-path="url(#a)">
<g id="circles">
<g class="circle">
<circle cx="50" cy="50" r="50" fill="var(--color-white)" />
<path d="M100 50c0 27.61-22.39 50-50 50V0c27.61 0 50 22.39 50 50Z" fill="var(--color-black)" />
</g>
<g class="circle">
<circle cx="50" cy="250" r="50" fill="var(--color-white)" />
<path d="M100 250c0 27.61-22.39 50-50 50V200c27.61 0 50 22.39 50 50Z" fill="var(--color-black)" />
</g>
<g class="circle">
<circle cx="50" cy="150" r="50" fill="var(--color-white)" />
<path d="M0 150c0-27.61 22.39-50 50-50v100c-27.61 0-50-22.39-50-50Z" fill="var(--color-black)" />
</g>
</g>
</g>
</svg>
</div>
</div>
<!-- HALF CIRCLES -->
<div class="box">
<div class="box-content">
<svg id="morph-boxes" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path fill="var(--color-blue)" d="M0 0h100v100H0z" />
<path id="morph-box-1" class="morph-box" d="M28.88 8.4H9.87v19.01l19.01 19.01h19.01V27.41L28.88 8.4z" fill="var(--color-black)" />
<path id="box-top-1" d="M9.87 8.4h19.01v19.01H9.87z" fill="var(--color-white)" />
<path id="morph-box-2" class="morph-box" d="M73.18 8.4H54.17v19.01l19.01 19.01h19.01V27.41L73.18 8.4z" fill="var(--color-black)" />
<path id="box-top-2" d="M54.17 8.4h19.01v19.01H54.17z" fill="var(--color-white)" />
<path id="morph-box-3" class="morph-box" d="M28.88 53.58H9.87v19.01L28.88 91.6h19.01V72.59L28.88 53.58z" fill="var(--color-black)" />
<path id="box-top-3" d="M9.87 53.58h19.01v19.01H9.87z" fill="var(--color-white)" />
<path id="morph-box-4" class="morph-box" d="M73.18 53.58H54.17v19.01L73.18 91.6h19.01V72.59L73.18 53.58z" fill="var(--color-black)" />
<path id="box-top-4" d="M54.17 53.58h19.01v19.01H54.17z" fill="var(--color-white)" />
<g class="morph-shapes">
<polygon id="morph-shape-4" points="92.19 72.59 73.18 72.59 73.18 91.6 73.18 91.6 92.19 91.6 92.19 72.59 92.19 72.59" fill="none" />
<polygon id="morph-shape-2" points="92.19 27.41 73.18 27.41 73.18 46.42 73.18 46.42 92.19 46.42 92.19 27.41 92.19 27.41" fill="none" />
<polygon id="morph-shape-1" points="47.89 27.41 28.88 27.41 28.88 46.42 28.88 46.42 47.89 46.42 47.89 27.41 47.89 27.41" fill="none" />
<polygon id="morph-shape-3" points="47.89 72.59 28.88 72.59 28.88 91.6 28.88 91.6 47.89 91.6 47.89 72.59 47.89 72.59" fill="none" />
</g>
</svg>
</div>
</div>
<!-- FOLLOWING STARS -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<defs>
<clipPath id="half-circle-clip-path">
<path fill="none" d="M0 0h100v100H0z" />
</clipPath>
</defs>
<path fill="var(--color-yellow)" d="M0 0h100v100H0z" />
<g clip-path="url(#half-circle-clip-path)">
<g id="half-circles">
<path id="half-circle-1" class="half-circle" d="M0 50C0 22.39 22.39 0 50 0v100C22.39 100 0 77.61 0 50Z" fill="var(--color-blue)" />
<path id="half-circle-2" class="half-circle" d="M50 50c0-27.61 22.39-50 50-50v100c-27.61 0-50-22.39-50-50Z" fill="var(--color-blue)" />
<path id="half-circle-3" class="half-circle" d="M100 50c0-27.61 22.39-50 50-50v100c-27.61 0-50-22.39-50-50Z" fill="var(--color-blue)" />
<path id="half-circle-4" class="half-circle" d="M150 50c0-27.61 22.39-50 50-50v100c-27.61 0-50-22.39-50-50Z" fill="var(--color-blue)" />
</g>
</g>
</svg>
</div>
</div>
<!-- MORPHING HEART -->
<div class="box">
<div class="box-content">
<svg id="following-stars" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path fill="var(--color-red)" d="M0 0h100v100H0z" />
<path class="rotating-star" fill="var(--color-white)" d="M100 50C72.39 50 50 27.61 50 0c0 27.61-22.39 50-50 50 27.61 0 50 22.39 50 50 0-27.61 22.39-50 50-50Z" />
<path class="following-star" fill="var(--color-yellow)" d="M100 50C72.39 50 50 27.61 50 0c0 27.61-22.39 50-50 50 27.61 0 50 22.39 50 50 0-27.61 22.39-50 50-50Z" />
<path class="following-star" fill="var(--color-yellow)" d="M100 50C72.39 50 50 27.61 50 0c0 27.61-22.39 50-50 50 27.61 0 50 22.39 50 50 0-27.61 22.39-50 50-50Z" />
<path class="following-star" fill="var(--color-yellow)" d="M100 50C72.39 50 50 27.61 50 0c0 27.61-22.39 50-50 50 27.61 0 50 22.39 50 50 0-27.61 22.39-50 50-50Z" />
<path class="following-star" fill="var(--color-yellow)" d="M100 50C72.39 50 50 27.61 50 0c0 27.61-22.39 50-50 50 27.61 0 50 22.39 50 50 0-27.61 22.39-50 50-50Z" />
</svg>
</div>
</div>
<!-- DRAW SVG LINES -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path fill="var(--color-red)" d="M0 0h100v100H0z" />
<path id="morph-heart" fill="var(--color-white)" d="M50 15.05c-10.76-10.76-28.22-10.76-38.98 0C.25 25.82.25 43.27 11.02 54.04L50 93.02l38.98-38.98c10.76-10.76 10.76-28.22 0-38.98C78.22 4.3 60.76 4.3 50 15.06Z" />
<path id="morph-lip" fill="none" d="M89.74 42.61c-7-7.47-15.48-21.85-28.55-21.85-7.61 0-8.85 6.26-11.18 6.26s-3.58-6.26-11.18-6.26c-13.07 0-21.55 14.38-28.55 21.85-2.98 3.18-7.67 6.22-7.67 6.22s3.22 2.02 5.78 4.61c6.88 6.98 21.46 25.41 41.62 25.8 20.16-.39 34.75-18.82 41.62-25.8 2.56-2.6 5.78-4.61 5.78-4.61s-4.69-3.04-7.67-6.22Z" />
</svg>
</div>
</div>
<!-- STRIPES -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path fill="var(--color-yellow)" d="M0 0h100v100H0z" />
<path class="square-stroke" d="M21.25 0v50c0 15.88 12.87 28.75 28.75 28.75S78.75 65.88 78.75 50" fill="none" stroke="var(--color-blue)" stroke-miterlimit="10" stroke-width="10" />
<path class="square-stroke-right" d="M21.25 49.92c0-15.88 12.87-28.75 28.75-28.75s28.75 12.87 28.75 28.75V100" fill="none" stroke="var(--color-blue)" stroke-miterlimit="10" stroke-width="10" />
<path class="square-stroke" d="M28.88 0v50c0 11.66 9.46 21.12 21.12 21.12S71.12 61.66 71.12 50" fill="none" stroke="var(--color-white)" stroke-miterlimit="10" stroke-width="10" />
<path class="square-stroke-right" d="M28.88 49.92c0-11.66 9.46-21.12 21.12-21.12s21.12 9.46 21.12 21.12V100" fill="none" stroke="var(--color-white)" stroke-miterlimit="10" stroke-width="10" />
<path class="square-stroke" d="M36.51 0v50c0 7.45 6.04 13.49 13.49 13.49S63.49 57.45 63.49 50" fill="none" stroke="var(--color-red)" stroke-miterlimit="10" stroke-width="10" />
<path class="square-stroke-right" d="M36.51 49.92c0-7.45 6.04-13.49 13.49-13.49s13.49 6.04 13.49 13.49V100" fill="none" stroke="var(--color-red)" stroke-miterlimit="10" stroke-width="10" />
</svg>
</div>
</div>
<!-- RANDOM CIRCLES -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path d="M0 0h100v100H0z" fill="var(--color-yellow)" />
<circle class="random-circle" cx="50" cy="50" r="50" fill="var(--color-white)" />
<circle class="random-circle" cx="50" cy="50" r="40" fill="var(--color-blue)" />
<circle class="random-circle" cx="50" cy="50" r="30" fill="var(--color-red)" />
</svg>
</div>
</div>
<!-- STREACH BARS -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path fill="var(--color-white)" d="M0 0h100v100H0z" />
<g class="bar">
<path id="bar-1" d="M71.97 6.27c-6.07 0-10.98 4.92-10.98 10.98v52.27c0 6.07 4.92 10.98 10.98 10.98s10.98-4.92 10.98-10.98V17.25c0-6.07-4.92-10.98-10.98-10.98Z" fill="var(--color-red)" />
<circle id="bar-1-circle-1" cx="71.97" cy="17.25" r="10.98" fill="var(--color-blue)" />
<circle cx="71.97" cy="69.52" r="10.98" fill="var(--color-yellow)" />
<path id="morph-bar-1" d="M71.97 48.56c-6.07 0-10.98 4.92-10.98 10.98v9.98c0 6.07 4.92 10.98 10.98 10.98s10.98-4.92 10.98-10.98v-9.98c0-6.07-4.92-10.98-10.98-10.98Z" fill="none" />
</g>
<g class="bar">
<path id="bar-2" d="M50 22.42c-6.07 0-10.98 4.92-10.98 10.98v52.27c0 6.07 4.92 10.98 10.98 10.98s10.98-4.92 10.98-10.98V33.4c0-6.07-4.92-10.98-10.98-10.98Z" fill="var(--color-blue)" />
<circle cx="50" cy="33.41" r="10.98" fill="var(--color-yellow)" />
<circle id="bar-2-circle-2" cx="50" cy="85.68" r="10.98" fill="var(--color-black)" />
<path id="morph-bar-2" d="M50.06 22.42c-6.07 0-10.98 4.92-10.98 10.98v9.98c0 6.07 4.92 10.98 10.98 10.98s10.98-4.92 10.98-10.98V33.4c0-6.07-4.92-10.98-10.98-10.98Z" fill="none" />
</g>
<g class="bar">
<path id="bar-3" d="M28.15 7.27c-6.07 0-10.98 4.92-10.98 10.98v52.27c0 6.07 4.92 10.98 10.98 10.98s10.98-4.92 10.98-10.98V18.26c0-6.07-4.92-10.98-10.98-10.98Z" fill="var(--color-red)" />
<circle id="bar-3-circle-1" cx="28.15" cy="18.26" r="10.98" fill="var(--color-black)" />
<circle cx="28.15" cy="70.53" r="10.98" fill="var(--color-blue)" />
<path id="morph-bar-3" fill="none" d="M27.86 37.18c-6.06.09-10.81 5.31-10.81 11.38v22.01c0 6.07 4.74 11.28 10.81 11.38 6.15.1 11.16-4.86 11.16-10.98v-22.8c0-6.12-5.01-11.08-11.16-10.98Z" />
</g>
</svg>
</div>
</div>
<!-- ROTATING DISK-->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path fill="var(--color-white)" d="M0 0h100v100H0z" />
<g id="disk">
<path fill="none" d="M0 0h100v100H0z" />
<path fill="var(--color-blue)" d="M100 50c0 27.61-22.39 50-50 50S0 77.61 0 50h100Z" />
</g>
<circle cx="50" cy="50" r="25" fill="var(--color-black)" />
</svg>
</div>
</div>
<!-- ARROWS -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 200">
<defs>
<clipPath id="a">
<path fill="none" d="M0 0h100v100H0z" />
</clipPath>
</defs>
<path fill="var(--color-white)" d="M0 0h100v100H0z" />
<g clip-path="url(#a)">
<path id="arrow-1" d="M50 0 0 50h100L50 0z" fill="var(--color-red)" />
<path id="arrow-2" d="M50 50 0 100h100L50 50z" fill="var(--color-black)" />
<path id="arrow-3" d="M50 100 0 150h100l-50-50z" fill="var(--color-red)" />
<path id="arrow-4" d="M50 150 0 200h100l-50-50z" fill="var(--color-black)" />
</g>
</svg>
</div>
</div>
<!-- LINE DRAWING -->
<div class="box">
<div class="box-content">
<svg id="lines" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect fill="var(--color-white)" width="100" height="100" />
<path class="line" fill="none" stroke="var(--color-blue)" stroke-miterlimit="10" stroke-width="1" stroke-linecap="round" d="M50 9.95v80.32" />
</svg>
</div>
</div>
<!-- STACK ELIPSES -->
<div class="box">
<div class="box-content">
<svg id="ellipse" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path fill="var(--color-yellow)" d="M0 0h100v100H0z" />
<ellipse class="ellipse" cx="50" cy="25" fill="var(--color-white)" rx="50" ry="25" />
</svg>
</div>
</div>
<!-- BALLANCING BALLS -->
<div class="box">
<div class="box-content">
<svg id="balancing-balls" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<defs>
<clipPath id="ball-mask">
<path fill="none" d="M0 0h100v100H0z" />
</clipPath>
</defs>
<path fill="var(--color-red)" d="M0 0h100v100H0z" />
<g clip-path="url(#ball-mask)">
<circle class="ball" id="balance-ball-1" cx="50" cy="87" r="13" fill="var(--color-white)" />
<circle class="ball" id="balance-ball-2" cx="50" cy="54" r="19" fill="var(--color-black)" />
<circle class="ball" id="balance-ball-3" cx="50" cy="0" r="35" fill="var(--color-yellow)" />
</g>
</svg>
</div>
</div>
<!-- Following Eye -->
<div class="box">
<div class="box-content">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<defs>
<clipPath id="clip-mask">
<path fill="none" d="M95.86 50S75.33 79.47 50 79.47 4.14 50 4.14 50 24.67 20.53 50 20.53 95.86 50 95.86 50Z" />
</clipPath>
</defs>
<path fill="var(--color-red)" d="M0 0h100v100H0z" />
<g class="eye">
<path fill="var(--color-white)" d="M95.86 50S75.33 79.47 50 79.47 4.14 50 4.14 50 24.67 20.53 50 20.53 95.86 50 95.86 50Z" />
<g clip-path="url(#clip-mask)">
<circle class="eye-pupil" cx="50" cy="50" r="20.91" fill="var(--color-black)" />
</g>
</g>
</svg>
</div>
</div>
</div>
<div>
<div class="title_container">
<!-- SPLIT TEXT -->
<p class="title">GSAP GRID</p>
<div class="color_pallet">
<div class="blue"></div>
<div class="red"></div>
<div class="yellow"></div>
<div class="black"></div>
</div>
</div>
</div>
</div>
// Drag and Move mouse around
// Hope you like it :)
// @shunyadezian
console.clear();
gsap.registerPlugin(
MorphSVGPlugin,
DrawSVGPlugin,
SplitText,
Draggable,
InertiaPlugin
);
const container = document.getElementById("grid_container");
// REVEAL GRID ITEM
const boxes = gsap.utils.toArray(".box");
gsap.to(boxes, {
autoAlpha: 1,
duration: 0.8,
stagger: 0.1,
ease: "power1.inOut"
});
// Following Eye
// ref: https://gsap.com/community/forums/topic/17962-cursor-follows-the-eyes/
container.addEventListener("mousemove", (e) => {
const { clientX, clientY } = e;
const maxTrans = 20;
const maxX = container.clientWidth / 2;
const maxY = container.clientHeight / 2;
const eye = document.querySelectorAll(".eye");
const pupil = document.querySelectorAll(".eye-pupil");
for (let i = 0; i < eye.length; i++) {
const eyeRect = eye[i].getBoundingClientRect();
const r = eyeRect.width / 2;
const centerX = eyeRect.left + r;
const centerY = eyeRect.top + r;
const x = clientX - centerX;
const y = clientY - centerY;
const xPercent = x / maxX;
const yPercent = y / maxY;
const scaledXPercent = xPercent * maxTrans;
const scaledYPercent = yPercent * maxTrans;
gsap.to(pupil[i], {
xPercent: scaledXPercent,
yPercent: scaledYPercent,
duration: 0.2,
overwrite: "auto"
});
gsap.to(eye[i], {
xPercent: scaledXPercent * 0.4,
yPercent: scaledYPercent * 0.4,
duration: 0.2,
overwrite: "auto"
});
}
});
// ROTATING STARS
const starTL = gsap.timeline({ repeat: -1, repeatDelay: 0.5 });
starTL
.to(".star", {
rotate: 360,
transformOrigin: "50% 50%",
duration: 1,
stagger: 0.5
})
.to(".star", {
scale: 1.5,
transformOrigin: "50% 50%",
duration: 0.2,
ease: "power1.out",
repeat: 1,
yoyo: true
});
// ROTATING CIRCLES
gsap.to("#circles", {
y: -200,
duration: 1.5,
ease: "none",
repeat: -1
});
gsap.to(".circle", {
rotate: 360,
transformOrigin: "50% 50%",
duration: 3,
repeat: -1,
ease: "none"
});
// MORPHING BOXES
const morphBoxes = gsap.utils.toArray(".morph-box");
const morphDuration = 1;
morphBoxes.forEach((box, i) => {
gsap.to(box, {
morphSVG: `#morph-shape-${i + 1}`,
duration: morphDuration,
ease: "power1.inOut",
repeat: -1,
yoyo: true,
delay: i * 0.1
});
gsap.to(`#box-top-${i + 1}`, {
y: 19,
x: 19,
duration: morphDuration,
ease: "power1.inOut",
repeat: -1,
yoyo: true,
delay: i * 0.1
});
});
// HALF CIRCLES
const halfCircleTl = gsap.timeline({ repeat: -1 }).timeScale(0.5);
const halfCircleEase = "power2.inOut";
const halfCirclesScale = {
scale: 0,
transformOrigin: "0% 50%",
ease: halfCircleEase
};
halfCircleTl
.to("#half-circle-1", {
...halfCirclesScale
})
.to(
"#half-circle-2",
{
x: -50,
ease: halfCircleEase
},
"<"
)
.to(
"#half-circle-3",
{
x: -50,
transformOrigin: "0% 50%",
ease: halfCircleEase
},
"<"
)
.to(
"#half-circle-4",
{
x: -50,
ease: halfCircleEase
},
"<"
)
.to("#half-circle-2", {
...halfCirclesScale
})
.to(
"#half-circle-3",
{
x: -100,
ease: halfCircleEase
},
"<"
)
.to(
"#half-circle-4",
{
x: -100,
ease: halfCircleEase
},
"<"
);
// FOLLOWING STARS
// ref: https://gsap.com/community/forums/topic/30502-mouse-cursor-follow-animation/
const starContainer = document.querySelector("#following-stars");
gsap.set(".following-star", {
xPercent: -50,
yPercent: -50,
x: 0,
y: 100,
transformOrigin: "center",
scale: 0
});
let initialMouseMove = true;
let timer;
starContainer.addEventListener("mousemove", (e) => {
const { clientX, clientY } = e;
const containerRect = starContainer.getBoundingClientRect();
const centerX = containerRect.left;
const centerY = containerRect.top;
const x = clientX - centerX;
const y = clientY - centerY;
// if it's the first mouse movement run this
if (initialMouseMove) {
initialMouseMove = false;
gsap.to(".following-star", {
scale: 0.4,
stagger: 0.02,
ease: "sine.out"
});
}
const mouseStopped = () => {
// reset this variable
// so we can track the first mouse move again
initialMouseMove = true;
gsap.to(".following-star", {
scale: 0,
stagger: 0.02,
ease: "sine.inOut"
});
};
// // clear the timer every time the mouse moves
clearTimeout(timer);
// // set a timer for 0.2 second
timer = setTimeout(mouseStopped, 20);
gsap.to(".following-star", {
duration: 0.5,
overwrite: "auto",
x: x / 2,
y: y / 2,
stagger: 0.1,
ease: "none"
});
});
// MORPHING HEART
gsap.to("#morph-heart", {
morphSVG: `#morph-lip`,
duration: 2,
ease: "power3.inOut",
repeat: -1,
yoyo: true
});
// STRIPES
gsap.set(".square-stroke", {
drawSVG: 0
});
gsap.to(".square-stroke", {
drawSVG: '100% "100%"',
duration: 2,
ease: "power3.out",
repeat: -1,
yoyo: true,
stagger: 0.1
});
gsap.set(".square-stroke-right", {
drawSVG: "100% 100%"
});
gsap.to(".square-stroke-right", {
drawSVG: "0% 100%", // reverse
duration: 2,
ease: "power3.out",
repeat: -1,
yoyo: true,
stagger: 0.1
});
// RANDOM CIRCLES
const randomCircleTl = gsap.timeline({ repeat: -1, repeatRefresh: true });
randomCircleTl
.to(".random-circle", {
x: () => gsap.utils.random(-40, 40, 5),
y: () => gsap.utils.random(-40, 40, 5),
scale: 0,
transformOrigin: "center"
})
.to(".random-circle", {
scale: () => gsap.utils.random(0.7, 1, 0.1),
duration: 1,
ease: "power3.inOut",
stagger: 0.2
});
// STREACH BARS
gsap.to(".bar", {
y: -5,
duration: 1,
ease: "power1.inOut",
repeat: -1,
yoyo: true,
stagger: 1
});
gsap.to("#bar-1", {
morphSVG: "#morph-bar-1",
duration: 1,
ease: "power3.inOut",
repeat: -1,
yoyo: true
});
gsap.to("#bar-1-circle-1", {
y: 40,
duration: 1,
ease: "power3.inOut",
repeat: -1,
yoyo: true
});
gsap.to("#bar-2", {
morphSVG: "#morph-bar-2",
duration: 3,
ease: "sine.inOut",
repeat: -1,
yoyo: true
});
gsap.to("#bar-2-circle-2", {
y: -40,
duration: 3,
ease: "sine.inOut",
repeat: -1,
yoyo: true
});
gsap.to("#bar-3", {
morphSVG: "#morph-bar-3",
duration: 2,
ease: "circ",
repeat: -1,
yoyo: true
});
gsap.to("#bar-3-circle-1", {
y: 30,
duration: 2,
ease: "circ",
repeat: -1,
yoyo: true
});
// ROTATING DISK
gsap.to("#disk", {
rotate: 360,
transformOrigin: "50% 50%",
duration: 3,
ease: "elastic.out(1,0.5)",
repeat: -1,
yoyo: true
});
// ARROWS
const arrowTL = gsap.timeline({ repeat: -1 });
arrowTL
.to("#arrow-1", {
scale: 0,
transformOrigin: "top center",
duration: 1,
ease: "power3.inOut"
})
.to(
"#arrow-2",
{
y: -50,
duration: 1,
ease: "power3.inOut"
},
"<"
)
.to("#arrow-3", {
y: -50,
duration: 1,
ease: "power3.inOut"
})
.to("#arrow-2", {
scale: 0,
transformOrigin: "top center",
duration: 1,
ease: "power3.inOut"
})
.to(
"#arrow-3",
{
y: -100,
duration: 1,
ease: "power3.inOut"
},
"<"
)
.to("#arrow-4", {
y: -100,
duration: 1,
ease: "power3.inOut"
});
// LINE DRAWING
const line = document.querySelector("#lines");
const lineOrigin = document.querySelector("#lines path");
// Number of duplicates
const numOfLines = 20;
for (let i = 0; i < numOfLines; i++) {
const clonedPath = lineOrigin.cloneNode(true);
clonedPath.setAttribute("class", "line");
line.appendChild(clonedPath);
}
const lines = gsap.utils.toArray(".line");
lines.forEach((line, i) => {
gsap.set(line, {
drawSVG: "100% 0%",
rotate: (i * 180) / numOfLines,
transformOrigin: "center"
});
});
gsap.to(lines, {
rotate: "+=360",
ease: "power3.inOut",
repeat: -1,
stagger: 0.1,
duration: 4
});
gsap.to("#lines path", {
drawSVG: "100% 50%",
duration: 2,
ease: "power3.inOut",
repeat: -1,
yoyo: true,
stagger: 0.1
});
// STACK ELIPSES
const ellipse = document.querySelector("#ellipse");
const ellipsOrigin = document.querySelector("#ellipse ellipse");
// Number of duplicates
const numOfEllipses = 10;
for (let i = 0; i < numOfEllipses; i++) {
const clonedPath = ellipsOrigin.cloneNode(true);
ellipse.appendChild(clonedPath);
}
const ellipses = gsap.utils.toArray(".ellipse");
ellipses.forEach((ellipse, i) => {
gsap.set(ellipse, {
transformOrigin: "bottom center"
});
});
gsap.to(ellipses, {
y: 50,
fill: "#9d2719",
ease: "power3.inOut",
stagger: 0.1,
repeat: -1,
duration: 1,
yoyo: true
});
// BALLANCING BALLS
const ballContainer = document.querySelector("#balancing-balls");
gsap.set("#balance-ball-1", {
xPercent: -190,
transformOrigin: "center",
x: 50
});
gsap.set("#balance-ball-2", {
xPercent: -130,
transformOrigin: "center",
x: 50
});
gsap.set("#balance-ball-3", {
xPercent: -70,
transformOrigin: "center",
x: 50
});
ballContainer.addEventListener("mousemove", (e) => {
const { clientX } = e;
const containerRect = ballContainer.getBoundingClientRect();
const centerX = containerRect.left;
const x = clientX - centerX;
gsap.to("#balance-ball-1", {
duration: 0.5,
overwrite: "auto",
x: x / 2,
ease: "power4.out"
});
gsap.to("#balance-ball-2", {
duration: 0.5,
overwrite: "auto",
x: x / 2,
ease: "power4.out",
delay: 0.02
});
gsap.to("#balance-ball-3", {
duration: 0.5,
overwrite: "auto",
x: x / 2,
ease: "power4.out",
delay: 0.045
});
});
ballContainer.addEventListener("mouseleave", () => {
gsap.to(".ball", {
x: 50,
stagger: 0.05,
ease: "sine.inOut"
});
});
// SPLIT TEXT
const title = document.querySelector(".title");
const split = new SplitText(title, { type: "chars" });
gsap.from(split.chars, {
duration: 0.5,
y: 100,
stagger: 0.1,
ease: "back.out"
});
const titleSpinTL = gsap.timeline({ paused: true });
titleSpinTL.to(split.chars, {
duration: 0.5,
rotateY: 360,
stagger: 0.1,
repeat: 1,
yoyo: true
});
title.addEventListener("mouseenter", () => {
titleSpinTL.restart();
});
////////////////////////////////////
// GRID SYSTEM
////////////////////////////////////
//ref: https://codepen.io/osublake/pen/NrRJwm?editors=0110
//ref: https://codepen.io/GreenSock/pen/JjwZzNG?editors=0010
const colSize = 200;
const rowSize = 200;
const gridRows = 4;
const gridColumns = 4;
function createGrid(gridRows, gridColumns) {
for (let i = 0; i < gridRows * gridColumns; i++) {
const y = Math.floor(i / gridColumns) * rowSize;
const x = (i * colSize) % (gridColumns * colSize);
const cell = document.createElement("div");
cell.classList.add("cell");
cell.style.width = colSize - 1 + "px";
cell.style.height = rowSize - 1 + "px";
cell.style.top = y + "px";
cell.style.left = x + "px";
container.appendChild(cell);
}
}
createGrid(gridRows, gridColumns);
let clampCol = gsap.utils.clamp(0, gridColumns - 1);
let clampRow = gsap.utils.clamp(0, gridRows - 1);
let cells = [];
// Map cell locations to array
for (let row = 0; row < gridRows; row++) {
for (let col = 0; col < gridColumns; col++) {
cells.push({
row: row,
col: col,
x: col * colSize,
y: row * rowSize
});
}
}
let listItems = gsap.utils.toArray(".box").sort(() => 0.5 - Math.random()); // Randomize list items
let sortables = listItems.map(Sortable); // Array of sortables
gsap.to(container, { autoAlpha: 1, duration: 0.5 });
function changeIndex(item, to, sameRow, sameCol) {
// Check if adjacent to new position
if ((sameRow && !sameCol) || (!sameRow && sameCol)) {
// Swap positions in array
var temp = sortables[to];
sortables[to] = item;
sortables[item.index] = temp;
} else {
// Change position in array
arrayMove(sortables, item.index, to);
}
// Simple, but not optimized way to change element's position in DOM. Not always necessary.
sortables.forEach((sortable) => container.appendChild(sortable.element));
// Set index for each sortable
sortables.forEach((sortable, index) => sortable.setIndex(index));
}
function Sortable(element, index) {
let content = element.querySelector(".box-content");
let animation = gsap.to(content, {
duration: 0.3,
boxShadow: "rgba(0,0,0,0.8) 0px 16px 32px 0px",
force3D: true,
scale: 1.1,
paused: true
});
let dragger = new Draggable(element, {
onDragStart: downAction,
onRelease: upAction,
onDrag: dragAction
});
// let position = element._gsTransform;
let getProp = gsap.getProperty(element);
// Public properties and methods
let sortable = {
cell: cells[index],
dragger: dragger,
element: element,
index: index,
setIndex: setIndex
};
gsap.set(element, {
x: sortable.cell.x,
y: sortable.cell.y
});
function setIndex(index) {
let cell = cells[index];
// var dirty = position.x !== cell.x || position.y !== cell.y;
let dirty = getProp("x") !== cell.x || getProp("y") !== cell.y;
sortable.cell = cell;
sortable.index = index;
// Don't layout if you're dragging
if (!dragger.isDragging && dirty) layout();
}
function downAction() {
animation.play();
this.update();
}
function dragAction() {
let col = clampCol(Math.round(this.x / colSize));
let row = clampRow(Math.round(this.y / rowSize));
let cell = sortable.cell;
let sameCol = col === cell.col;
let sameRow = row === cell.row;
// Check if position has changed
if (!sameRow || !sameCol) {
// Calculate the new index
var index = gridColumns * row + col;
// Update the model
changeIndex(sortable, index, sameRow, sameCol);
}
}
function upAction() {
animation.reverse();
layout();
}
function layout() {
gsap.to(element, {
duration: 0.3,
x: sortable.cell.x,
y: sortable.cell.y
});
}
return sortable;
}
// Changes an elements's position in array
function arrayMove(array, from, to) {
array.splice(to, 0, array.splice(from, 1)[0]);
}
<script src="https://unpkg.com/gsap@3/dist/gsap.min.js"></script>
<script src="https://assets.codepen.io/16327/SplitText3.min.js"></script>
<script src="https://assets.codepen.io/16327/MorphSVGPlugin3.min.js"></script>
<script src="https://assets.codepen.io/16327/DrawSVGPlugin3.min.js"></script>
<script src="https://unpkg.com/gsap@3/dist/Draggable.min.js"></script>
<script src="https://assets.codepen.io/16327/InertiaPlugin.min.js"></script>
@import url("https://fonts.googleapis.com/css2?family=Tilt+Warp&display=swap");
:root {
--color-blue: #154084;
--color-red: #9d2719;
--color-yellow: #d7b418;
--color-white: #fff3e7;
--color-black: #222222;
--box-size: 200px;
font-family: "Tilt Warp", sans-serif;
color: var(--color-text);
background-color: var(--color-black);
}
body {
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
#print_container {
padding: 12px;
background-color: var(--color-white);
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 12px;
}
.title_container {
display: flex;
justify-content: space-between;
align-items: end;
}
.title {
font-size: 5rem;
line-height: 5rem;
font-weight: 600;
letter-spacing: -2px;
color: var(--color-black);
margin: 0;
}
.color_pallet {
display: flex;
}
.color_pallet div {
width: 20px;
height: 20px;
}
.color_pallet .blue {
background-color: var(--color-blue);
}
.color_pallet .red {
background-color: var(--color-red);
}
.color_pallet .yellow {
background-color: var(--color-yellow);
}
.color_pallet .black {
background-color: var(--color-black);
}
#grid_container {
position: relative;
width: calc(var(--box-size) * 4);
height: calc(var(--box-size) * 4);
}
.cell {
position: absolute;
pointer-events: none;
/* border: 1px solid #ffffff82; */
}
.box {
opacity: 0;
position: absolute;
top: 0;
left: 0;
width: var(--box-size);
height: var(--box-size);
line-height: var(--box-size);
cursor: pointer;
overflow: hidden;
}
.box-content {
height: 100%;
background-color: rgb(255, 255, 255);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment