mirror of
https://github.com/LukeHagar/website.git
synced 2025-12-09 12:57:48 +00:00
improve OSS animation
This commit is contained in:
@@ -1,288 +1,358 @@
|
||||
<script lang="ts">
|
||||
import { spring, type AnimationListOptions, type SpringOptions } from 'motion';
|
||||
import { animation, createScrollHandler, scroll, type Animation } from '.';
|
||||
import { toScale, type Scale } from '$lib/utils/toScale';
|
||||
import { spring, type AnimationListOptions, type SpringOptions } from 'motion';
|
||||
import { animation, createScrollHandler, scroll, type Animation } from '.';
|
||||
import { toScale, type Scale } from '$lib/utils/toScale';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
const springOptions: SpringOptions = { stiffness: 58.78, mass: 1, damping: 17.14 };
|
||||
const animationOptions: AnimationListOptions = {
|
||||
x: { easing: spring(springOptions) },
|
||||
y: { easing: spring(springOptions) }
|
||||
};
|
||||
const animations: {
|
||||
mobile: {
|
||||
main: Animation;
|
||||
reversed: Animation;
|
||||
};
|
||||
desktop: {
|
||||
main: Animation;
|
||||
reversed: Animation;
|
||||
};
|
||||
}[] = [
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-discord', { x: 0, y: 0, rotate: 1 }, animationOptions),
|
||||
reversed: animation('#oss-discord', { y: 1200, x: 0, rotate: 1 }, animationOptions)
|
||||
},
|
||||
desktop: {
|
||||
main: animation('#oss-discord', { x: 20, y: '-80vh', rotate: 15 }, animationOptions),
|
||||
reversed: animation('#oss-discord', { x: -100, y: '0vh', rotate: 15 }, animationOptions)
|
||||
}
|
||||
},
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-github', { x: 0, y: -10, rotate: -2 }, animationOptions),
|
||||
reversed: animation('#oss-github', { y: 1200, x: 10, rotate: -2 }, animationOptions)
|
||||
},
|
||||
desktop: {
|
||||
main: animation('#oss-github', { x: -100, y: '-55vh', rotate: 6.26 }, animationOptions),
|
||||
reversed: animation('#oss-github', { x: 0, y: '0vh', rotate: 6.26 }, animationOptions)
|
||||
}
|
||||
},
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-twitter', { x: 0, y: 10, rotate: -3 }, animationOptions),
|
||||
reversed: animation('#oss-twitter', { y: 1200, x: -10, rotate: -3 }, animationOptions)
|
||||
},
|
||||
desktop: {
|
||||
main: animation('#oss-twitter', { x: 100, y: '-70vh', rotate: -15 }, animationOptions),
|
||||
reversed: animation('#oss-twitter', { x: 0, y: '0vh', rotate: -15 }, animationOptions)
|
||||
}
|
||||
},
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-youtube', { x: 0, y: 5, rotate: 2 }, animationOptions),
|
||||
reversed: animation('#oss-youtube', { y: 1200, x: -5, rotate: 2 }, animationOptions)
|
||||
},
|
||||
desktop: {
|
||||
main: animation('#oss-youtube', { x: -100, y: '-55vh', rotate: -3.77 }, animationOptions),
|
||||
reversed: animation('#oss-youtube', { x: 0, y: '0vh', rotate: -3.77 }, animationOptions)
|
||||
}
|
||||
},
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-commits', { x: 0, y: -4, rotate: -1 }, animationOptions),
|
||||
reversed: animation('#oss-commits', { y: 1200, x: 4, rotate: -1 }, animationOptions)
|
||||
},
|
||||
desktop: {
|
||||
main: animation('#oss-commits', { x: 100, y: '-80vh', rotate: -10.2 }, animationOptions),
|
||||
reversed: animation('#oss-commits', { x: 0, y: '0vh', rotate: -10.2 }, animationOptions)
|
||||
}
|
||||
}
|
||||
];
|
||||
const springOptions: SpringOptions = { stiffness: 58.78, mass: 1, damping: 17.14 };
|
||||
const animationOptions: AnimationListOptions = {
|
||||
x: { easing: spring(springOptions) },
|
||||
y: { easing: spring(springOptions) }
|
||||
};
|
||||
const animations: {
|
||||
mobile: {
|
||||
main: Animation;
|
||||
reversed: Animation;
|
||||
};
|
||||
desktop: {
|
||||
main: Animation;
|
||||
reversed: Animation;
|
||||
};
|
||||
}[] = [
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-discord', { x: 0, y: 0, rotate: 1 }, animationOptions),
|
||||
reversed: animation('#oss-discord', { y: 1200, x: 0, rotate: 1 }, animationOptions)
|
||||
},
|
||||
desktop: {
|
||||
main: animation(
|
||||
'#oss-discord',
|
||||
{ x: 20, y: '-80vh', rotate: 15 },
|
||||
animationOptions
|
||||
),
|
||||
reversed: animation(
|
||||
'#oss-discord',
|
||||
{ x: -100, y: '0vh', rotate: 15 },
|
||||
animationOptions
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-github', { x: 0, y: -10, rotate: -2 }, animationOptions),
|
||||
reversed: animation('#oss-github', { y: 1200, x: 10, rotate: -2 }, animationOptions)
|
||||
},
|
||||
desktop: {
|
||||
main: animation(
|
||||
'#oss-github',
|
||||
{ x: -100, y: '-55vh', rotate: 6.26 },
|
||||
animationOptions
|
||||
),
|
||||
reversed: animation(
|
||||
'#oss-github',
|
||||
{ x: 0, y: '0vh', rotate: 6.26 },
|
||||
animationOptions
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-twitter', { x: 0, y: 10, rotate: -3 }, animationOptions),
|
||||
reversed: animation(
|
||||
'#oss-twitter',
|
||||
{ y: 1200, x: -10, rotate: -3 },
|
||||
animationOptions
|
||||
)
|
||||
},
|
||||
desktop: {
|
||||
main: animation(
|
||||
'#oss-twitter',
|
||||
{ x: 100, y: '-70vh', rotate: -15 },
|
||||
animationOptions
|
||||
),
|
||||
reversed: animation(
|
||||
'#oss-twitter',
|
||||
{ x: 0, y: '0vh', rotate: -15 },
|
||||
animationOptions
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-youtube', { x: 0, y: 5, rotate: 2 }, animationOptions),
|
||||
reversed: animation('#oss-youtube', { y: 1200, x: -5, rotate: 2 }, animationOptions)
|
||||
},
|
||||
desktop: {
|
||||
main: animation(
|
||||
'#oss-youtube',
|
||||
{ x: -100, y: '-55vh', rotate: -3.77 },
|
||||
animationOptions
|
||||
),
|
||||
reversed: animation(
|
||||
'#oss-youtube',
|
||||
{ x: 0, y: '0vh', rotate: -3.77 },
|
||||
animationOptions
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
mobile: {
|
||||
main: animation('#oss-commits', { x: 0, y: -4, rotate: -1 }, animationOptions),
|
||||
reversed: animation('#oss-commits', { y: 1200, x: 4, rotate: -1 }, animationOptions)
|
||||
},
|
||||
desktop: {
|
||||
main: animation(
|
||||
'#oss-commits',
|
||||
{ x: 100, y: '-80vh', rotate: -10.2 },
|
||||
animationOptions
|
||||
),
|
||||
reversed: animation(
|
||||
'#oss-commits',
|
||||
{ x: 0, y: '0vh', rotate: -10.2 },
|
||||
animationOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
function isMobile(): boolean {
|
||||
return globalThis?.window?.innerWidth < 1024;
|
||||
}
|
||||
function isMobile(): boolean {
|
||||
if (typeof window === 'undefined') return false;
|
||||
return window?.innerWidth < 1024;
|
||||
}
|
||||
|
||||
const animScale: Scale = [0, animations.length - 1];
|
||||
const percentScale: Scale = [0.1, 0.9];
|
||||
const scrollHandler = createScrollHandler(
|
||||
animations.map(({ mobile, desktop }, i) => {
|
||||
return {
|
||||
percentage: isMobile() ? toScale(i, animScale, percentScale) : 0.1,
|
||||
whenAfter() {
|
||||
const { main, reversed } = isMobile() ? mobile : desktop;
|
||||
const animScale: Scale = [0, animations.length - 1];
|
||||
const percentScale: Scale = [0.1, 0.9];
|
||||
const scrollHandler = createScrollHandler(
|
||||
animations.map(({ mobile, desktop }, i) => {
|
||||
return {
|
||||
percentage: isMobile() ? toScale(i, animScale, percentScale) : 0.1,
|
||||
whenAfter() {
|
||||
const { main, reversed } = isMobile() ? mobile : desktop;
|
||||
|
||||
main.play();
|
||||
return reversed.play;
|
||||
}
|
||||
};
|
||||
})
|
||||
);
|
||||
main.play();
|
||||
return reversed.play;
|
||||
}
|
||||
};
|
||||
})
|
||||
);
|
||||
</script>
|
||||
|
||||
<div
|
||||
id="open-source"
|
||||
use:scroll
|
||||
on:aw-scroll={({ detail }) => {
|
||||
const { percentage } = detail;
|
||||
scrollHandler(percentage);
|
||||
}}
|
||||
on:aw-resize={({ detail }) => {
|
||||
scrollHandler.reset();
|
||||
const { percentage } = detail;
|
||||
id="open-source"
|
||||
use:scroll
|
||||
on:aw-scroll={({ detail }) => {
|
||||
const { percentage } = detail;
|
||||
scrollHandler(percentage);
|
||||
}}
|
||||
on:aw-resize={({ detail }) => {
|
||||
scrollHandler.reset();
|
||||
const { percentage } = detail;
|
||||
|
||||
scrollHandler(percentage);
|
||||
}}
|
||||
scrollHandler(percentage);
|
||||
}}
|
||||
>
|
||||
<div class="sticky-wrapper">
|
||||
<h3 class="aw-display aw-u-color-text-primary">Powered by Open Source</h3>
|
||||
<div class="sticky-wrapper">
|
||||
<h3 class="aw-display aw-u-color-text-primary">Powered by Open Source</h3>
|
||||
|
||||
<div class="cards-wrapper">
|
||||
<a
|
||||
href="/discord"
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-discord"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span class="aw-icon-discord aw-u-font-size-40" aria-hidden="true" aria-label="Discord" />
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">17k+ Discord Members</div>
|
||||
</a>
|
||||
<div class="cards-wrapper">
|
||||
<a
|
||||
href="/discord"
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-discord"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span
|
||||
class="aw-icon-discord aw-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
aria-label="Discord"
|
||||
/>
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">17k+ Discord Members</div>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-github"
|
||||
href="https://github.com/appwrite/appwrite"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span class="aw-icon-github aw-u-font-size-40" aria-hidden="true" aria-label="GitHub" />
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">32k+ GitHub Stars</div>
|
||||
</a>
|
||||
<a
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-github"
|
||||
href="https://github.com/appwrite/appwrite"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span
|
||||
class="aw-icon-github aw-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
aria-label="GitHub"
|
||||
/>
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">32k+ GitHub Stars</div>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://twitter.com/appwrite"
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-twitter"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span class="aw-icon-x aw-u-font-size-40" aria-hidden="true" aria-label="Twitter" />
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">125k+ Twitter Followers</div>
|
||||
</a>
|
||||
<a
|
||||
href="https://twitter.com/appwrite"
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-twitter"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span
|
||||
class="aw-icon-x aw-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
aria-label="Twitter"
|
||||
/>
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">125k+ Twitter Followers</div>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://www.youtube.com/@Appwrite"
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-youtube"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span class="aw-icon-youtube aw-u-font-size-40" aria-hidden="true" aria-label="YouTube" />
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">3k+ Youtube Subscribers</div>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.youtube.com/@Appwrite"
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-youtube"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span
|
||||
class="aw-icon-youtube aw-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
aria-label="YouTube"
|
||||
/>
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">3k+ Youtube Subscribers</div>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-commits"
|
||||
href="https://github.com/appwrite/appwrite"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span class="aw-icon-github aw-u-font-size-40" aria-hidden="true" aria-label="GitHub" />
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">15k+ Code Commits</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<a
|
||||
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-commits"
|
||||
href="https://github.com/appwrite/appwrite"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<span
|
||||
class="aw-icon-github aw-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
aria-label="GitHub"
|
||||
/>
|
||||
</div>
|
||||
<div class="aw-title u-margin-block-start-auto">15k+ Code Commits</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
#open-source {
|
||||
height: 1500px;
|
||||
position: relative;
|
||||
}
|
||||
#open-source {
|
||||
min-height: 1500px;
|
||||
height: 250vh;
|
||||
position: relative;
|
||||
@media (min-width: 1024px) {
|
||||
height: 150vh;
|
||||
}
|
||||
}
|
||||
|
||||
.sticky-wrapper {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
overflow: hidden;
|
||||
.sticky-wrapper {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
overflow: hidden;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.25rem;
|
||||
padding-inline: 1.25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.25rem;
|
||||
padding-inline: 1.25rem;
|
||||
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
|
||||
&::after {
|
||||
background: linear-gradient(
|
||||
to top,
|
||||
hsl(var(--aw-color-background)) 0%,
|
||||
hsl(var(--aw-color-background) / 0) 5%
|
||||
);
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
&::after {
|
||||
background: linear-gradient(
|
||||
to top,
|
||||
hsl(var(--aw-color-background)) 0%,
|
||||
hsl(var(--aw-color-background) / 0) 5%
|
||||
);
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
.cards-wrapper {
|
||||
position: relative;
|
||||
height: 22.5rem;
|
||||
margin-top: 80px;
|
||||
}
|
||||
.cards-wrapper {
|
||||
position: relative;
|
||||
height: 22.5rem;
|
||||
margin-top: 80px;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
h3 {
|
||||
max-width: 61.375rem;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
h3 {
|
||||
max-width: 61.375rem;
|
||||
}
|
||||
|
||||
.cards-wrapper {
|
||||
position: absolute;
|
||||
height: 100vh;
|
||||
width: clamp(1024px, 90vw, 1440px);
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.cards-wrapper {
|
||||
position: absolute;
|
||||
height: 100vh;
|
||||
width: clamp(1024px, 90vw, 1440px);
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.oss-card {
|
||||
background: linear-gradient(
|
||||
106deg,
|
||||
rgba(255, 255, 255, 0.72) 0%,
|
||||
rgba(255, 255, 255, 0.8) 41.9%,
|
||||
rgba(255, 255, 255, 0.6) 100%
|
||||
);
|
||||
backdrop-filter: blur(10px);
|
||||
.oss-card {
|
||||
background: linear-gradient(
|
||||
106deg,
|
||||
rgba(255, 255, 255, 0.72) 0%,
|
||||
rgba(255, 255, 255, 0.8) 41.9%,
|
||||
rgba(255, 255, 255, 0.6) 100%
|
||||
);
|
||||
backdrop-filter: blur(10px);
|
||||
|
||||
--card-padding: 2rem;
|
||||
--card-padding: 2rem;
|
||||
|
||||
--w: clamp(306px, 50vw, 22.125rem);
|
||||
--h: 20.125rem;
|
||||
width: var(--w);
|
||||
height: var(--h);
|
||||
text-align: left;
|
||||
--w: clamp(306px, 50vw, 22.125rem);
|
||||
--h: 20.125rem;
|
||||
width: var(--w);
|
||||
height: var(--h);
|
||||
text-align: left;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
position: absolute;
|
||||
left: calc(50% - calc(var(--w) / 2));
|
||||
transform: translateX(-1200px);
|
||||
position: absolute;
|
||||
left: calc(50% - calc(var(--w) / 2));
|
||||
transform: translateX(-1200px);
|
||||
|
||||
[class*='icon'] {
|
||||
opacity: 48%;
|
||||
}
|
||||
}
|
||||
[class*='icon'] {
|
||||
opacity: 48%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.oss-card {
|
||||
left: unset;
|
||||
transform: unset;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.oss-card {
|
||||
left: unset;
|
||||
transform: unset;
|
||||
}
|
||||
|
||||
#oss-discord {
|
||||
bottom: -400px;
|
||||
left: 1%;
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
#oss-discord {
|
||||
bottom: -400px;
|
||||
left: 1%;
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
|
||||
#oss-github {
|
||||
bottom: -400px;
|
||||
left: 19%;
|
||||
}
|
||||
#oss-github {
|
||||
bottom: -400px;
|
||||
left: 19%;
|
||||
}
|
||||
|
||||
#oss-twitter {
|
||||
bottom: -400px;
|
||||
left: clamp(20%, 22vw, 29%);
|
||||
}
|
||||
#oss-twitter {
|
||||
bottom: -400px;
|
||||
left: clamp(20%, 22vw, 29%);
|
||||
}
|
||||
|
||||
#oss-youtube {
|
||||
bottom: -400px;
|
||||
left: clamp(64%, calc(1024px - 10vw), 70%);
|
||||
}
|
||||
#oss-youtube {
|
||||
bottom: -400px;
|
||||
left: clamp(64%, calc(1024px - 10vw), 70%);
|
||||
}
|
||||
|
||||
#oss-commits {
|
||||
bottom: -400px;
|
||||
right: 10%;
|
||||
}
|
||||
}
|
||||
#oss-commits {
|
||||
bottom: -400px;
|
||||
right: 10%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user