feat: 优化 landing page 字体样式和功能介绍
- 主标题使用更优雅的字体样式和柔和阴影 - 副标题添加半透明背景提升可读性 - 新增四个功能模块的详细介绍卡片(纪念日/提醒/AI/便签) - 使用毛玻璃效果增强视觉层次 - 响应式布局适配不同屏幕 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
6fd1acc999
commit
25f999cb1f
@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Button, Container, Title, Text, Group, Stack } from '@mantine/core';
|
||||
import { Button, Container, Title, Text, Group, Stack, Paper, ThemeIcon, SimpleGrid, Box } from '@mantine/core';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import iconUrl from '../assets/icon.png';
|
||||
|
||||
@ -48,7 +48,7 @@ function ZenBackground() {
|
||||
let strokes: InkStroke[] = [];
|
||||
let time = 0;
|
||||
let lastStrokeTime = 0;
|
||||
const strokeInterval = 30; // 每隔一段时间生成新笔触
|
||||
const strokeInterval = 30;
|
||||
|
||||
// 生成随机笔触
|
||||
const createStroke = (): InkStroke | null => {
|
||||
@ -65,7 +65,7 @@ function ZenBackground() {
|
||||
speed: random(0.4, 1.0),
|
||||
inkAlpha: random(10, 30),
|
||||
baseWeight: random(0.3, 1.5),
|
||||
maxLength: random(30, 90), // 缩短笔触长度,加快消失
|
||||
maxLength: random(30, 90),
|
||||
currentLength: 0,
|
||||
complete: false,
|
||||
};
|
||||
@ -77,7 +77,6 @@ function ZenBackground() {
|
||||
for (let i = 0; i < 8; i++) {
|
||||
const stroke = createStroke();
|
||||
if (stroke) {
|
||||
// 随机偏移起始位置
|
||||
stroke.currentLength = random(0, stroke.maxLength * 0.5);
|
||||
strokes.push(stroke);
|
||||
}
|
||||
@ -93,7 +92,7 @@ function ZenBackground() {
|
||||
const animate = () => {
|
||||
time += 0.008;
|
||||
|
||||
// 快速淡出背景 - 让水墨痕迹更快消失
|
||||
// 快速淡出背景
|
||||
if (Math.floor(time * 125) % 3 === 0) {
|
||||
ctx.fillStyle = 'rgba(250, 249, 247, 0.12)';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
@ -102,9 +101,7 @@ function ZenBackground() {
|
||||
// 定期生成新笔触
|
||||
if (time - lastStrokeTime > strokeInterval * 0.01) {
|
||||
lastStrokeTime = time;
|
||||
// 移除已完成太久的笔触
|
||||
strokes = strokes.filter(s => !s.complete || s.currentLength < s.maxLength);
|
||||
// 添加新笔触(随机数量)
|
||||
const newCount = Math.floor(random(0, 2));
|
||||
for (let i = 0; i < newCount; i++) {
|
||||
const stroke = createStroke();
|
||||
@ -116,18 +113,15 @@ function ZenBackground() {
|
||||
for (const stroke of strokes) {
|
||||
if (stroke.complete) continue;
|
||||
|
||||
// 噪声驱动
|
||||
const n = noise(stroke.x, stroke.y, time);
|
||||
stroke.angle += (n - 0.5) * 0.12;
|
||||
|
||||
// 呼吸感 - 更柔和
|
||||
const breath = Math.sin(time * 1.5 + stroke.x * 0.01) * 0.25;
|
||||
const currentSpeed = stroke.speed * (1 + breath * 0.2);
|
||||
|
||||
stroke.x += Math.cos(stroke.angle) * currentSpeed;
|
||||
stroke.y += Math.sin(stroke.angle) * currentSpeed;
|
||||
|
||||
// 笔触粗细 - 模拟提按
|
||||
const progress = stroke.currentLength / stroke.maxLength;
|
||||
const weightVar = Math.sin(progress * Math.PI) * 1.0;
|
||||
const weight = Math.max(0.2, stroke.baseWeight + weightVar);
|
||||
@ -143,16 +137,13 @@ function ZenBackground() {
|
||||
stroke.complete = true;
|
||||
}
|
||||
|
||||
// 绘制 - 水墨晕染效果
|
||||
if (stroke.points.length > 1) {
|
||||
for (let i = 1; i < stroke.points.length; i++) {
|
||||
const p1 = stroke.points[i - 1];
|
||||
const p2 = stroke.points[i];
|
||||
// 渐变透明度
|
||||
const alpha = stroke.inkAlpha * (1 - i / stroke.points.length * 0.4) / 100;
|
||||
const size = p2.weight * random(0.8, 1.2);
|
||||
|
||||
// 绘制柔和的笔触
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(p1.x, p1.y);
|
||||
ctx.lineTo(p2.x, p2.y);
|
||||
@ -161,7 +152,6 @@ function ZenBackground() {
|
||||
ctx.lineCap = 'round';
|
||||
ctx.stroke();
|
||||
|
||||
// 添加淡淡的墨点晕染
|
||||
if (random(0, 1) < 0.3) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(p2.x, p2.y, size * random(0.5, 1.5), 0, Math.PI * 2);
|
||||
@ -172,12 +162,12 @@ function ZenBackground() {
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制圆相(Ensō)- 缓慢呼吸
|
||||
// 绘制圆相(Ensō)
|
||||
const centerX = canvas.width / 2;
|
||||
const centerY = canvas.height / 2;
|
||||
const breathScale = 1 + Math.sin(time * 0.3) * 0.015;
|
||||
const radius = Math.min(canvas.width, canvas.height) * 0.18 * breathScale;
|
||||
const gap = Math.PI * 0.18; // 开口
|
||||
const gap = Math.PI * 0.18;
|
||||
const startAngle = -Math.PI / 2 + time * 0.05;
|
||||
|
||||
ctx.beginPath();
|
||||
@ -224,6 +214,40 @@ function ZenBackground() {
|
||||
);
|
||||
}
|
||||
|
||||
// 功能特性卡片
|
||||
function FeatureCard({
|
||||
icon,
|
||||
title,
|
||||
description,
|
||||
}: {
|
||||
icon: string;
|
||||
title: string;
|
||||
description: string;
|
||||
}) {
|
||||
return (
|
||||
<Paper
|
||||
p="lg"
|
||||
radius="sm"
|
||||
style={{
|
||||
background: 'rgba(255, 255, 255, 0.6)',
|
||||
backdropFilter: 'blur(10px)',
|
||||
border: '1px solid rgba(0, 0, 0, 0.05)',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<Stack gap="sm">
|
||||
<Text size="xl" fw={300} style={{ letterSpacing: '0.1em' }}>{icon}</Text>
|
||||
<Text size="md" fw={500} style={{ letterSpacing: '0.08em', color: '#1a1a1a' }}>
|
||||
{title}
|
||||
</Text>
|
||||
<Text size="sm" c="#666" style={{ lineHeight: 1.8, fontWeight: 300 }}>
|
||||
{description}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
export function LandingPage() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
@ -285,75 +309,95 @@ export function LandingPage() {
|
||||
</svg>
|
||||
|
||||
<Container
|
||||
size="sm"
|
||||
size="lg"
|
||||
style={{
|
||||
position: 'relative',
|
||||
zIndex: 1,
|
||||
minHeight: '100vh',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
padding: '2rem',
|
||||
padding: '3rem 1rem',
|
||||
}}
|
||||
>
|
||||
{/* Hero 区域 */}
|
||||
<Box
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
paddingTop: 'min(15vh, 120px)',
|
||||
paddingBottom: 'min(10vh, 80px)',
|
||||
}}
|
||||
>
|
||||
<Stack align="center" gap="lg">
|
||||
{/* 产品图标 */}
|
||||
<div
|
||||
style={{
|
||||
width: 90,
|
||||
height: 90,
|
||||
width: 100,
|
||||
height: 100,
|
||||
borderRadius: '50%',
|
||||
background: 'rgba(26, 26, 26, 0.03)',
|
||||
background: 'rgba(26, 26, 26, 0.04)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: '0.5rem',
|
||||
marginBottom: '2rem',
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={iconUrl}
|
||||
alt="掐日子"
|
||||
style={{
|
||||
width: 60,
|
||||
height: 60,
|
||||
width: 65,
|
||||
height: 65,
|
||||
borderRadius: '50%',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 主标题 */}
|
||||
<Title
|
||||
order={1}
|
||||
style={{
|
||||
fontWeight: 300,
|
||||
fontSize: 'clamp(2.2rem, 7vw, 3.2rem)',
|
||||
letterSpacing: '0.25em',
|
||||
fontWeight: 200,
|
||||
fontSize: 'clamp(2.5rem, 8vw, 4rem)',
|
||||
letterSpacing: '0.2em',
|
||||
color: '#1a1a1a',
|
||||
fontFamily: 'Noto Serif SC, serif',
|
||||
fontFamily: 'Noto Serif SC, Georgia, serif',
|
||||
marginBottom: '0.5rem',
|
||||
textShadow: '0 2px 10px rgba(0,0,0,0.03)',
|
||||
}}
|
||||
>
|
||||
掐日子
|
||||
</Title>
|
||||
|
||||
{/* 副标题 - 增强可读性 */}
|
||||
<Text
|
||||
size="sm"
|
||||
size="lg"
|
||||
style={{
|
||||
letterSpacing: '0.35em',
|
||||
color: '#888',
|
||||
fontWeight: 300,
|
||||
fontWeight: 400,
|
||||
fontSize: 'clamp(1rem, 2.5vw, 1.25rem)',
|
||||
letterSpacing: '0.3em',
|
||||
color: '#333',
|
||||
fontFamily: 'Noto Serif SC, serif',
|
||||
marginBottom: '1rem',
|
||||
padding: '0.5rem 1.5rem',
|
||||
background: 'rgba(255, 255, 255, 0.7)',
|
||||
backdropFilter: 'blur(4px)',
|
||||
borderRadius: '2px',
|
||||
}}
|
||||
>
|
||||
AI 纪念日 · 提醒
|
||||
</Text>
|
||||
|
||||
{/* 描述文案 */}
|
||||
<Text
|
||||
size="xs"
|
||||
size="sm"
|
||||
style={{
|
||||
color: '#999',
|
||||
maxWidth: 300,
|
||||
lineHeight: 1.9,
|
||||
color: '#666',
|
||||
maxWidth: 360,
|
||||
lineHeight: 2,
|
||||
fontWeight: 300,
|
||||
fontSize: '0.9rem',
|
||||
}}
|
||||
>
|
||||
轻便、灵活的倒数日和提醒应用
|
||||
@ -361,57 +405,70 @@ export function LandingPage() {
|
||||
让每一个重要的日子都被铭记
|
||||
</Text>
|
||||
|
||||
<Group gap="md" mt="lg">
|
||||
<Group gap="md" mt="xl">
|
||||
<Button
|
||||
size="sm"
|
||||
size="md"
|
||||
onClick={() => navigate('/login')}
|
||||
style={{
|
||||
background: '#1a1a1a',
|
||||
border: '1px solid #1a1a1a',
|
||||
padding: '0 2rem',
|
||||
padding: '0.75rem 2.5rem',
|
||||
fontWeight: 400,
|
||||
letterSpacing: '0.15em',
|
||||
letterSpacing: '0.2em',
|
||||
borderRadius: 2,
|
||||
fontSize: '0.85rem',
|
||||
}}
|
||||
>
|
||||
登录
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
size="md"
|
||||
variant="outline"
|
||||
onClick={() => navigate('/register')}
|
||||
style={{
|
||||
borderColor: '#ccc',
|
||||
borderColor: '#999',
|
||||
color: '#1a1a1a',
|
||||
padding: '0 2rem',
|
||||
padding: '0.75rem 2.5rem',
|
||||
fontWeight: 400,
|
||||
letterSpacing: '0.15em',
|
||||
letterSpacing: '0.2em',
|
||||
borderRadius: 2,
|
||||
fontSize: '0.85rem',
|
||||
}}
|
||||
>
|
||||
注册
|
||||
</Button>
|
||||
</Group>
|
||||
</Box>
|
||||
|
||||
<Group gap={40} mt={50} style={{ opacity: 0.7 }}>
|
||||
<Stack gap={3} align="center">
|
||||
<Text size="xs" fw={300} c="#444">◯</Text>
|
||||
<Text size="xs" c="#666" style={{ letterSpacing: '0.1em' }}>纪念日</Text>
|
||||
</Stack>
|
||||
<Stack gap={3} align="center">
|
||||
<Text size="xs" fw={300} c="#444">◎</Text>
|
||||
<Text size="xs" c="#666" style={{ letterSpacing: '0.1em' }}>提醒</Text>
|
||||
</Stack>
|
||||
<Stack gap={3} align="center">
|
||||
<Text size="xs" fw={300} c="#444">◇</Text>
|
||||
<Text size="xs" c="#666" style={{ letterSpacing: '0.1em' }}>AI</Text>
|
||||
</Stack>
|
||||
<Stack gap={3} align="center">
|
||||
<Text size="xs" fw={300} c="#444">▫</Text>
|
||||
<Text size="xs" c="#666" style={{ letterSpacing: '0.1em' }}>便签</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Stack>
|
||||
{/* 功能介绍区域 */}
|
||||
<Box
|
||||
style={{
|
||||
paddingBottom: 'min(15vh, 120px)',
|
||||
}}
|
||||
>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 4 }} spacing="lg">
|
||||
<FeatureCard
|
||||
icon="◯"
|
||||
title="纪念日"
|
||||
description="记录生日、结婚纪念日等重要日子。支持农历日期,自动计算倒数日。轻松掌握还有多少天到来,让每个值得纪念的日子都不被遗忘。"
|
||||
/>
|
||||
<FeatureCard
|
||||
icon="◎"
|
||||
title="提醒"
|
||||
description="设置一次性或重复提醒事项。支持多种提前提醒时间:准时、提前5/15分钟、1小时、1天。重要事项准时送达,不错过任何关键节点。"
|
||||
/>
|
||||
<FeatureCard
|
||||
icon="◇"
|
||||
title="AI 智能"
|
||||
description="AI 智能解析自然语言,快速创建事件。只需输入「生日是3月15日」,AI 自动识别日期、类型和重复规则。创建提醒从未如此简单。"
|
||||
/>
|
||||
<FeatureCard
|
||||
icon="▫"
|
||||
title="便签"
|
||||
description="支持 Markdown 的个人笔记空间。随时记录想法、灵感或待办事项。与纪念日和提醒功能无缝配合,打造完整的个人时间管理工具。"
|
||||
/>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user