feat(ui): 实现ACG风格UI改造和动画效果
添加樱花飘落和表情点击特效组件,优化卡片动画和背景模糊效果 更新主题色为粉色并添加动漫风格背景图 引入圆角字体提升可爱风格 新增开发文档记录改造计划
This commit is contained in:
104
src/components/widget/Sakura.astro
Normal file
104
src/components/widget/Sakura.astro
Normal file
@@ -0,0 +1,104 @@
|
||||
<canvas id="sakura-canvas"></canvas>
|
||||
|
||||
<style>
|
||||
#sakura-canvas {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Sakura falling effect
|
||||
const canvas = document.getElementById("sakura-canvas") as HTMLCanvasElement;
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
let width = 0;
|
||||
let height = 0;
|
||||
let petals = [];
|
||||
|
||||
const resize = () => {
|
||||
width = canvas.width = window.innerWidth;
|
||||
height = canvas.height = window.innerHeight;
|
||||
};
|
||||
|
||||
class Petal {
|
||||
x: number;
|
||||
y: number;
|
||||
vx: number;
|
||||
vy: number;
|
||||
opacity: number;
|
||||
size: number;
|
||||
rotation: number;
|
||||
rotationSpeed: number;
|
||||
color: string;
|
||||
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.x = Math.random() * width;
|
||||
this.y = Math.random() * height - height;
|
||||
this.vx = Math.random() * 1 + 0.5;
|
||||
this.vy = Math.random() * 1 + 0.5;
|
||||
this.opacity = Math.random() * 0.5 + 0.3;
|
||||
this.size = Math.random() * 10 + 5;
|
||||
this.rotation = Math.random() * 360;
|
||||
this.rotationSpeed = (Math.random() - 0.5) * 2;
|
||||
this.color = `rgba(255, 183, 197, ${this.opacity})`; // Sakura pink
|
||||
}
|
||||
|
||||
update() {
|
||||
this.x += this.vx;
|
||||
this.y += this.vy;
|
||||
this.rotation += this.rotationSpeed;
|
||||
|
||||
if (this.y > height) {
|
||||
this.reset();
|
||||
this.y = -20;
|
||||
}
|
||||
if (this.x > width) {
|
||||
this.x = -20;
|
||||
}
|
||||
}
|
||||
|
||||
draw() {
|
||||
if (!ctx) return;
|
||||
ctx.save();
|
||||
ctx.translate(this.x, this.y);
|
||||
ctx.rotate((this.rotation * Math.PI) / 180);
|
||||
ctx.fillStyle = this.color;
|
||||
ctx.beginPath();
|
||||
// Draw a simple petal shape
|
||||
ctx.moveTo(0, 0);
|
||||
ctx.bezierCurveTo(this.size / 2, -this.size / 2, this.size, 0, 0, this.size);
|
||||
ctx.bezierCurveTo(-this.size, 0, -this.size / 2, -this.size / 2, 0, 0);
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
const init = () => {
|
||||
resize();
|
||||
petals = Array.from({ length: 50 }, () => new Petal()); // 50 petals
|
||||
animate();
|
||||
};
|
||||
|
||||
const animate = () => {
|
||||
if (!ctx) return;
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
petals.forEach((petal) => {
|
||||
petal.update();
|
||||
petal.draw();
|
||||
});
|
||||
requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
window.addEventListener("resize", resize);
|
||||
init();
|
||||
</script>
|
||||
Reference in New Issue
Block a user