feat: implement index section 2

Co-authored-by: Sylvanysc <Sylvanysc@users.noreply.github.com>
Co-authored-by: xudeyu444 <xudeyu444@users.noreply.github.com>
Co-authored-by: 奕 <a18355849597@outlook.com>
This commit is contained in:
2025-05-30 01:05:59 +08:00
parent 2ba90f730b
commit 901a80d9a0
5 changed files with 170 additions and 2 deletions

13
app.vue
View File

@@ -44,7 +44,18 @@ onMounted(() => {
</script>
<template>
<ScrollPanel ref="scrollPanel" style="width: 100vw; height: 100vh">
<ScrollPanel
ref="scrollPanel"
style="width: 100vw; height: 100vh"
:pt="{
content: {
class: 'snap-y snap-mandatory scroll-smooth',
style: {
scrollDuration: '2s',
},
},
}"
>
<header
class="fixed w-full z-10 px-12"
:style="{ '--s-progress': sProgress }"

BIN
assets/images/index/s2d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

View File

@@ -40,7 +40,7 @@ export default defineNuxtConfig({
50: "#fdf2ef",
100: "#f7dcd5",
200: "#f0c6bc",
300: "#e6b0a3",
300: "#e9b0a3",
400: "#da998a",
500: "#cc8271",
600: "#ba6b58",

View File

@@ -123,6 +123,97 @@ onMounted(() => {
</div>
</div>
</section>
<section
class="flex flex-col justify-center items-center min-h-[80vh] gap-8 relative"
>
<div class="fixed top-0 left-0 w-full h-full z-[-1]">
<div
class="absolute top-0 left-0 w-full h-full flex pt-15 justify-between items-center s2d"
:style="{
transform: `rotate(${
(riro(range(-0.5, 0.5, sProgress - 1) + 0.5) - 0.5) * -60
}deg)`,
opacity:
1 -
Math.abs(riro(range(-0.5, 0.5, sProgress - 1) + 0.5) - 0.5) * 2,
}"
></div>
<div
class="absolute bottom-0 left-1/2 -translate-x-1/2 rounded-t-4xl px-6 pt-4 flex gap-6 from-(--p-primary-300) to-[transparent] bg-linear-to-b after:from-(transparent) after:from-50 after:to-(--s-to) after:bg-linear-to-b after:absolute after:top-0 after:left-0 after:w-full after:h-full after:z-2"
style="
--s-to: color-mix(in srgb, var(--s-background), transparent 20%);
"
:style="{
transform: `translateY(${
range(-0.5, 0.5, sProgress - 1) * -100
}%) scale(${1 + range(-0.5, 0.5, sProgress - 1) * 0.2})`,
opacity: 1 - Math.abs(range(-0.5, 0.5, sProgress - 1)) * 2,
}"
>
<div
class="flex flex-col items-center justify-between mt-2 mb-6 gap-5"
>
<h2
class="text-3xl text-(--p-primary-500) font-[KNYuanmo] tracking-widest"
>
SPARK
</h2>
<div
v-for="i in 3"
:key="i"
class="w-full rounded-full p-3 from-(--p-primary-400) to-(--p-primary-200) bg-linear-to-b"
></div>
</div>
<div class="flex flex-col gap-4 w-full">
<div class="flex gap-4 pl-2">
<div
v-for="i in 2"
:key="i"
class="p-3 rounded-full bg-(--p-primary-500)"
></div>
<div class="w-40 p-3 rounded-full bg-(--p-primary-500)"></div>
<div class="grow-1"></div>
<div
v-for="i in 3"
:key="i"
class="p-3 rounded-full bg-(--p-primary-500)"
></div>
</div>
<div
class="rounded-t-2xl p-4 flex gap-4 w-full from-(--p-primary-400) to-[transparent] bg-linear-to-b grow-1"
>
<div
v-for="i in 3"
:key="i"
class="w-45 h-27 rounded-xl flex items-center justify-center from-(--p-primary-500) to-(--p-primary-300) bg-linear-to-b"
>
<i
class="pi text-5xl! text-(--p-primary-600)"
:class="`pi-${['th-large', 'cog', 'thumbs-up'][i - 1]}`"
></i>
</div>
</div>
</div>
</div>
</div>
<h2 class="text-center text-6xl font-bold text-(--p-primary-color)">
星星之火可以燎原
</h2>
<p class="text-center text-xl leading-[2em]">
每个普通用户的需求反馈每名开发者的代码贡献每一次社区的互助分享<br />
都在为 Linux 桌面生态注入蓬勃活力<br />
我们深信人人为我我为人人以共享之火照亮开源之路<br />
您上传的应用可能成为他人工作的桥梁他人分享的工具也可能为您带来方便<br />
我们珍视开源世界的共建基因以微小而持久的善意融入这场共享长跑<br />
让技术普惠的星火在彼此照映中汇聚成光
</p>
<div class="h-24"></div>
</section>
<section></section>
<section></section>
<section></section>
@@ -137,6 +228,7 @@ onMounted(() => {
section {
width: 100%;
height: 100vh;
scroll-snap-align: start;
}
.s-dots {
@@ -207,4 +299,28 @@ section {
z-index: -1;
}
}
.s2d {
&::before {
content: "";
width: calc(64 * var(--spacing));
height: calc(128 * var(--spacing));
background-image: url("~/assets/images/index/s2d.avif");
background-image: url("~/assets/images/index/s2d.webp");
background-image: url("~/assets/images/index/s2d.png");
background-size: contain;
background-position: center;
}
&::after {
content: "";
width: calc(64 * var(--spacing));
height: calc(128 * var(--spacing));
background-image: url("~/assets/images/index/s2d.avif");
background-image: url("~/assets/images/index/s2d.webp");
background-image: url("~/assets/images/index/s2d.png");
background-size: contain;
background-position: center;
transform: rotate(180deg);
}
}
</style>

41
utils/index.ts Normal file
View File

@@ -0,0 +1,41 @@
export function range(start: number, end: number, x: number): number {
return Math.min(end, Math.max(start, x));
}
export function getCubicBezier(x1: number, y1: number, x2: number, y2: number) {
return (t: number) => {
const oneMinusT = 1 - t;
const oneMinusTSquared = oneMinusT * oneMinusT; // (1-t)^2
const oneMinusTCubed = oneMinusTSquared * oneMinusT; // (1-t)^3
const tSquared = t * t; // t^2
const tCubed = tSquared * t; // t^3
// Y(t) = P0y*(1-t)^3 + 3*P1y*t*(1-t)^2 + 3*P2y*t^2*(1-t) + P3y*t^3
const y =
0 * oneMinusTCubed +
3 * y2 * t * oneMinusTSquared +
3 * y1 * tSquared * oneMinusT +
1 * tCubed;
return y;
};
}
export function mergeTimingFunctions(
fn1: (t: number) => number,
fn2: (t: number) => number
): (t: number) => number {
return (t: number) => {
if (t < 0.5) {
return fn1(t * 2) / 2; // Scale down for first half
}
return fn2((t - 0.5) * 2) / 2 + 0.5; // Scale down for second half and offset
};
}
export const eieo = getCubicBezier(0.5, 0.0, 0.5, 1.0);
export const eieo2 = mergeTimingFunctions(eieo, eieo);
export const riro = getCubicBezier(0.0, 0.5, 1.0, 0.5);