778 lines
18 KiB
Plaintext
778 lines
18 KiB
Plaintext
---
|
||
export const prerender = false
|
||
|
||
// import BoringLayout from '../layout/BoringLayout.astro'
|
||
import FullLayoutV1 from '../layout/FullLayoutV1.astro'
|
||
import MainpageButton from '../components/MainpageButton.svelte'
|
||
import MainpageComments from '../components/MainpageComments.astro'
|
||
import MainpageTypewriter from '../components/MainpageTypewriter.svelte'
|
||
import { Image } from 'astro:assets'
|
||
import { Icon } from 'astro-icon/components'
|
||
import PassthemAvatar from '../assets/mainpage_avatars/passthem.png'
|
||
|
||
import { mainpageGetClick } from '../lib/apis/legacy/mainpage'
|
||
|
||
// 无用按钮的数字预注入
|
||
let initialClicks = 0
|
||
|
||
try {
|
||
const resp = await mainpageGetClick()
|
||
initialClicks = resp.data
|
||
} catch (e) {
|
||
console.error('在获取点击数量时失败了', e)
|
||
}
|
||
---
|
||
|
||
<FullLayoutV1 title="首页 - 小帕的小窝">
|
||
<!-- 就像写幻灯片一样的逻辑写它吧! -->
|
||
<section class="slide">
|
||
<!-- 自我介绍部分 -->
|
||
<div class="self-introduction">
|
||
<figure class="avatar">
|
||
<Image
|
||
src={PassthemAvatar}
|
||
alt="passthem 的头像,一个戴眼镜的男孩"
|
||
loading="lazy"
|
||
width={240}
|
||
height={240}
|
||
densities={[1.5, 2]}
|
||
/>
|
||
</figure>
|
||
<div class="descriptions">
|
||
<div class="motto">
|
||
<p>passthem¹</p>
|
||
<p>一个<MainpageTypewriter client:load />的</p>
|
||
<p>个人势创作者</p>
|
||
</div>
|
||
<div class="buttons">
|
||
<MainpageButton initialClicks={initialClicks} client:load />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="notation">
|
||
<p>¹我在各个平台的惯用 ID,开头字母大小写无所谓</p>
|
||
<p>
|
||
²头像由 <a href="https://space.bilibili.com/2017869">Yscao@bilibili</a> 绘制
|
||
</p>
|
||
<p>
|
||
³有人说这个配色像 <a
|
||
href="https://www.bilibili.com/video/av383664698/"
|
||
class="thsx">涂黑书信</a
|
||
>
|
||
</p>
|
||
<p class="animation-error-warning">
|
||
⁴你的系统设置中似乎禁用了动画效果,而 Firefox
|
||
在禁用动画效果时,网页的表现会很奇怪
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="slide">
|
||
<div class="slide-title-design1" aria-hidden="true">
|
||
<svg width="800" height="240" viewBox="0 0 800 240">
|
||
<text x="10" y="220" class="stroke-layer">留言</text>
|
||
<text x="0" y="210" class="main-layer">留言</text>
|
||
</svg>
|
||
</div>
|
||
<div class="slide-title-design2" aria-hidden="true">
|
||
<Icon name="mdi:comment-quote" />
|
||
</div>
|
||
<div class="comment-page-container">
|
||
<h1>来自大家的留言</h1>
|
||
<div class="comment-container">
|
||
<MainpageComments />
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="slide">
|
||
<div class="slide-title-design1" aria-hidden="true">
|
||
<svg width="800" height="240" viewBox="0 0 800 240">
|
||
<text x="10" y="220" class="stroke-layer">联络</text>
|
||
<text x="0" y="210" class="main-layer">联络</text>
|
||
</svg>
|
||
</div>
|
||
<div class="slide-title-design2" aria-hidden="true">
|
||
<Icon name="mdi:email" />
|
||
</div>
|
||
<div class="contact-container">
|
||
<h1>
|
||
<div class="text">联系我<div class="animation-before"></div></div><div
|
||
class="animation"
|
||
>
|
||
</div>
|
||
</h1>
|
||
<table>
|
||
<tbody>
|
||
<tr>
|
||
<th>Github</th>
|
||
<th><a href="https://github.com/passthem-desu">passthem-desu</a></th
|
||
>
|
||
</tr>
|
||
<tr>
|
||
<th>Wakatime</th>
|
||
<th><a href="https://wakatime.com/@passthem">@passthem</a></th>
|
||
</tr>
|
||
<tr>
|
||
<th>Youtube</th>
|
||
<th
|
||
><a href="https://www.youtube.com/@Passthem183">@Passthem183</a
|
||
></th
|
||
>
|
||
</tr>
|
||
<tr>
|
||
<th>OtoSite</th>
|
||
<th><a href="https://otomad.site/@passthem">@passthem</a></th>
|
||
</tr>
|
||
<tr>
|
||
<th>Email</th>
|
||
<th
|
||
><a href="mailto:passthem183@gmail.com">passthem183@gmail.com</a
|
||
></th
|
||
>
|
||
</tr>
|
||
<tr>
|
||
<th>Bilibili</th>
|
||
<th><a href="https://space.bilibili.com/92852604">passthem</a></th>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="slide">
|
||
<div class="slide-title-design1" aria-hidden="true">
|
||
<svg width="800" height="240" viewBox="0 0 800 240">
|
||
<text x="10" y="220" class="stroke-layer">友链</text>
|
||
<text x="0" y="210" class="main-layer">友链</text>
|
||
</svg>
|
||
</div>
|
||
<div class="slide-title-design2" aria-hidden="true">
|
||
<Icon name="mdi:link-variant" />
|
||
</div>
|
||
<h1>友情链接</h1>
|
||
<div class="friends">
|
||
{
|
||
[
|
||
[
|
||
'https://omega98.top/images/blog_avatar.jpg',
|
||
'https://omega98.top',
|
||
'核子的博客',
|
||
],
|
||
['https://www.tnot.top/logo.png', 'https://tnot.top', 'TNOT 的博客'],
|
||
[
|
||
'https://ruusuge.top/img/logo_hu_cc283ac364b1bc0b.png',
|
||
'https://ruusuge.top',
|
||
'ルース毛的博客',
|
||
],
|
||
[
|
||
'https://cdn.jsdelivr.net/gh/TransparentLC/transparentlc.github.io/img/avatar.jpg',
|
||
'https://akarin.dev',
|
||
'存在感消失的地方',
|
||
],
|
||
[
|
||
'https://wzq02.top/assets/icons/favicon-96x96.png',
|
||
'https://wzq02.top',
|
||
'wzq02 的博客',
|
||
],
|
||
[
|
||
'https://pics.r1kka.one/file/1738764637932_-305500c1acccdf39.jpg',
|
||
'https://r1kka.one/',
|
||
"Rikka's Blog",
|
||
],
|
||
[
|
||
'https://shimizukaede.top/vite.svg',
|
||
'https://shimizukaede.top',
|
||
'Kaede 的博客',
|
||
],
|
||
[
|
||
'https://nonerd.tech/assets/apple-touch-icon.png',
|
||
'https://nonerd.tech/',
|
||
'废柴铁克诺',
|
||
],
|
||
[
|
||
'https://legacy.passthem.top/assets/ydt-DIeb2Djx.png',
|
||
'https://qm.qq.com/q/nDnHUy9KQo',
|
||
'有顶天变电站 (QQ)',
|
||
],
|
||
[
|
||
'https://legacy.passthem.top/assets/lfxdxy-BogfTZvz.png',
|
||
'https://qm.qq.com/q/QOpCVZcvyS',
|
||
'六方相的新月 (QQ)',
|
||
],
|
||
].map((b) => (
|
||
<a href={b[1]} class="friend">
|
||
<div class="avatar">
|
||
<Image
|
||
src={b[0]}
|
||
width={60}
|
||
height={60}
|
||
alt={`网站「${b[2]}」的图标`}
|
||
/>
|
||
</div>
|
||
<div class="description">{b[2]}</div>
|
||
</a>
|
||
))
|
||
}
|
||
</div>
|
||
</section>
|
||
</FullLayoutV1>
|
||
|
||
<script>
|
||
const setupObserver = () => {
|
||
const observer = new IntersectionObserver(
|
||
(entries) => {
|
||
entries.forEach((entry) => {
|
||
if (entry.intersectionRatio > 0.5) {
|
||
entry.target.classList.add('slide-visible')
|
||
} else {
|
||
entry.target.classList.remove('slide-visible')
|
||
}
|
||
})
|
||
},
|
||
{ threshold: 0.5 },
|
||
)
|
||
|
||
document.querySelectorAll('section.slide').forEach((ele) => {
|
||
observer.observe(ele)
|
||
;(ele as HTMLElement).addEventListener('focusin', () => {
|
||
ele.scrollIntoView({
|
||
block: 'start',
|
||
})
|
||
})
|
||
})
|
||
}
|
||
|
||
document.addEventListener('astro:page-load', setupObserver)
|
||
</script>
|
||
|
||
<style>
|
||
:global(html) {
|
||
scroll-snap-type: y proximity;
|
||
scroll-behavior: smooth;
|
||
}
|
||
|
||
.slide {
|
||
scroll-snap-align: start;
|
||
scroll-snap-stop: always;
|
||
height: 100lvh;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
overflow: hidden;
|
||
isolation: isolate;
|
||
|
||
&:nth-child(2n) {
|
||
background-color: var(--color-bg-1);
|
||
}
|
||
|
||
& > .notation {
|
||
position: absolute;
|
||
width: 100dvw;
|
||
padding-inline-start: 2rem;
|
||
padding-block-end: 2rem;
|
||
inset-inline-start: 0;
|
||
inset-block-end: calc(100lvh - 100dvh);
|
||
font-size: smaller;
|
||
color: var(--color-fg-0);
|
||
opacity: 0.3;
|
||
|
||
& a {
|
||
text-decoration: underline;
|
||
|
||
&:hover {
|
||
background-color: var(--color-fg-0);
|
||
color: var(--color-bg-0);
|
||
}
|
||
}
|
||
}
|
||
|
||
& h1 {
|
||
font-size: clamp(2.5rem, 6vw, 3rem);
|
||
font-weight: 800;
|
||
}
|
||
}
|
||
|
||
.animation-error-warning {
|
||
display: none;
|
||
}
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
@-moz-document url-prefix() {
|
||
.animation-error-warning {
|
||
display: block;
|
||
}
|
||
|
||
:global(html) {
|
||
scroll-snap-type: none;
|
||
scroll-behavior: auto;
|
||
}
|
||
}
|
||
}
|
||
|
||
@property --avatar-scalar {
|
||
syntax: '<number>';
|
||
inherits: true;
|
||
initial-value: 0;
|
||
}
|
||
|
||
@property --avatar-hover-scalar {
|
||
syntax: '<number>';
|
||
inherits: true;
|
||
initial-value: 0;
|
||
}
|
||
|
||
@property --avatar-rotation {
|
||
syntax: '<angle>';
|
||
inherits: true;
|
||
initial-value: 0deg;
|
||
}
|
||
|
||
/* 自我介绍部分 */
|
||
.self-introduction {
|
||
display: flex;
|
||
flex-direction: column;
|
||
text-align: center;
|
||
align-items: center;
|
||
gap: 2rem;
|
||
|
||
@media (min-width: 768px) {
|
||
flex-direction: row-reverse;
|
||
text-align: left;
|
||
}
|
||
|
||
& > .avatar {
|
||
margin: 0;
|
||
border-radius: 50%;
|
||
|
||
--final-width: clamp(160px, 30vw, 240px);
|
||
--avatar-scalar: 0;
|
||
--avatar-hover-scalar: 1;
|
||
--avatar-rotation: 20deg;
|
||
transition:
|
||
--avatar-rotation cubic-bezier(0.2, 1, 0.4, 1) 1.8s,
|
||
--avatar-scalar cubic-bezier(0.2, 2, 0.3, 0.8) 1.2s,
|
||
--avatar-hover-scalar cubic-bezier(0.2, 3, 0.4, 0.6) 0.6s,
|
||
width cubic-bezier(0.4, 1, 0.4, 1) 0.9s;
|
||
|
||
transform: rotate(var(--avatar-rotation)) scale(var(--avatar-scalar))
|
||
scale(var(--avatar-hover-scalar));
|
||
aspect-ratio: 1 / 1;
|
||
overflow: hidden;
|
||
width: 0;
|
||
|
||
section.slide.slide-visible & {
|
||
--avatar-scalar: 1;
|
||
--avatar-rotation: 0deg;
|
||
width: var(--final-width);
|
||
}
|
||
|
||
&:hover,
|
||
&:focus {
|
||
--avatar-hover-scalar: 1.05;
|
||
}
|
||
}
|
||
|
||
& > .descriptions {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 3rem;
|
||
|
||
& > .motto {
|
||
font-size: clamp(2rem, 4vw, 4rem);
|
||
font-weight: 800;
|
||
|
||
display: grid;
|
||
grid-template-rows: repeat(3, 1fr);
|
||
align-items: center;
|
||
width: 11em;
|
||
|
||
& > p {
|
||
width: max-content;
|
||
margin-inline: auto;
|
||
|
||
@media (min-width: 768px) {
|
||
margin-inline: 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
& > .buttons {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
|
||
@media (min-width: 768px) {
|
||
flex-direction: row;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 涂黑书信的特殊处理 */
|
||
.thsx {
|
||
cursor: pointer;
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.motto > p {
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
&::before {
|
||
content: '';
|
||
display: block;
|
||
background-color: var(--color-fg-0);
|
||
width: 100%;
|
||
height: 100%;
|
||
position: absolute;
|
||
z-index: 2;
|
||
inset-inline-start: -100%;
|
||
}
|
||
}
|
||
|
||
section:has(.thsx:hover) .motto > p,
|
||
section:has(.thsx:focus) .motto > p {
|
||
&:nth-child(1)::before {
|
||
transition-delay: 0;
|
||
}
|
||
&:nth-child(2)::before {
|
||
transition-delay: 0.1s;
|
||
}
|
||
&:nth-child(3)::before {
|
||
transition-delay: 0.2s;
|
||
}
|
||
|
||
&::before {
|
||
transition: inset-inline-start cubic-bezier(0.2, 1, 0.17, 1) 1s;
|
||
inset-inline-start: 0%;
|
||
}
|
||
}
|
||
|
||
section:has(.thsx:hover) .buttons {
|
||
transition: filter cubic-bezier(0.2, 1, 0.17, 1) 1s;
|
||
filter: grayscale(100%);
|
||
}
|
||
|
||
/* 一个特殊设计的标题元素,呼呼 */
|
||
.slide-title-design1 {
|
||
position: absolute;
|
||
inset-inline-start: -3rem;
|
||
inset-block-end: -2rem;
|
||
opacity: 0;
|
||
user-select: none;
|
||
z-index: -1;
|
||
transition: all ease 1.5s;
|
||
|
||
section.slide.slide-visible & {
|
||
opacity: 0.2;
|
||
inset-inline-start: -1rem;
|
||
}
|
||
|
||
& > svg {
|
||
font-weight: 900;
|
||
font-size: 10rem;
|
||
|
||
& > .stroke-layer {
|
||
fill: none;
|
||
stroke: var(--color-fg-0);
|
||
stroke-width: 1px;
|
||
stroke-linejoin: round;
|
||
}
|
||
& > .main-layer {
|
||
fill: var(--color-fg-0);
|
||
}
|
||
}
|
||
}
|
||
.slide-title-design2 {
|
||
position: absolute;
|
||
inset-inline-end: -5rem;
|
||
inset-block-start: -2rem;
|
||
opacity: 0;
|
||
user-select: none;
|
||
z-index: -1;
|
||
transition: all ease 1.5s;
|
||
|
||
section.slide.slide-visible & {
|
||
opacity: 0.2;
|
||
inset-inline-end: -3rem;
|
||
}
|
||
|
||
& > svg {
|
||
font-size: 288px;
|
||
transform: rotate(-12deg);
|
||
}
|
||
}
|
||
|
||
/* 评论页 */
|
||
.comment-page-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
& > .comment-container {
|
||
height: 0;
|
||
padding: 0;
|
||
margin: 0;
|
||
transition: all cubic-bezier(0.4, 1, 0.4, 1) 1.2s;
|
||
border-radius: 1rem;
|
||
background-color: var(--color-bg-n);
|
||
width: calc(min(100dvw - 2rem, 40rem));
|
||
position: relative;
|
||
|
||
&::before {
|
||
content: '';
|
||
display: block;
|
||
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 1rem;
|
||
transition: all cubic-bezier(0.4, 1, 0.4, 1) 1.2s;
|
||
position: absolute;
|
||
transform: rotate(0deg);
|
||
z-index: -1;
|
||
background-color: rgb(from var(--color-fg-0) r g b / 0.05);
|
||
}
|
||
|
||
section.slide.slide-visible & {
|
||
margin-block-start: 2rem;
|
||
height: 60dvh;
|
||
|
||
&::before {
|
||
transform: rotate(-6deg);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 联络页 */
|
||
@keyframes bg-contact-roll {
|
||
0% {
|
||
background-position: 0 0;
|
||
}
|
||
100% {
|
||
background-position: var(--bg-width) 0;
|
||
}
|
||
}
|
||
|
||
.contact-container {
|
||
& > h1 {
|
||
--height: 1.5em;
|
||
--skew-angle: 15deg;
|
||
--col1: var(--color-fg-0);
|
||
--bg-width: 2rem;
|
||
--unit: calc(tan(var(--skew-angle)) * var(--height) * 0.5);
|
||
|
||
height: var(--height);
|
||
line-height: var(--height);
|
||
display: grid;
|
||
grid-template-columns: auto 1fr;
|
||
color: var(--color-bg-0);
|
||
margin-block-end: 0.5em;
|
||
position: relative;
|
||
|
||
& > .text {
|
||
background-color: var(--color-fg-0);
|
||
position: relative;
|
||
}
|
||
|
||
& .animation-before {
|
||
width: calc(var(--unit) * 2);
|
||
position: absolute;
|
||
overflow: hidden;
|
||
height: 100%;
|
||
inset-inline-end: calc(var(--unit) * -2);
|
||
inset-block-start: 0;
|
||
|
||
&::after {
|
||
content: '';
|
||
display: block;
|
||
background-color: var(--col1);
|
||
width: 100%;
|
||
height: 100%;
|
||
transform: skewX(var(--skew-angle)) translateX(calc(-1 * var(--unit)));
|
||
}
|
||
}
|
||
|
||
& > .animation {
|
||
content: '';
|
||
display: block;
|
||
background-image: linear-gradient(
|
||
90deg,
|
||
transparent 0,
|
||
transparent 25%,
|
||
var(--col1) 25%,
|
||
var(--col1) 75%,
|
||
transparent 75%,
|
||
transparent 100%
|
||
);
|
||
background-repeat: repeat;
|
||
background-size: var(--bg-width) 100%;
|
||
animation: bg-contact-roll infinite linear 2s;
|
||
transform: skewX(var(--skew-angle)) translateX(calc(var(--unit) - 1px));
|
||
}
|
||
}
|
||
|
||
& > table {
|
||
font-family: var(--font-mono);
|
||
|
||
& caption {
|
||
text-align: center;
|
||
}
|
||
|
||
& tr {
|
||
text-align: left;
|
||
display: grid;
|
||
grid-template-columns: 6em 16em;
|
||
gap: 1em;
|
||
line-height: 2em;
|
||
|
||
@media (max-width: 767px) {
|
||
grid-template-columns: 18em;
|
||
gap: 0;
|
||
line-height: 1.8em;
|
||
margin-block: 1em;
|
||
}
|
||
|
||
& th:nth-child(1) {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
|
||
@media (max-width: 767px) {
|
||
justify-content: left;
|
||
}
|
||
|
||
&::after {
|
||
content: ':';
|
||
}
|
||
}
|
||
|
||
& th:nth-child(2) {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
|
||
@media (max-width: 767px) {
|
||
justify-content: end;
|
||
}
|
||
|
||
&::before {
|
||
content: '[';
|
||
}
|
||
|
||
&::after {
|
||
content: ']';
|
||
}
|
||
|
||
&:hover,
|
||
&:has(a:focus) {
|
||
background-color: var(--color-fg-0);
|
||
color: var(--color-bg-0);
|
||
}
|
||
|
||
& > a {
|
||
text-align: center;
|
||
margin-inline: 1em;
|
||
|
||
&:focus {
|
||
outline: none;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 友链页 */
|
||
.slide:has(> .friends) {
|
||
flex-direction: column;
|
||
gap: 1rem;
|
||
}
|
||
|
||
.friends {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
max-width: 50rem;
|
||
max-height: 30rem;
|
||
padding-block: 3rem;
|
||
overflow-y: auto;
|
||
margin-inline: 1rem;
|
||
/* background-color: rgb(from var(--color-bg-0) r g b / .3); */
|
||
background-color: rgb(from var(--color-bg-2) r g b / 0.5);
|
||
border-radius: 2rem;
|
||
backdrop-filter: blur(5px);
|
||
|
||
& > .friend {
|
||
background-color: var(--color-bg-0);
|
||
display: grid;
|
||
align-items: center;
|
||
border-radius: 30px;
|
||
overflow: hidden;
|
||
width: 14rem;
|
||
height: 60px;
|
||
grid-template-columns: 60px 1fr;
|
||
position: relative;
|
||
isolation: isolate;
|
||
|
||
& > .avatar {
|
||
border-radius: 30px;
|
||
height: 60px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
overflow: hidden;
|
||
background-color: var(--color-bg-n);
|
||
/* box-shadow: 0 0 0 10px var(--color-bg-2); */
|
||
transition: all cubic-bezier(0.2, 1, 0.4, 1) 0.5s;
|
||
}
|
||
|
||
& > .description {
|
||
text-align: center;
|
||
}
|
||
|
||
&::before {
|
||
content: '';
|
||
display: block;
|
||
border-radius: 30px;
|
||
background-color: var(--color-bg-n);
|
||
position: absolute;
|
||
z-index: -1;
|
||
width: 100%;
|
||
height: 100%;
|
||
|
||
inset-inline-start: calc(-100% + 30px);
|
||
box-shadow: 0 0 0 10px var(--color-blue);
|
||
transition: inset-inline-start cubic-bezier(0.2, 1, 0.4, 1) 0.5s;
|
||
}
|
||
|
||
outline: solid 0px transparent;
|
||
outline-offset: 0px;
|
||
transition: all cubic-bezier(0.2, 1, 0.4, 1) 0.5s;
|
||
|
||
&:focus {
|
||
outline: solid 3px var(--color-blue);
|
||
outline-offset: 3px;
|
||
}
|
||
|
||
&:hover,
|
||
&:focus {
|
||
transform: scale(1.1);
|
||
}
|
||
|
||
&:hover::before,
|
||
&:focus::before {
|
||
inset-inline-start: 0;
|
||
}
|
||
|
||
&:hover .avatar,
|
||
&:focus .avatar {
|
||
/* transform: rotate(360deg); */
|
||
}
|
||
}
|
||
}
|
||
</style>
|