Created
January 21, 2024 03:54
-
-
Save landsurveyorsunited/2f1fd49df23a61e554a083ffc56b73cc to your computer and use it in GitHub Desktop.
Web Gears ⚙️ (Scroll-driven animations)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<nav> | |
<a href="https://landsurveyorsunited.com" target="_blank"> | |
<img style="width:50px;"class="w-9" src="https://storage.ning.com/topology/rest/1.0/file/get/12222126291?profile=original" alt="Logo"> | |
</a> | |
</nav> | |
<div class="belt"></div> | |
<div class="gears"> | |
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 146 146"> | |
<path fill-rule="evenodd" clip-rule="evenodd" d="m0 68 13.306-1.094a59.756 59.756 0 0 1 2.202-11.126L3.643 49.683l3.827-9.238 12.705 4.079a60.097 60.097 0 0 1 6.308-9.424l-8.637-10.183 7.07-7.071 10.185 8.637a60.15 60.15 0 0 1 7.65-5.311L38.597 8.236l9.239-3.827 6.018 11.71a59.682 59.682 0 0 1 13.052-2.813L68 0h10l1.094 13.306a59.683 59.683 0 0 1 13.052 2.813l6.018-11.71 9.239 3.827-4.154 12.936a59.613 59.613 0 0 1 3.728 2.368 60.13 60.13 0 0 1 3.922 2.943l10.184-8.637 7.071 7.07-8.637 10.185a60.086 60.086 0 0 1 6.308 9.423l12.705-4.08 3.827 9.24-11.864 6.096a59.682 59.682 0 0 1 2.201 11.126L146 68v10l-13.306 1.094a59.762 59.762 0 0 1-2.201 11.126l11.864 6.097-3.827 9.238-12.705-4.079a60.134 60.134 0 0 1-6.18 9.267l-.051.063-.077.093 8.637 10.184-7.071 7.071-10.184-8.637a60.158 60.158 0 0 1-7.42 5.176l-.152.09-.078.045 4.154 12.936-9.239 3.827-6.018-11.71a59.67 59.67 0 0 1-13.052 2.813L78 146H68l-1.094-13.306a59.67 59.67 0 0 1-13.052-2.813l-6.018 11.71-9.239-3.827 4.154-12.936a60.132 60.132 0 0 1-7.65-5.311l-10.184 8.637-7.071-7.071 8.637-10.184a60.072 60.072 0 0 1-6.308-9.423L7.47 105.555l-3.827-9.238 11.864-6.097a59.733 59.733 0 0 1-2.201-11.126L0 78V68Zm73 23c9.941 0 18-8.059 18-18s-8.059-18-18-18-18 8.059-18 18 8.059 18 18 18Z" fill="currentColor" /> | |
</svg> | |
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"> | |
<path fill-rule="evenodd" clip-rule="evenodd" d="m68.001 10.593-8.587-6.107-6.59 6.458a32.084 32.084 0 0 0-6.063-1.93L45.307 0H34.693l-1.456 9.022a32.435 32.435 0 0 0-6.06 1.923l-6.591-6.458-8.587 6.106 4.24 8.135a31.65 31.65 0 0 0-3.745 5.044L3.28 22.34 0 32.22l8.312 4.141a30.607 30.607 0 0 0 .005 6.236L0 46.74l3.28 9.881 9.208-1.432a30.966 30.966 0 0 0 3.748 5.047l-4.238 8.131 8.588 6.107 6.59-6.457a32.083 32.083 0 0 0 5.89 1.892L34.692 80h10.614l1.63-10.099a32.441 32.441 0 0 0 5.722-1.816l7.38 7.23 8.586-6.107-4.745-9.106a31.655 31.655 0 0 0 3.626-4.914l9.214 1.433 3.28-9.88-8.312-4.142c.212-2.079.208-4.169-.005-6.235L80 32.22l-3.28-9.881-9.208 1.432a30.972 30.972 0 0 0-3.748-5.048l4.237-8.13ZM40 51c6.075 0 11-4.925 11-11s-4.925-11-11-11-11 4.925-11 11 4.925 11 11 11Z" fill="currentColor" /> | |
</svg> | |
</div> | |
<header> | |
<h1>Scroll to work 👉</h1> | |
</header> | |
<main> | |
<section> | |
<h2>Use scroll animation to rotate the gears.</h2> | |
<iframe id="iframe1" src="your-iframe-source-url-1.html" style="width:100%; height:100%;" loading="lazy" frameborder="0"></iframe> | |
<button onclick="toggleFullScreen('iframe1')">Full Screen</button> | |
</section> | |
<section> | |
<h2>Rotate the small gear twice (10 tooth).</h2> | |
<iframe id="iframe2" src="your-iframe-source-url-2.html" style="width:100%; height:100%;" loading="lazy" frameborder="0"></iframe> | |
<button onclick="toggleFullScreen('iframe2')">Full Screen</button> | |
</section> | |
<section> | |
<h2>Rotate the big gear 0.625 times that (16 tooth).</h2> | |
<iframe id="iframe3" src="your-iframe-source-url-3.html" style="width:100%; height:100%;" loading="lazy" frameborder="0"></iframe> | |
<button onclick="toggleFullScreen('iframe3')">Full Screen</button> | |
</section> | |
<section> | |
<h2>fin.</h2> | |
<iframe id="iframe4" src="your-iframe-source-url-4.html" style="width:100%; height:100%;" loading="lazy" frameborder="0"></iframe> | |
<button onclick="toggleFullScreen('iframe4')">Full Screen</button> | |
</section> | |
<section> | |
<h2>Use scroll animation to rotate the gears.</h2> | |
<iframe id="iframe1" src="your-iframe-source-url-1.html" style="width:100%; height:100%;" loading="lazy" frameborder="0"></iframe> | |
<button onclick="toggleFullScreen('iframe1')">Full Screen</button> | |
</section> | |
<section> | |
<h2>Rotate the small gear twice (10 tooth).</h2> | |
<iframe id="iframe2" src="your-iframe-source-url-2.html" style="width:100%; height:100%;" loading="lazy" frameborder="0"></iframe> | |
<button onclick="toggleFullScreen('iframe2')">Full Screen</button> | |
</section> | |
<section> | |
<h2>Rotate the big gear 0.625 times that (16 tooth).</h2> | |
<iframe id="iframe3" src="your-iframe-source-url-3.html" style="width:100%; height:100%;" loading="lazy" frameborder="0"></iframe> | |
<button onclick="toggleFullScreen('iframe3')">Full Screen</button> | |
</section> | |
<section> | |
<h2>fin.</h2> | |
<iframe id="iframe4" src="your-iframe-source-url-4.html" style="width:100%; height:100%;" loading="lazy" frameborder="0"></iframe> | |
<button onclick="toggleFullScreen('iframe4')">Full Screen</button> | |
</section> | |
</main> | |
<footer>jf © 2024 ┬┴┬┴┤•ᴥ•ʔ├┬┴┬┴</footer> | |
<script> | |
function toggleFullScreen(iframeId) { | |
var iframe = document.getElementById(iframeId); | |
if (!document.fullscreenElement) { | |
if (iframe.requestFullscreen) { | |
iframe.requestFullscreen(); | |
} else if (iframe.mozRequestFullScreen) { /* Firefox */ | |
iframe.mozRequestFullScreen(); | |
} else if (iframe.webkitRequestFullscreen) { /* Chrome, Safari & Opera */ | |
iframe.webkitRequestFullscreen(); | |
} else if (iframe.msRequestFullscreen) { /* IE/Edge */ | |
iframe.msRequestFullscreen(); | |
} | |
} else { | |
if (document.exitFullscreen) { | |
document.exitFullscreen(); | |
} else if (document.mozCancelFullScreen) { /* Firefox */ | |
document.mozCancelFullScreen(); | |
} else if (document.webkitExitFullscreen) { /* Chrome, Safari & Opera */ | |
document.webkitExitFullscreen(); | |
} else if (document.msExitFullscreen) { /* IE/Edge */ | |
document.msExitFullscreen(); | |
} | |
} | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import gsap from 'https://cdn.skypack.dev/gsap@3.12.0' | |
import ScrollTrigger from 'https://cdn.skypack.dev/gsap@3.12.0/ScrollTrigger' | |
if (!CSS.supports('animation-timeline: scroll()')) { | |
gsap.registerPlugin(ScrollTrigger) | |
/** | |
* Two animations. | |
* 1. Belt translation. | |
* 2. Gear rotation, | |
* */ | |
const bodyScroller = { | |
ease: 'none', | |
scrollTrigger: { | |
scroller: 'body', | |
scrub: true, | |
start: 0, | |
end: document.body.scrollHeight, | |
}, | |
} | |
// 1. Belt translation | |
const belt = document.querySelector('.belt') | |
gsap.to('.belt', { | |
translateY: | |
(parseInt( | |
getComputedStyle(document.documentElement).getPropertyValue( | |
'--gutter-size' | |
), | |
10 | |
) / | |
6) * | |
-20, | |
...bodyScroller | |
}) | |
// 2. Gear rotation | |
gsap.to('.gears svg', { | |
rotate: (index) => { | |
return index === 0 ? 720 * 10 / 16 * -1 : 720 | |
}, | |
...bodyScroller, | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@font-face { | |
font-family: 'Geist Sans'; | |
src: url('https://assets.codepen.io/605876/GeistVF.ttf') format('truetype'); | |
} | |
*, | |
*:after, | |
*:before { | |
box-sizing: border-box; | |
} | |
:root { | |
--gutter-size: 120px; | |
} | |
body { | |
min-height: 100vh; | |
font-family: "Geist Sans", "SF Pro Text", "SF Pro Icons", "AOS Icons", "Helvetica Neue", Helvetica, Arial, sans-serif, system-ui; | |
padding-inline: var(--gutter-size); | |
font-weight: 80; | |
color: hsl(0 0% 10%); | |
} | |
body::after { | |
content: ""; | |
width: var(--gutter-size); | |
position: fixed; | |
top: 0; | |
bottom: 0; | |
right: 0; | |
background: hsl(0 0% 80%); | |
} | |
.belt { | |
--color: white; | |
--size: calc(var(--gutter-size) / 6); | |
content: ""; | |
width: var(--size); | |
position: fixed; | |
top: 0; | |
left: calc(100% - var(--gutter-size)); | |
background: | |
linear-gradient(var(--color), var(--color)) 0 0 / calc(var(--size) / 2) var(--size) no-repeat repeat, | |
linear-gradient(-10deg, transparent 80%, var(--color) 81%) 0 0 / calc(var(--size) * 0.8) var(--size) no-repeat repeat, | |
linear-gradient(10deg, var(--color) 20%, transparent 21%) 0 0 / calc(var(--size) * 0.8) var(--size) no-repeat repeat; | |
filter: drop-shadow(0 0 6px hsl(0 0% 50%)); | |
clip-path: inset(0 -200% 0 0); | |
height: calc(100vh + (var(--size) * 20)); | |
z-index: 2; | |
} | |
header { | |
height: 100vh; | |
display: grid; | |
place-items: center; | |
} | |
section { | |
height: 100vh; | |
width: 100%; | |
display: grid; | |
place-items: center; | |
} | |
h2 { | |
font-size: clamp(2rem, 1vw + 1rem, 6rem); | |
font-weight: 80; | |
color:orange; | |
} | |
main { | |
width: 80ch; | |
max-width: 100%; | |
margin: 0 auto; | |
padding: 0 1rem; | |
} | |
.gears { | |
color: hsl(0 0% 40%); | |
position: fixed; | |
top: 0; | |
right: 0; | |
width: var(--gutter-size); | |
z-index: 2; | |
filter: drop-shadow(0 1px 2px hsl(0 0% 50%)); | |
} | |
h1 { | |
font-size: clamp(2rem, 6vw + 1rem, 12rem); | |
text-transform: uppercase; | |
font-family: Impact; | |
padding: 0 1rem; | |
color: white; | |
} | |
nav { | |
width: 48px; | |
position: fixed; | |
bottom: 2rem; | |
right: calc(var(--gutter-size) * 0.5); | |
z-index: 10; | |
translate: calc(50% + (var(--gutter-size) / 12)) 0; | |
opacity: 0.75; | |
} | |
nav a { | |
color: hsl(0 0% 10%); | |
} | |
footer { | |
padding: 2rem 1rem; | |
text-align: center; | |
} | |
/** | |
* 10 tooth vs. 16 tooth cog | |
* So the smaller moves at 1.6 times the rate and the bigger is 10 / 16 | |
* */ | |
.gears svg:first-of-type { | |
width: 96%; | |
position: absolute; | |
left: 100%; | |
translate: -80% -22%; | |
} | |
.gears svg:last-of-type { | |
width: 66%; | |
translate: 16% 102%; | |
position: absolute; | |
top: 0; | |
left: 0; | |
} | |
@media(max-width: 600px) { | |
:root { | |
--gutter-size: 56px; | |
} | |
body { | |
padding-inline: unset; | |
padding-right: var(--gutter-size); | |
} | |
} | |
@supports (animation-timeline: scroll()) { | |
.gears svg:first-of-type { | |
--end: calc((720 * (10 / 16)) * -1deg); | |
} | |
.gears svg:last-of-type { | |
--end: 720deg; | |
} | |
.gears svg { | |
animation: work both linear; | |
animation-timeline: scroll(); | |
} | |
@keyframes work { | |
to { rotate: var(--end, 360deg); } | |
} | |
.belt { | |
animation: belt both linear; | |
animation-timeline: scroll(); | |
} | |
@keyframes belt { | |
to { translate: 0 calc(var(--size) * -20); } | |
} | |
} | |
body { | |
background-color: #111827!important; | |
color: #FFF; | |
margin: 0; | |
padding: 0; | |
} | |
body { | |
min-height: 100vh; | |
display: grid; | |
place-items: center; | |
font-family: "SF Pro Text", "SF Pro Icons", "AOS Icons", "Helvetica Neue", Helvetica, Arial, sans-serif, system-ui; | |
background: hsl(0 0% 0%); | |
gap: 2rem; | |
} | |
body::before { | |
--line: hsl(0 0% 95% / 0.25); | |
content: ""; | |
height: 100vh; | |
width: 100vw; | |
position: fixed; | |
background: | |
linear-gradient(90deg, var(--line) 1px, transparent 1px 10vmin) 0 -5vmin / 10vmin 10vmin, | |
linear-gradient(var(--line) 1px, transparent 1px 10vmin) 0 -5vmin / 10vmin 10vmin; | |
mask: linear-gradient(-15deg, transparent 30%, white); | |
top: 0; | |
z-index: -1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment