Commit a28e035e authored by timel's avatar timel

Merge branch 'feat/start' into 'main'

重构起始页(landing page)

See merge request mycard/Neos!281
parents 210aa003 01b0ade5
Pipeline #23239 passed with stages
in 36 minutes and 7 seconds
.wrap { .wrap {
position: relative; position: relative;
text-align: center;
height: calc(100% - var(--header-height)); height: calc(100% - var(--header-height));
display: flex; display: flex;
flex-direction: column; flex-direction: column;
...@@ -10,124 +9,65 @@ ...@@ -10,124 +9,65 @@
} }
.main { .main {
height: 650px; height: 453px;
width: 650px; width: 1000px;
max-height: 100%;
position: relative; position: relative;
display: flex; display: flex;
justify-content: center; justify-content: space-between;
.neos-pic { .left {
max-width: 100%; height: 100%;
max-height: 100%; display: flex;
filter: drop-shadow(0 0 50px #ffffff7d) drop-shadow(0 10px 0.5rem #0a3c71ce); flex-direction: column;
z-index: -1; gap: 6px;
}
.neos-logo { .neos-logo {
filter: drop-shadow(0 0 2rem #ffffffbc); width: 143px;
position: absolute; height: 34px;
top: 50%; }
width: 90%; .title {
height: fit-content; font-size: 36px;
left: 52%; font-weight: 500;
transform: translateX(-50%); color: rgba(255, 255, 255, 0.86);
} }
} .keywords {
font-size: 24px;
// 以下是粒子动画的样式 font-weight: 500;
color: rgba(235, 245, 235, 0.8);
.particles-container { }
width: 100%; .details {
margin-top: 31px;
width: 450px;
font-size: 14px;
font-weight: 500;
line-height: 24px;
color: rgba(235, 245, 235, 0.5);
}
}
.right {
width: 360px;
height: 100%; height: 100%;
position: relative; position: relative;
} overflow: hidden;
border-bottom-right-radius: 180px;
.particle-container { border-bottom-left-radius: 180px;
$particleNum: 200; .neos-main-bg {
$particleColor: hsl(180, 100%, 80%);
position: absolute; position: absolute;
transform: translateY(-10vh); bottom: 0;
animation-iteration-count: infinite; width: fit-content;
animation-timing-function: linear; height: 360px;
.particle {
width: 100%;
height: 100%;
border-radius: 50%; border-radius: 50%;
mix-blend-mode: screen; filter: brightness(0.7);
background-image: radial-gradient(
hsl(180, 100%, 80%),
hsl(180, 100%, 80%) 10%,
hsla(180, 100%, 80%, 0) 56%
);
animation: fadein-frames 200ms infinite, scale-frames 2s infinite;
}
@keyframes fadein-frames {
0% {
opacity: 1;
}
50% {
opacity: 0.7;
}
100% {
opacity: 1;
}
}
@keyframes scale-frames {
0% {
transform: scale3d(0.4, 0.4, 1);
}
50% {
transform: scale3d(2.2, 2.2, 1);
}
100% {
transform: scale3d(0.4, 0.4, 1);
}
}
$particleBaseSize: 10;
@for $i from 1 to $particleNum {
&:nth-child(#{$i}) {
$particleSize: random($particleBaseSize);
width: $particleSize + px;
height: $particleSize + px;
$startPositionY: random(10) + 80;
$framesName: "move-frames" + $i;
$moveDuration: 28000 + random(9000) + ms;
animation-name: #{$framesName};
animation-duration: $moveDuration;
animation-delay: random(37000) + ms;
@keyframes #{$framesName} {
from {
transform: translate3d(
#{random(90) + vw},
#{$startPositionY + vh},
0
);
}
to {
transform: translate3d(
#{random(90) + vw},
#{- $startPositionY - random(30) + vh},
0
);
}
}
.particle {
animation-delay: random(4000) + ms;
} }
.neos-main {
position: absolute;
bottom: 0;
border-bottom-right-radius: 50%;
transform: scale(1.25);
transform-origin: 50% 100%;
width: max-content;
filter: drop-shadow(0px 8px 8px rgba(255, 255, 255, 0.3))
drop-shadow(0px 0px 4px rgba(255, 255, 255, 0.8));
transition: 0.2s;
} }
} }
} }
...@@ -17,28 +17,31 @@ export const Component: React.FC = () => { ...@@ -17,28 +17,31 @@ export const Component: React.FC = () => {
<> <>
<Background /> <Background />
<div className={styles.wrap}> <div className={styles.wrap}>
<div className={styles["particles-container"]}> <main className={styles.main}>
{Array.from({ length: 100 }).map((_, key) => ( <div className={styles.left}>
<div key={key} className={styles["particle-container"]}>
<div className={styles["particle"]} />
</div>
))}
</div>
<main className={styles["main"]}>
<img <img
className={styles["neos-logo"]} className={styles["neos-logo"]}
src={`${NeosConfig.assetsPath}/neos-logo.svg`} src={`${NeosConfig.assetsPath}/neos-logo.svg`}
alt="YGO NEOS" alt="YGO NEOS"
/> />
<div className={styles.title}>游戏王网页对战模拟器</div>
<div className={styles.keywords}>开源、免费、轻量级</div>
<div className={styles.details}>
这是有关Neos的详细介绍。观夫明堂之宏壮也,则突兀瞳曨,乍明乍蒙,若大古元气之结空。巃嵸颓沓,若嵬若嶪,似天阃地门之开阖。尔乃划岝峉以岳立,郁穹崇而鸿纷。冠百王而垂勋,烛万象而腾文。
</div>
<LoginBtn logined={Boolean(user)} />
</div>
<div className={styles.right}>
<img
className={styles["neos-main-bg"]}
src={`${NeosConfig.assetsPath}/neos-main-bg.webp`}
/>
<img <img
className={styles["neos-pic"]} className={styles["neos-main"]}
src={`${NeosConfig.assetsPath}/neos.png`} src={`${NeosConfig.assetsPath}/neos-main.webp`}
alt="neos"
/> />
</main>
<div style={{ display: "flex", justifyContent: "center" }}>
<LoginBtn logined={Boolean(user)} />
</div> </div>
</main>
</div> </div>
</> </>
); );
...@@ -55,7 +58,10 @@ const LoginBtn: React.FC<{ logined: boolean }> = ({ logined }) => { ...@@ -55,7 +58,10 @@ const LoginBtn: React.FC<{ logined: boolean }> = ({ logined }) => {
const goToMatch = () => navigate("/match"); const goToMatch = () => navigate("/match");
return ( return (
<SpecialButton onClick={logined ? goToMatch : loginViaSSO}> <SpecialButton
style={{ marginTop: "auto" }}
onClick={logined ? goToMatch : loginViaSSO}
>
<span>{logined ? "开始游戏" : "登录游戏"}</span> <span>{logined ? "开始游戏" : "登录游戏"}</span>
<RightOutlined /> <RightOutlined />
</SpecialButton> </SpecialButton>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment