<?php
$isThreadPage = preg_match('/thread-\d+\.htm/i', $_SERVER['REQUEST_URI']);
$titleKeywords = ['2026', '新年', '春节', '大吉', '恭喜发财', '万事如意', '平安', '大年', '拜年'];
$titleHasKeyword = false;
if (isset($thread['subject'])) {
$title = $thread['subject'];
foreach ($titleKeywords as $kw) {
if (strpos($title, $kw) !== false) {
$titleHasKeyword = true;
break;
}
}
}
if (false && $isThreadPage && $titleHasKeyword) {
?>
<script>
(function() {
const CONFIG = {
particleCount: 30, // 每次点击产生的粒子数量
gravity: 0.15, // 重力
friction: 0.96, // 摩擦力(空气阻力),越小减速越快
textScaleSpeed: 0.05, // 文字变大速度
colors: [
'#FF0000', // 正红
'#FF4500', // 橙红
'#FFD700', // 金色
'#FFA500', // 橙色
'#FFFAF0', // 象牙白(增加闪烁感)
'#DC143C' // 猩红
],
greetings: [
'🧧 2026 新年快乐', '🧨 爆竹声声', '🏮 大吉大利',
'✨ 万事如意', '💰 恭喜发财', '🍎 岁岁平安',
'六六大顺 🥳', 'Happy 2026 😄'
]
};
if (document.getElementById('2026-spring-festival-canvas')) return;
const canvas = document.createElement('canvas');
canvas.id = '2026-spring-festival-canvas';
const ctx = canvas.getContext('2d');
canvas.style.position = 'fixed';
canvas.style.top = '0';
canvas.style.left = '0';
canvas.style.width = '100%';
canvas.style.height = '100%';
canvas.style.pointerEvents = 'none';
canvas.style.zIndex = '999999';
canvas.style.userSelect = 'none';
document.body.appendChild(canvas);
let elements = [];
let width = window.innerWidth;
let height = window.innerHeight;
function resize() {
width = window.innerWidth;
height = window.innerHeight;
const dpr = window.devicePixelRatio || 1;
canvas.width = width * dpr;
canvas.height = height * dpr;
ctx.scale(dpr, dpr);
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
}
window.addEventListener('resize', resize);
resize();
const random = (min, max) => Math.random() * (max - min) + min;
const randomColor = () => CONFIG.colors[Math.floor(Math.random() * CONFIG.colors.length)];
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.angle = random(0, Math.PI * 2);
this.velocity = random(4, 10);
this.vx = Math.cos(this.angle) * this.velocity;
this.vy = Math.sin(this.angle) * this.velocity;
this.color = randomColor();
this.size = random(3, 6);
this.opacity = 1;
this.decay = random(0.015, 0.03);
this.rotation = 0;
this.rotationSpeed = random(-0.2, 0.2);
this.shape = Math.random() > 0.5 ? 'circle' : 'rect';
}
update() {
this.vx *= CONFIG.friction;
this.vy *= CONFIG.friction;
this.vy += CONFIG.gravity;
this.x += this.vx;
this.y += this.vy;
this.rotation += this.rotationSpeed;
this.opacity -= this.decay;
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.rotation);
ctx.globalAlpha = Math.max(0, this.opacity);
ctx.fillStyle = this.color;
if (this.shape === 'circle') {
ctx.beginPath();
ctx.arc(0, 0, this.size / 2, 0, Math.PI * 2);
ctx.fill();
} else {
ctx.fillRect(-this.size / 2, -this.size / 2, this.size, this.size);
}
ctx.restore();
}
}
class PopupText {
constructor(x, y) {
this.x = x;
this.y = y;
this.text = CONFIG.greetings[Math.floor(Math.random() * CONFIG.greetings.length)];
this.scale = 0;
this.opacity = 1;
this.vy = -2;
this.friction = 0.98;
}
update() {
if (this.scale < 1) {
this.scale += (1 - this.scale) * 0.1;
}
this.y += this.vy;
this.vy *= this.friction;
this.opacity -= 0.012;
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.scale(this.scale, this.scale);
ctx.globalAlpha = Math.max(0, this.opacity);
ctx.font = 'bold 28px "Microsoft YaHei", "PingFang SC", sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.shadowColor = '#FFD700';
ctx.shadowBlur = 10;
ctx.strokeStyle = '#FFFFFF';
ctx.lineWidth = 4;
ctx.strokeText(this.text, 0, 0);
ctx.shadowBlur = 0;
ctx.fillStyle = '#FF0000';
ctx.fillText(this.text, 0, 0);
ctx.restore();
}
}
let lastTouchTime = 0;
const triggerEffect = (e) => {
if (e.type === 'touchstart') {
lastTouchTime = Date.now();
} else if (e.type === 'mousedown') {
if (Date.now() - lastTouchTime < 500) return;
if (e.button !== 0) return;
}
if (e.target.closest('a') || e.target.closest('button') || e.target.closest('.btn')) return;
const x = e.clientX || (e.touches && e.touches[0].clientX);
const y = e.clientY || (e.touches && e.touches[0].clientY);
if (!x || !y) return;
elements.push(new PopupText(x, y - 30));
for (let i = 0; i < CONFIG.particleCount; i++) {
elements.push(new Particle(x, y));
}
};
const bindEvents = () => {
window.removeEventListener('mousedown', triggerEffect);
window.removeEventListener('touchstart', triggerEffect);
window.addEventListener('mousedown', triggerEffect);
window.addEventListener('touchstart', triggerEffect, { passive: true });
};
bindEvents();
function animate() {
if (elements.length > 0) {
ctx.clearRect(0, 0, width, height);
elements = elements.filter(el => el.opacity > 0);
elements.forEach(el => {
el.update();
el.draw();
});
}
requestAnimationFrame(animate);
}
animate();
window.addEventListener('beforeunload', () => {
elements = [];
canvas.remove();
});
})();
</script>
开头加了页面检测,只有帖子页面才触发,其它地方用去掉它
论坛已移除,发出来备份。