SignUp Page Animation
Today I am share you Latest Social media Trending Sign up Animation Page source code free. This creative and interactive login page offers a unique design inspired by Rube Goldberg. This adds a playful and engaging user experience while maintaining the functionality of entering name, email, and contract options. Ideal for websites looking for a distinctive and memorable design.”
Source Code html, css, js.
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>SignUp Page</title>
</head>
<body>
<div class="container">
<div class="form-container">
<label class="form-row">
<input
autocomplete="one-time-code"
type="text"
id="name"
name="name"
placeholder="Name"
required
/>
</label>
<label class="form-row">
<input
autocomplete="one-time-code"
type="email"
id="email"
name="email"
placeholder="Email"
required
/>
</label>
<label class="form-row">
<input type="checkbox" id="subscribe" name="subscribe" /> Remember me
</label>
<div class="form-row">
<input type="submit" value="Submit" />
</div>
</div>
<svg
viewBox="0 0 1000 1000"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="710" y="527" width="16" height="47" rx="10" ry="10"></rect>
<g class="grabbing-hand">
<path
d="M48.89,54.39c-3.51.76-15.72,3-22.83-.68a14,14,0,0,0-6.41-1.52h0A3.79,3.79,0,0,1,17,51.09a3.7,3.7,0,0,1-1.1-2.64V27.75A3.75,3.75,0,0,1,19.63,24H24.1"
/>
<path
class="grabbing-hand-finger-open"
d="M57.05,29.76l24.82,0a4.07,4.07,0,0,0,4.11-4h0a4.07,4.07,0,0,0-4-4.11L48.69,21.3"
/>
<path
class="grabbing-hand-finger-open"
d="M59.34,37.74l28.81.61a4.06,4.06,0,0,0,4.14-4h0a4.06,4.06,0,0,0-4-4.15L57,29.64"
/>
<path
class="grabbing-hand-finger-open"
d="M57.13,45.9l26.94.78a4.07,4.07,0,0,0,4.15-4h0a4.07,4.07,0,0,0-4-4.14l-24.84-.8"
/>
<path
class="grabbing-hand-finger-open"
d="M48.89,54.39l27.82.36a4.06,4.06,0,0,0,4.2-3.93h0A4.06,4.06,0,0,0,77,46.62l-19.88-.78"
/>
<path
class="grabbing-hand-finger-open"
d="M40.78,28c5.75-5.85,12.66-22,10.5-25.88-2.25-4.09-6,.1-14.73,8.66C30.84,16.36,30.91,17.1,24.32,24"
/>
</g>
<g class="pull-system">
<line class="checkbox-pull-line" x1="0" y1="0" x2="0" y2="0" />
<g class="checkbox-pull-circle">
<circle cx="0" cy="0" r="10" />
<circle cx="0" cy="0" r="4" fill="#000000" />
</g>
<circle
class="submit-btn-circle"
cx="0"
cy="0"
r="3"
stroke="none"
fill="#000"
/>
<path class="submit-btn-connector" d=""></path>
</g>
<g class="spray-hand-container">
<g class="pushing-hand">
<circle cx="18" cy="0" r="5" fill="#000000" />
<circle cx="18" cy="-70" r="5" fill="#000000" />
<path d="M18,-70 v70" stroke-width="4" />
<g>
<path
d="M25.3,32.9V60.2a4.2,4.2,0,0,0,4.2,4.2h0a4.2,4.2,0,0,0,4.2-4.2V26.7"
/>
<rect
x="3.9"
y="18.4"
width="8.4"
height="21.47"
rx="3.7"
transform="translate(10.2 -1) rotate(19.4)"
/>
<path
d="M20.9,24a3.4,3.4,0,0,0-1.7-1.1h0a4.2,4.2,0,0,0-5.4,2.5L9.1,38.8a4.3,4.3,0,0,0,2.6,5.4h0a4.3,4.3,0,0,0,5.4-2.6l1.8-5.1"
/>
<path
d="M18.4,37.9,17.3,43a4.2,4.2,0,0,0,3.4,4.9h0a4.3,4.3,0,0,0,4.5-2.3"
/>
<path
fill="white"
d="M29,16.8c-6.4,5-15,13.2-12.8,17.8s6,.7,15.8-6.7c6.4-4.8,7.4-12.6.5-19.2V4.2A3.8,3.8,0,0,0,28.7.5H8A3.5,3.5,0,0,0,5.4,1.6,3.7,3.7,0,0,0,4.3,4.2V8.7"
/>
<path d="M4.3,8.7c-5.8,6.4-3.6,20-2.2,24.8" />
</g>
</g>
<g class="sprayer">
<g class="sprayer-head">
<defs>
<radialGradient
id="grad1"
cx="50%"
cy="50%"
r="50%"
fx="100%"
fy="50%"
>
<stop offset="0%" stop-color="#777777" stop-opacity="0" />
<stop offset="100%" stop-color="#777777" stop-opacity="1" />
</radialGradient>
</defs>
<rect
x="82.39"
y="19.85"
width="13.06"
height="16.79"
rx="1.46"
/>
<rect x="74.55" y="22.56" width="7.84" height="6.1" rx="1.13" />
<line
class="spray-line"
stroke="#777777"
stroke-dasharray="8 5"
x1="22.4"
y1="14.76"
x2="74.27"
y2="25.2"
/>
<line
class="spray-line"
stroke="#777777"
stroke-dasharray="8 5"
x1="21.51"
y1="21.12"
x2="74.27"
y2="25.2"
/>
<line
class="spray-line"
stroke="#777777"
stroke-dasharray="8 5"
x1="21.44"
y1="28.26"
x2="74.27"
y2="25.2"
/>
<line
class="spray-line"
stroke="#777777"
stroke-dasharray="8 5"
x1="22.37"
y1="35.54"
x2="74.27"
y2="25.2"
/>
<line
class="spray-line"
stroke="#777777"
stroke-dasharray="8 5"
x1="24.21"
y1="42.36"
x2="74.27"
y2="25.2"
/>
<line
class="spray-line"
stroke="#777777"
stroke-dasharray="8 5"
x1="24.31"
y1="7.78"
x2="74.27"
y2="25.2"
/>
<circle
fill="url(#grad1)"
stroke="none"
class="spray-bubble"
cx="25.43"
cy="12.97"
r="12.47"
/>
<circle
fill="url(#grad1)"
stroke="none"
class="spray-bubble"
cx="15.6"
cy="25.43"
r="15.1"
/>
<circle
fill="url(#grad1)"
stroke="none"
class="spray-bubble"
cx="33.24"
cy="37.13"
r="9.21"
/>
<circle
fill="url(#grad1)"
stroke="none"
class="spray-bubble"
cx="35.92"
cy="19.5"
r="11.89"
/>
<circle
fill="url(#grad1)"
stroke="none"
class="spray-bubble"
cx="18.82"
cy="34.45"
r="11.89"
/>
</g>
<path
d="M89,42h0a21.3,21.3,0,0,1,21.3,21.3v56.48a5.06,5.06,0,0,1-5.06,5.06H72.6a5.06,5.06,0,0,1-5.06-5.06V63.4A21.45,21.45,0,0,1,89,42Z"
fill="#fff"
/>
<rect
x="78.3"
y="36.64"
width="21.24"
height="6.15"
rx="1.93"
fill="#fff"
/>
<rect
x="76.33"
y="71.46"
width="33.96"
height="23.23"
fill="#cccccc"
/>
</g>
</g>
<g>
<line class="gear-connector" x1="0" x2="0" y1="0" y2="0" />
<g class="gears"></g>
</g>
<g class="grabbing-hand">
<g fill="#ffffff">
<rect
class="grabbing-hand-finger-closed"
x="44.79"
y="13.38"
width="8.42"
height="22.15"
rx="3.67"
transform="translate(20.57 71.26) rotate(-85.25)"
/>
<rect
class="grabbing-hand-finger-closed"
x="44.08"
y="39.17"
width="8.42"
height="21.47"
rx="3.67"
transform="translate(-5.44 93.9) rotate(-85.25)"
/>
<rect
class="grabbing-hand-finger-closed"
x="45.68"
y="30.71"
width="8.42"
height="22.57"
rx="3.67"
transform="matrix(0.08, -1, 1, 0.08, 3.91, 88.24)"
/>
<rect
class="grabbing-hand-finger-closed"
x="44.98"
y="22.21"
width="8.42"
height="22.57"
rx="3.67"
transform="matrix(0.08, -1, 1, 0.08, 11.74, 79.74)"
/>
<path
class="grabbing-hand-finger-closed"
d="M32.18,27.42c5,6.46,13.22,15.06,17.76,12.81,4.18-2.07.69-6-6.66-15.74C38.46,18.1,30.69,17.1,24.1,24"
/>
</g>
</g>
<g class="spiral-container">
<path stroke-width=".8" class="spiral-path" d="" />
</g>
<g class="weight-big-container">
<line x1="14" x2="60" y1="14" y2="14"></line>
<line x1="14" x2="60" y1="14" y2="55"></line>
<circle cx="14" cy="14" r="5" fill="#000000" stroke="none" />
<g class="weight-big" stroke="none">
<path
d="M25.5,16.7c.2-.6.5-1.3.7-2C31.1,3.1,23.2,0,14.3,0S-1.6,4.2,2.4,14.7a22.5,22.5,0,0,1,.8,2.4A14.4,14.4,0,0,0,0,26.2c0,8,6.5,11.6,14.5,11.6S29,34.2,29,26.2A14.6,14.6,0,0,0,25.5,16.7ZM14.4,5c5.6,0,9.3,1.9,7.1,8.5a13.5,13.5,0,0,0-7-1.8,14.6,14.6,0,0,0-7.2,1.9C5.5,7.5,8.8,5,14.4,5Z"
fill="#231f20"
/>
<path
d="M15.1,15.6l-1.8-.2a9.2,9.2,0,0,0-9.1,9.2,6.2,6.2,0,0,0,.2,1.9A13.3,13.3,0,0,1,15.1,15.6Z"
fill="#fff"
/>
</g>
</g>
<g class="scales-container">
<defs>
<marker
id="ball"
viewBox="0 0 10 10"
refX="5"
refY="5"
markerUnits="strokeWidth"
markerWidth="5"
markerHeight="5"
orient="auto"
>
<circle cx="5" cy="5" r="3" fill="#000" />
</marker>
</defs>
<rect
x="10"
y="-19"
width="30"
height="90"
rx="15"
ry="15"
stroke-width="10"
stroke="#ccc"
/>
<rect
class="timing-chain"
x="10"
y="-19"
width="30"
height="90"
rx="15"
ry="15"
stroke="#fff"
/>
<rect
x="-31"
y="-19"
width="30"
height="144"
rx="15"
ry="15"
stroke-width="10"
stroke="#ccc"
/>
<rect
class="timing-chain"
x="-31"
y="-19"
width="30"
height="144"
rx="15"
ry="15"
stroke="#fff"
/>
<g class="reels-connector">
<rect x="-8" y="3.2" width="25" height="10" rx="5" ry="5" />
<circle cx="-1" cy="8.5" r="3" fill="#000" stroke="none" />
<circle cx="9.9" cy="8.5" r="3" fill="#000" stroke="none" />
</g>
<g class="car-weight-connector">
<rect x="-36" y="97" width="10" height="95" rx="5" ry="5" />
<circle cx="-31" cy="103" r="3" fill="#000" stroke="none" />
<circle cx="-31" cy="186" r="3" fill="#000" stroke="none" />
</g>
<line
class="scales-moving-line"
x1="147.6"
y1="30.52"
x2="40"
y2="12"
stroke-width="2"
marker-start="url(#ball)"
marker-end="url(#ball)"
/>
<path
fill="#000000"
d="M102.45,30.68,92,20.26c-9.89,9.9-9.89,10.47-9.89,10.47Z"
/>
</g>
<g class="car-container">
<g>
<g class="car">
<circle cx="17" cy="88" r="5" />
<circle cx="17" cy="88" r="2" fill="#000" />
<circle cx="32" cy="88" r="5" />
<circle cx="32" cy="88" r="2" fill="#000" />
<path d="M10,65 h30 l-5,15 h-20 l-5,-15 " fill="#000" />
</g>
<line x1="-51" y1="95" x2="145" y2="95" />
</g>
</g>
</svg>
</div>
<script src="https://unpkg.com/gsap@3/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>
CSS Code
body {
padding: 0;
margin: 0;
font-family: sans-serif;
background-color: #FAF9F6;
}
.container {
position: fixed;
top: 38%;
left: 50%;
transform: translate(-50%, -50%);
}
svg,
.form-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.form-container {
width: 270px;
}
svg {
width: 1000px;
pointer-events: none;
}
.form-container .form-row {
width: 100%;
height: 60px;
display: flex;
align-items: center;
justify-content: flex-start;
}
.form-container .form-row input {
width: 100%;
height: 30px;
margin: 0;
padding: 5px;
outline: none;
border: 2px solid #dddddd;
}
.form-container .form-row input.valid {
border-color: #000000;
}
.form-container .form-row input[type="checkbox"] {
width: 20px;
height: 20px;
margin: 0 10px 0 0;
padding: 0;
border: 2px solid #dddddd;
}
.form-container .form-row input[type="submit"] {
height: 40px;
cursor: pointer;
border: none;
background-color: #eeeeee;
/*pointer-events: none;*/
}
/*.form-container .form-row input[type="submit"].valid {*/
/* pointer-events: auto;*/
/*}*/
.form-container input[type="submit"]:hover {
background-color: #dddddd;
}
.form-container label,
.form-container input,
.form-container input::placeholder {
font-size: 15px;
font-family: inherit;
}
svg {
stroke-width: 1.2px;
/*stroke: #222245;*/
stroke: #000000;
fill: none
}
Java Script Code
const containerEl = document.querySelector('.container');
const checkboxEl = document.querySelector('.form-container .form-row input[type="checkbox"]');
const nameEl = document.querySelector('.form-container .form-row input[name="name"]');
const emailEl = document.querySelector('.form-container .form-row input[name="email"]');
const submitBtn = document.querySelector('.form-container .form-row input[type="submit"]');
const sprayer = document.querySelector('.sprayer');
const sprayHandContainer = document.querySelector('.spray-hand-container');
const sprayLines = Array.from(document.querySelectorAll('.spray-line'));
const sprayBubbles = Array.from(document.querySelectorAll('.spray-bubble'));
const pushingHand = document.querySelector('.pushing-hand');
const sprayerHead = document.querySelector('.sprayer-head');
const gearsContainer = document.querySelector('svg .gears');
const gearConnector = document.querySelector('.gear-connector');
const pullSystemContainer = document.querySelector('.pull-system');
const checkboxPullLine = document.querySelector('.checkbox-pull-line');
const checkboxPullCircle = document.querySelector('.checkbox-pull-circle');
const btnPullLine = document.querySelector('.submit-btn-connector');
const btnHandlerCircle = document.querySelector('.submit-btn-circle');
const spiralContainer = document.querySelector('.spiral-container');
const weightBigContainer = document.querySelector('.weight-big-container');
const scalesContainer = document.querySelector('.scales-container');
const scalesLine = document.querySelector('.scales-moving-line');
const weightBig = document.querySelector('.weight-big');
const spiralPath = document.querySelector('.spiral-path');
const carContainer = document.querySelector('.car-container');
const car = document.querySelector('.car');
const carInclineWrapper = document.querySelector('.car-container g');
const timingChains = Array.from(document.querySelectorAll('.timing-chain'));
const reelsConnector = document.querySelector('.reels-connector');
const carWeightConnector = document.querySelector('.car-weight-connector');
const grabbingHand = document.querySelectorAll('.grabbing-hand');
const grabbingHandOpenFingers = Array.from(document.querySelectorAll('.grabbing-hand-finger-open'));
const grabbingHandClosedFingers = Array.from(document.querySelectorAll('.grabbing-hand-finger-closed'));
layoutPreparation();
scaleToFit();
window.onresize = scaleToFit;
function scaleToFit() {
const h = 800;
if (window.innerHeight < h) {
gsap.set(containerEl, {
scale: window.innerHeight / h,
transformOrigin: "50% 75%"
})
}
}
let sprayRepeatCounter = 0;
const state = {
handClosed: false,
sumbitBtnOnPlace: false,
sumbitBtnTextOpacity: 0,
pullProgress: 0
}
let nameValid = false;
let emailValid = false;
const emailTl = createEmailTl();
const gearsTls = createGearsTimelines();
createPullingTimeline(state.handClosed, checkboxEl.checked);
checkboxEl.addEventListener('change', () => {
createPullingTimeline(state.handClosed, checkboxEl.checked);
})
nameEl.addEventListener('input', () => {
nameValid = nameEl.value.length > 3;
if (nameValid) {
nameEl.classList.add("valid");
gearsTls.forEach(tl => {
if (tl.paused()) {
tl.play();
gsap.fromTo(tl, {
timeScale: 0
}, {
timeScale: 1
})
}
})
} else {
nameEl.classList.remove("valid");
gearsTls.forEach(tl => {
if (!tl.paused()) {
gsap.to(tl, {
timeScale: 0,
onComplete: () => {
tl.pause();
}
})
}
})
sprayRepeatCounter = 0;
gsap.to(submitBtn, {
duration: .3,
color: "rgba(0, 0, 0, " + 0 + ")"
})
}
})
emailEl.addEventListener('input', () => {
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
emailValid = emailRegex.test(emailEl.value);
if (emailValid) {
emailTl.play();
emailEl.classList.add("valid");
} else {
emailTl.reverse();
emailEl.classList.remove("valid");
}
})
submitBtn.addEventListener('click', () => {
if (emailValid && checkboxEl.checked && nameValid && sprayRepeatCounter > 1) {
gsap.to("svg > *", {
duration: .1,
opacity: 0,
stagger: {
each: 0.03,
from: 'random',
ease: 'none',
}
})
gsap.to(".form-row", {
delay: .4,
duration: .1,
opacity: 0,
stagger: .1
})
}
})
function layoutPreparation() {
gsap.set(pullSystemContainer, {
x: 375,
y: 646
})
gsap.set(sprayHandContainer, {
x: 700,
y: 621
})
gsap.set(sprayer, {
x: -59.5,
y: 53
})
gsap.set(carContainer, {
x: 190,
y: 802,
})
gsap.set(scalesContainer, {
x: 170,
y: 710,
})
gsap.set(grabbingHand, {
x: 297,
y: 830
})
gsap.set(grabbingHandClosedFingers, {
opacity: 0
})
gsap.set(spiralContainer, {
x: 305,
y: 435,
svgOrigin: "14 14",
scaleX: -1,
})
gsap.set(weightBigContainer, {
x: 305,
y: 435,
})
gsap.set(submitBtn, {
color: "rgba(0, 0, 0, " + 0 + ")"
})
gsap.set([sprayLines, sprayBubbles], {
opacity: 0
})
gsap.set(timingChains[0], {
attr: {
"stroke-width": "5",
"stroke-dasharray": "0 12",
}
})
gsap.set(timingChains[1], {
attr: {
"stroke-width": "5",
"stroke-dasharray": "0 12",
}
})
gsap.set(checkboxPullLine, {
attr: {
y1: -105,
y2: 44
}
});
gsap.set(submitBtn, {
transformOrigin: "100% 0%",
rotation: -90
})
gsap.set(checkboxPullCircle, {
y: 44
});
}
function updateSpiralPath(centerX, centerY, radius, coils, points, offset) {
let path = "";
let thetaMax = coils * 2 * Math.PI;
const awayStep = radius / thetaMax;
const chord = 2 * Math.PI / points;
thetaMax -= offset * points * chord;
for (let theta = 0; theta <= thetaMax; theta += chord) {
const away = awayStep * theta;
const x = centerX + Math.cos(theta) * away;
const y = centerY + Math.sin(theta) * away;
if (theta === 0) {
path += `M${x},${y}`;
} else {
const prevAway = awayStep * (theta - chord);
const arcRadius = (away + prevAway) / 2;
path += ` A${arcRadius},${arcRadius} 0 0,1 ${x},${y}`;
}
}
const outerAngle = thetaMax + .5 * Math.PI;
const outerLength = 50 + 25 * offset
const endPoint = [
Math.cos(outerAngle) * outerLength,
Math.sin(outerAngle) * outerLength,
]
path += (' l' + endPoint[0] + ',' + endPoint[1]);
gsap.set(spiralPath, {
attr: {
d: path
},
})
gsap.set(weightBig, {
x: -47 + 3 * offset,
y: 12 + outerLength
})
}
function createEmailTl() {
const spiralTurnsNumber = 8;
const spiralProgress = {v: 0}
const hammerTimeStart = 1.85;
const fingersDelay = .5;
const fingersTimeDelta = .03;
const tl = gsap.timeline({
paused: true,
defaults: {
ease: "none",
duration: 2
},
onUpdate: () => {
updateSpiralPath(14, 14, 45, 17, 200, spiralTurnsNumber * spiralProgress.v);
},
})
.to(spiralProgress, {
v: 1
}, 0)
.to(spiralContainer, {
rotation: -spiralTurnsNumber * 360,
}, 0)
.fromTo(scalesLine, {
rotation: -20,
svgOrigin: "92 20"
}, {
duration: .15,
rotation: -1,
svgOrigin: "92 20"
}, hammerTimeStart)
.fromTo(timingChains[0], {
attr: {
"stroke-dashoffset": 2
}
}, {
duration: .15,
attr: {
"stroke-dashoffset": 20
}
}, hammerTimeStart)
.fromTo(timingChains[1], {
attr: {
"stroke-dashoffset": 24
}
}, {
duration: .15,
attr: {
"stroke-dashoffset": 6
}
}, hammerTimeStart)
.to(reelsConnector, {
duration: .15,
y: 18
}, hammerTimeStart)
.to(carWeightConnector, {
duration: .15,
y: -18
}, hammerTimeStart)
.to(carInclineWrapper, {
duration: .15,
rotation: 6,
svgOrigin: "120 93"
}, hammerTimeStart)
.fromTo(car, {
x: -50,
}, {
duration: .6,
x: 95,
ease: "power2.in",
}, hammerTimeStart)
for (let i = 0; i < 5; i++) {
tl
.set(grabbingHandOpenFingers[i], {
opacity: 0
}, hammerTimeStart + fingersDelay + fingersTimeDelta * (i + 1))
.set(grabbingHandClosedFingers[i], {
opacity: 1
}, hammerTimeStart + fingersDelay + fingersTimeDelta * (i + 1))
}
tl
.fromTo(state, {
handClosed: false
}, {
duration: .01,
handClosed: true
}, ">")
.to(grabbingHand, {
duration: fingersTimeDelta * 5,
x: "+=20"
}, hammerTimeStart + fingersDelay)
tl.progress(0.001);
return tl;
}
function createGearsTimelines() {
const tls = []
const params = {
baseSize: 15,
pitch: 11,
teethCurve: .6,
startPos: {x: 634, y: 389},
speed: .2
}
const data = [{
angle: 0, teethNumber: 10, hasHole: true
}, {
angle: -.5, teethNumber: 32, hasHole: true
}, {
angle: 1.65, teethNumber: 12, hasHole: false
}];
const handleRadius = 14;
const gears = [];
data.forEach((d, dIdx) => {
const radius = (d.teethNumber * params.baseSize) / (2 * Math.PI);
let x, y, startAngle;
if (dIdx === 0) {
startAngle = 0;
x = params.startPos.x;
y = params.startPos.y;
} else {
const parent = gears[dIdx - 1];
const size = parent.teethNumber / d.teethNumber;
x = parent.center.x + Math.cos(d.angle) * (parent.radius + radius);
y = parent.center.y + Math.sin(d.angle) * (parent.radius + radius);
startAngle = (1 + size) * d.angle - size * parent.angle;
}
const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
gearsContainer.appendChild(group);
group.appendChild(path);
const gear = {
idx: dIdx,
center: {x, y},
radius,
angle: startAngle,
teethNumber: d.teethNumber,
hasHole: d.hasHole,
toothAngle: 2 * Math.PI / d.teethNumber,
toothCurveAngle: params.teethCurve / d.teethNumber,
group
}
const rOut = gear.radius + .25 * params.pitch;
const rIn = rOut - .75 * params.pitch;
let pathD = "M" + (gear.center.x + Math.cos(gear.angle - gear.toothAngle + gear.toothCurveAngle) * rOut) + ", " + (gear.center.y + Math.sin(gear.angle - gear.toothAngle + gear.toothCurveAngle) * rOut) + " ";
for (let a = gear.angle; a < (gear.angle + 2 * Math.PI - .5 * gear.toothAngle); a += gear.toothAngle) {
const pa = (a - .5 * gear.toothAngle);
pathD += ("L" + (gear.center.x + Math.cos(pa - gear.toothCurveAngle) * rOut) + ", " + (gear.center.y + Math.sin(pa - gear.toothCurveAngle) * rOut) + " ");
pathD += ("L" + (gear.center.x + Math.cos(pa) * rIn) + ", " + (gear.center.y + Math.sin(pa) * rIn) + " ");
pathD += ("L" + (gear.center.x + Math.cos(a) * rIn) + ", " + (gear.center.y + Math.sin(a) * rIn) + " ");
pathD += ("L" + (gear.center.x + Math.cos(a + gear.toothCurveAngle) * rOut) + ", " + (gear.center.y + Math.sin(a + gear.toothCurveAngle) * rOut) + " ");
}
if (gear.hasHole) {
const holeRadius = .5 * rIn;
pathD += ("M" + (gear.center.x - holeRadius) + ", " + (gear.center.y) + " ");
pathD += `A ${holeRadius} ${holeRadius} 1 1 0 ${gear.center.x + holeRadius} ${gear.center.y}`;
pathD += `A ${holeRadius} ${holeRadius} 1 1 0 ${gear.center.x - holeRadius} ${gear.center.y}`;
}
if (dIdx === 0) {
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
gsap.set(circle, {
attr: {
cx: gear.center.x,
cy: gear.center.y,
r: 5,
fill: "#000000"
}
})
gearsContainer.appendChild(circle);
gsap.set(path, {
attr: {
fill: "#000000",
"fill-opacity": .25
}
})
} else if (dIdx === (data.length - 1)) {
gsap.set(path, {
attr: {
fill: "#000000",
"fill-opacity": .25
}
})
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
gsap.set(circle, {
attr: {
cx: gear.center.x + handleRadius,
cy: gear.center.y,
r: 5,
fill: "#000000"
}
})
gear.group.appendChild(circle);
}
path.setAttribute("d", pathD);
const tl = gsap.timeline({
repeat: -1,
paused: true,
})
.to(group, {
duration: params.speed * gear.teethNumber,
rotation: 360 * (gear.idx % 2 ? -1 : 1),
svgOrigin: gear.center.x + " " + gear.center.y,
ease: "none",
});
if (dIdx === (data.length - 1)) {
tl.eventCallback("onUpdate", () => {
const angle = tl.progress() * 2 * Math.PI;
const deltaY = Math.sin(angle) * handleRadius;
gsap.set(pushingHand, {
y: deltaY,
})
if (deltaY > 8) {
const d = Math.max(0, deltaY - 8);
gsap.set(sprayerHead, {
y: d
})
let sprayProgress = Math.max(0, tl.progress() - .1);
sprayProgress *= (1 / .2);
let bubblesOpacity = (sprayProgress > 1) ? 0 : sprayProgress;
bubblesOpacity *= (1 - Math.pow(bubblesOpacity, 8));
const textProgress = Math.pow(sprayProgress / 1.5, 6);
if (!state.sumbitBtnOnPlace) {
state.sumbitBtnTextOpacity = (sprayRepeatCounter - 1) * .3 + .3 * textProgress;
state.sumbitBtnTextOpacity = Math.pow(state.sumbitBtnTextOpacity, 2);
}
gsap.set(submitBtn, {
color: "rgba(0, 0, 0, " + state.sumbitBtnTextOpacity + ")"
})
gsap.set(sprayLines, {
attr: {
"stroke-dashoffset": 70 * sprayProgress
},
opacity: Math.pow(bubblesOpacity, 2)
})
sprayBubbles.forEach((b, bIdx) => {
gsap.set(b, {
x: 25 * (1 - sprayProgress) * (1 + .1 * bIdx),
scale: .5 + 1.4 * Math.pow(sprayProgress, 2),
transformOrigin: "center center",
opacity: bubblesOpacity
})
})
}
gsap.set(gearConnector, {
attr: {
x1: gear.center.x + handleRadius * Math.cos(angle),
y1: gear.center.y + handleRadius * Math.sin(angle),
x2: 700 + 18,
y2: 646 - 100 + deltaY
}
})
});
tl.eventCallback("onRepeat", () => {
if (!state.sumbitBtnOnPlace) {
sprayRepeatCounter++;
}
});
}
tl.progress(0.6)
tls.push(tl);
gears.push(gear);
})
return tls;
}
function createPullingTimeline(isFixed, BtnPulled) {
let tl = gsap.timeline({
// paused: true,
defaults: {
ease: "power1.inOut",
duration: 1
},
onUpdate: animatePullingLine
});
if (isFixed && BtnPulled) {
tl
.to(state, {
pullProgress: 1
}, 0)
.to(submitBtn, {
rotation: 0
}, 0)
.to(state, {
duration: .1,
sumbitBtnOnPlace: 1
}, .9)
.to(checkboxPullLine, {
attr: {y2: 44 - 130}
}, 0)
.to(checkboxPullCircle, {
y: 44 - 130
}, 0)
} else if (!isFixed && BtnPulled) {
tl
.to(state, {
pullProgress: 1
}, 0)
.to(checkboxPullLine, {
attr: {y2: 44 - 130}
}, 0)
.to(checkboxPullCircle, {
y: 44 - 130
}, 0)
} else if (isFixed && !BtnPulled) {
tl
.to(state, {
pullProgress: 0
}, 0)
.to(submitBtn, {
rotation: -90
}, 0)
.to(state, {
duration: .1,
sumbitBtnOnPlace: 0
}, 0)
.to(checkboxPullLine, {
attr: {y2: 44}
}, 0)
.to(checkboxPullCircle, {
y: 44
}, 0)
} else if (!isFixed && !BtnPulled) {
tl
.to(state, {
pullProgress: 0
}, 0)
.to(checkboxPullLine, {
attr: {y2: 44}
}, 0)
.to(checkboxPullCircle, {
y: 44
}, 0)
}
function animatePullingLine() {
const buttonOriginPoint = [260, -76];
const btnWidth = 270;
const deg = (gsap.getProperty(submitBtn, "rotation") - 4) * Math.PI / 180;
const btnEnd = [
buttonOriginPoint[0] - (btnWidth - 20) * Math.cos(deg),
buttonOriginPoint[1] - (btnWidth - 20) * Math.sin(deg),
]
gsap.set(btnHandlerCircle, {
attr: {
cx: btnEnd[0],
cy: btnEnd[1]
}
})
const handle = 7;
const r = 10;
let btnPullLinePath = "M" + (-r - handle) + "," + (250 - (isFixed ? 0 : state.pullProgress * 300));
btnPullLinePath += "h" + (2 * handle);
btnPullLinePath += "h" + (-handle);
btnPullLinePath += " V" + (44 - state.pullProgress * 130);
const slideAngle = .3 * Math.PI * (1 - (isFixed ? 1 : .5) * state.pullProgress);
const dx = r * Math.cos(slideAngle);
const dy = -r * Math.sin(slideAngle);
btnPullLinePath += "a" + r + ', ' + r + " 0 0 1 " + (r + dx) + " " + dy;
btnPullLinePath += " L" + btnEnd[0] + "," + btnEnd[1];
gsap.set(btnPullLine, {
attr: {
d: btnPullLinePath
},
strokeWidth: 3
})
}
return tl;
}