import {groupChat} from './group-chat/index.js';
export class EasterEgg {
constructor() {
this.clickCount = 0;
this.lastClickTime = 0;
this.versionElement = document.getElementById('app-version');
// 音频上下文(懒加载)
this.audioCtx = null;
if (this.versionElement) {
this.init();
}
}
init() {
this.versionElement.addEventListener('click', (e) => this.handleClick(e));
// Change cursor to indicate interactability (subtle hint)
this.versionElement.style.cursor = 'pointer';
this.versionElement.style.userSelect = 'none';
this.versionElement.title = "版本号";
}
handleClick(e) {
const now = Date.now();
// Reset if more than 2 seconds since last click
if (now - this.lastClickTime > 2000) {
this.clickCount = 0;
}
this.lastClickTime = now;
this.clickCount++;
// Visual feedback for each click
this.animateClick();
if (this.clickCount === 5) {
this.triggerShakeEffect();
} else if (this.clickCount > 5 && this.clickCount < 10) {
// Extend timer if clicking continues while broken
if (document.body.classList.contains('easter-egg--broken')) {
this.resetAutoRestoreTimer();
}
} else if (this.clickCount >= 10) {
this.triggerGroupChat();
}
}
animateClick() {
this.versionElement.style.transition = 'transform 0.1s';
this.versionElement.style.transform = 'scale(0.9)';
setTimeout(() => {
this.versionElement.style.transform = 'scale(1)';
}, 100);
}
triggerShakeEffect() {
// 先重置可能存在的效果
this.resetEffects();
// 创建石头
const stone = document.createElement('div');
stone.classList.add('easter-egg-stone');
stone.innerText = '🪨';
document.body.appendChild(stone);
// 触发重绘以确保过渡动画生效
// 添加飞行状态类
// 动画时间需要与CSS保持一致 (0.6s)
setTimeout(() => {
// 撞击瞬间
stone.remove();
// 播放音效
this.playBreakSound();
document.body.classList.add('easter-egg--shake');
document.body.classList.add('easter-egg--broken');
// 500ms 后停止震动
setTimeout(() => {
document.body.classList.remove('easter-egg--shake');
}, 500);
// 设置自动恢复定时器
this.resetAutoRestoreTimer();
}, 600);
}
resetAutoRestoreTimer() {
if (this.restoreTimer) clearTimeout(this.restoreTimer);
// Random time between 5-10 seconds
const delay = 5000 + Math.random() * 5000;
this.restoreTimer = setTimeout(() => {
this.resetEffects();
}, delay);
}
resetEffects() {
document.body.classList.remove('easter-egg--shake');
document.body.classList.remove('easter-egg--broken');
if (this.restoreTimer) clearTimeout(this.restoreTimer);
}
triggerGroupChat() {
this.resetEffects();
// Open chat
groupChat.open();
// Reset count
this.clickCount = 0;
}
playBreakSound() {
try {
if (!this.audioCtx) {
this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
}
// 如果音频上下文处于挂起状态(浏览器策略),尝试恢复
if (this.audioCtx.state === 'suspended') {
this.audioCtx.resume();
}
const ctx = this.audioCtx;
// 1. 创建白噪音缓冲区
const bufferSize = ctx.sampleRate * 2.0; // 2秒
const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
const data = buffer.getChannelData(0);
for (let i = 0; i < bufferSize; i++) {
data[i] = Math.random() * 2 - 1;
}
// 2. 创建噪音源
const noise = ctx.createBufferSource();
noise.buffer = buffer;
// 3. 滤镜:高通滤波模拟玻璃的高频声
const filter = ctx.createBiquadFilter();
filter.type = 'highpass';
filter.frequency.value = 800;
filter.Q.value = 10; // 增加一些共振
// 4. 包络:控制音量变化模拟撞击和余音
const gain = ctx.createGain();
// 连接节点
noise.connect(filter);
filter.connect(gain);
gain.connect(ctx.destination);
// 设置包络参数
const now = ctx.currentTime;
// 冲击:瞬间大音量
gain.gain.setValueAtTime(0, now);
gain.gain.linearRampToValueAtTime(0.8, now + 0.01);
// 衰减:迅速下降
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.3);
// 播放
noise.start(now);
noise.stop(now + 0.3);
} catch (e) {
console.warn('Easter egg sound synthesis failed:', e);
}
}
}
评论加载中...