mirror of
https://github.com/spark-store-project/spark-store-abyss
synced 2025-12-16 03:32:06 +08:00
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:
13
app.vue
13
app.vue
@@ -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
BIN
assets/images/index/s2d.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 174 KiB |
@@ -40,7 +40,7 @@ export default defineNuxtConfig({
|
||||
50: "#fdf2ef",
|
||||
100: "#f7dcd5",
|
||||
200: "#f0c6bc",
|
||||
300: "#e6b0a3",
|
||||
300: "#e9b0a3",
|
||||
400: "#da998a",
|
||||
500: "#cc8271",
|
||||
600: "#ba6b58",
|
||||
|
||||
116
pages/index.vue
116
pages/index.vue
@@ -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
41
utils/index.ts
Normal 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);
|
||||
Reference in New Issue
Block a user