删除无用静态文件✅

This commit is contained in:
Han
2025-04-02 19:04:32 +08:00
parent 18ae1b240b
commit 7dab27d0a3
24 changed files with 289 additions and 50 deletions
+189
View File
@@ -0,0 +1,189 @@
document.addEventListener('DOMContentLoaded', () => {
const confettiEffect = (() => {
// 状态对象
const state = {
canvas: null,
ctx: null,
W: 0,
H: 0,
isStart: false,
mp: 150,
particles: [],
angle: 0,
tiltAngle: 0,
confettiActive: true,
animationComplete: true,
animationHandler: null,
particleColors: {
colorOptions: [
"DodgerBlue", "OliveDrab", "Gold", "pink",
"SlateBlue", "lightblue", "Violet", "PaleGreen",
"SteelBlue", "SandyBrown", "Chocolate", "Crimson"
],
colorIndex: 0,
colorIncrementer: 0,
getColor: function () {
if (++this.colorIncrementer % 10 === 0) {
this.colorIndex = (this.colorIndex + 1) % this.colorOptions.length;
}
return this.colorOptions[this.colorIndex];
}
}
};
// 粒子构造函数
function createParticle(color, W, H, mp) {
return {
x: Math.random() * W,
y: Math.random() * H - H,
r: random(10, 30),
d: Math.random() * mp + 10,
color: color,
tilt: Math.floor(10 * Math.random()) - 10,
tiltAngleIncremental: 0.07 * Math.random() + 0.05,
tiltAngle: 0
};
}
// 工具函数
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
// 核心方法
function setGlobals() {
state.canvas = document.querySelector(".vh-aside-item.user > canvas");
state.ctx = state.canvas.getContext("2d");
}
function handleResize() {
[state.W, state.H] = [state.canvas.width, state.canvas.height];
}
function initializeButton() {
const elements = document.querySelectorAll('.vh-aside-item.user');
elements.forEach(el => {
el.addEventListener('mouseenter', restartConfetti);
el.addEventListener('mouseleave', deactivateConfetti);
});
}
function initializeConfetti() {
state.particles = Array.from({ length: state.mp }, () =>
createParticle(
state.particleColors.getColor(),
state.W,
state.H,
state.mp
)
);
state.animationComplete = false;
startConfetti();
}
// 动画相关方法
function animate() {
if (state.animationComplete) return;
handleResize();
state.ctx.clearRect(0, 0, state.W, state.H);
state.particles.forEach(p => drawParticle(p, state.ctx));
updateParticles();
state.animationHandler = requestAnimationFrame(animate);
}
function drawParticle(p, ctx) {
ctx.beginPath();
ctx.lineWidth = p.r / 2;
ctx.strokeStyle = p.color;
ctx.moveTo(p.x + p.tilt + p.r / 4, p.y);
ctx.lineTo(p.x + p.tilt, p.y + p.tilt + p.r / 4);
ctx.stroke();
}
function updateParticles() {
state.angle += 0.01;
state.tiltAngle += 0.1;
const activeParticles = state.particles.reduce((count, p, i) => {
if (state.animationComplete) return count;
if (!state.confettiActive && p.y < -15) p.y = state.H + 100;
else {
stepParticle(p, i);
if (p.y <= state.H) count++;
checkReposition(p, i);
}
return count;
}, 0);
if (activeParticles === 0) stopConfetti();
}
function stepParticle(p, i) {
p.tiltAngle += p.tiltAngleIncremental;
p.y += (Math.cos(state.angle + p.d) + 3 + p.r / 2) / 2;
p.x += Math.sin(state.angle);
p.tilt = 15 * Math.sin(p.tiltAngle - i / 3);
}
function checkReposition(p, i) {
if (!(p.x > state.W + 20 || p.x < -20 || p.y > state.H)) return;
const shouldReposition = (i % 5 > 0 || i % 2 === 0)
? { x: Math.random() * state.W, y: -10 }
: Math.sin(state.angle) > 0
? { x: -5, y: Math.random() * state.H }
: { x: state.W + 5, y: Math.random() * state.H };
repositionParticle(p, shouldReposition.x, shouldReposition.y);
}
function repositionParticle(p, x, y) {
Object.assign(p, { x, y, tilt: Math.floor(10 * Math.random()) - 10 });
}
// 控制方法
function startConfetti() {
[state.W, state.H] = [window.innerWidth, window.innerHeight];
if (!state.animationComplete) animate();
}
function stopConfetti() {
state.animationComplete = true;
state.ctx?.clearRect(0, 0, state.W, state.H);
}
function clearTimers() {
cancelAnimationFrame(state.animationHandler);
}
function deactivateConfetti() {
state.confettiActive = false;
clearTimers();
stopConfetti();
state.isStart = false;
}
function restartConfetti() {
if (state.isStart) return;
handleResize();
state.isStart = true;
clearTimers();
setTimeout(() => {
state.confettiActive = true;
state.animationComplete = false;
initializeConfetti();
}, 100);
}
// 公共接口
return {
init: () => {
setGlobals();
initializeButton();
window.addEventListener('resize', handleResize);
}
};
})();
confettiEffect.init();
});
+54
View File
@@ -0,0 +1,54 @@
document.addEventListener('DOMContentLoaded', () => {
const vhPaopaoInit = (element, options) => {
const config = Object.assign({ radius: 10, density: 0.3, clearOffset: 0.2 }, options);
let width, height, ctx, active = true;
const canvas = document.createElement('canvas');
const particles = [];
// 初始化画布
const initCanvas = () => {
width = element.offsetWidth;
height = element.offsetHeight;
Object.assign(canvas.style, { top: '0', zIndex: '0', position: 'absolute', 'pointer-events': 'none' });
element.append(canvas);
element.parentElement.style.overflow = 'hidden';
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
};
// 粒子类
class Particle {
constructor() { this.reset() }
reset() {
this.x = Math.random() * width;
this.y = height + 100 * Math.random();
this.alpha = 0.1 + Math.random() * config.clearOffset;
this.scale = 0.1 + 0.3 * Math.random();
this.speed = Math.random();
this.color = config.color === "random" ? `rgba(${Math.random() * 255 | 0},0,0,${Math.random().toFixed(2)})` : config.color;
}
draw() {
if (this.alpha <= 0) this.reset();
this.y -= this.speed;
this.alpha -= 0.0005;
ctx.beginPath();
ctx.arc(this.x, this.y, this.scale * config.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
}
}
// 初始化
initCanvas();
// 动画循环
const animate = () => { active && ctx.clearRect(0, 0, width, height); particles.forEach(p => p.draw()); requestAnimationFrame(animate); };
Array.from({ length: width * config.density | 0 }, () => particles.push(new Particle()));
animate();
// 事件监听
window.addEventListener('scroll', () => active = document.documentElement.scrollTop <= height);
window.addEventListener('resize', () => { width = element.clientWidth; height = element.clientHeight; canvas.width = width; canvas.height = height; });
};
// 调用
const target = document.querySelector('main.main > .header-main');
target && vhPaopaoInit(target, { radius: 10, density: 0.2, color: "rgba(255,255,255,.4)", clearOffset: 0.99 });
});