前言:当代码邂逅浪漫

在这个充满爱意的520,我仅用5分钟就完成了一个包含时空胶囊、动态情书、记忆时间轴等复杂功能的网页应用。这一切的实现密码,正是CodeBuddy展现的AI编程魔力。通过这次实践,我深刻体会到AI如何将创意快速转化为可运行的代码艺术。


以下是实际操作中的开发界面与最终呈现效果(文末附代码):

【CodeBuddy】今天520,我只教你一遍。_时间轴

【CodeBuddy】今天520,我只教你一遍。_时间轴_02

【CodeBuddy】今天520,我只教你一遍。_自动生成_03


一、AI编程的典型应用场景

1.1 动态UI生成

项目中渐变色背景、漂浮Emoji特效(floatEmojis动画)等视觉元素,AI通过自然语言描述自动生成CSS动画代码:

@keyframes floatUp {
    0% { transform: translateY(0) rotate(0deg); opacity: 0; }
    50% { opacity: 1; }
    100% { transform: translateY(-100px) rotate(360deg); opacity: 0; }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

1.2 交互逻辑构建

胶囊开关动画(capsule点击事件)与页面切换的协同逻辑,AI自动生成完整的DOM操作代码链:

capsule.addEventListener('click', () => {
    capsuleTop.style.transform = 'translateY(-30px) rotate(-10deg)';
    setTimeout(() => coverSection.classList.add('hidden'), 1000);
});
  • 1.
  • 2.
  • 3.
  • 4.

1.3 数据结构设计

记忆点时间轴(memories数组)的生成与管理,AI智能推荐了包含日期、文本、表情符号的三维数据结构方案。

二、核心功能实现解析

功能模块AI贡献点代码示例
粒子特效自动生成随机运动算法createParticles()函数实现
时间轴布局智能计算位置分布公式position = (index/(len-1))*90+5
表情输入系统推荐光标定位方案range.collapse(false)的应用
响应式设计自动生成媒体查询断点@media (max-width:768px)规则集

三、开发过程的技术突破

  1. 动画协调难题:AI建议采用setTimeout队列管理多个动画的时序关系
  2. 状态保持困境:通过AI生成的currentMemoryIndex索引方案实现跨页面数据传递
  3. 移动端适配:AI自动转换rem单位并优化触摸事件处理
  4. 性能优化:AI推荐will-change属性提升动画渲染性能

四、AI编程的惊艳之处

  1. 语义理解突破:准确理解"心形粒子特效"转换为hsl(330-390,100%,70%)色域
  2. 上下文感知:在创建floatingEmojis时自动补充pointer-events:none属性
  3. 代码优化建议:推荐用requestAnimationFrame替代常规定时器
  4. 错误预防:在audio.play()调用时自动添加异常捕获

五、实践中的深度思考

  1. 创意瓶颈突破:AI在20分钟内提供了3种时间轴布局方案,激发设计灵感
  2. 开发效率跃升:过去需要3天的工作量缩短至2小时完成
  3. 学习范式革新:通过AI生成的代码反向学习现代CSS特性(如backdrop-filter)
  4. 人机协作模式:开发者专注架构设计,AI处理实现细节的新型工作流

结语:智能时代的浪漫代码

当粒子特效在屏幕上绽放,时间轴载着记忆缓缓流动,我看到的不仅是520的浪漫告白,更是AI编程开启的新纪元。这场实践证明:AI不是替代开发者,而是将我们从重复劳动中解放,让人类智慧更专注地闪耀在创意与架构的星空。未来的编程世界,必将是人类想象力与AI执行力的完美协奏。


附:

index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>时空胶囊 - 520告白</title>
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
</head>
<body>
    <div class="emoji-background"></div>
    <div class="container">
        <!-- 封面区 -->
        <section id="cover" class="cover-section">
            💌 时空胶囊 💝
            <p class="subtitle animate__animated animate__fadeInUp">✨ 珍藏我对你的心意 ✨</p>
            <div class="capsule-container">
                <div class="capsule animate__animated animate__pulse animate__infinite">
                    <div class="capsule-top">💖</div>
                    <div class="capsule-body">📜</div>
                </div>
            </div>
            <div class="floating-emojis"></div>
        </section>

        <!-- 互动区 -->
        <section id="interaction" class="interaction-section hidden">
            <div class="time-machine">
                <div class="timeline"></div>
                <div class="memories"></div>
            </div>
        </section>

        <!-- 内容展示区 -->
        <section id="content" class="content-section hidden">
            <button class="back-btn fixed-back-btn">⏮ 返回时间轴</button>
            <div class="love-letter">
                <h2 id="h0">💝 致最爱的你 💘</h2>
                <div class="emoji-picker">
                    <span class="emoji-option">😊</span>
                    <span class="emoji-option">❤️</span>
                    <span class="emoji-option">🥰</span>
                    <span class="emoji-option">😘</span>
                    <span class="emoji-option">💕</span>
                    <span class="emoji-option">🌹</span>
                    <span class="emoji-option">🎁</span>
                    <span class="emoji-option"></span>
                </div>
                <div class="letter-content" contenteditable="true">
                    在这里写下你想说的话...
                </div>
                <button class="send-btn">🚀 发送心意</button>
            </div>
        </section>
    </div>

    <script src="app.js"></script>
</body>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.

style.css

:root {
    --primary-color: #ff6b9d;
    --secondary-color: #a56cc1;
    --accent-color: #ffb6c1;
    --text-color: #333;
    --light-text: #fff;
    --bg-gradient: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Arial', sans-serif;
}

body {
    background: var(--bg-gradient);
    color: var(--text-color);
    min-height: 100vh;
    overflow-x: hidden;
    transition: background 0.5s ease;
    position: relative;
}

/* Emoji背景 */
.emoji-background {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 0;
    overflow: hidden;
}

.emoji-background::before {
    content: "💖❤️💕💘💓💗💖❤️💕💘💓💗💖❤️💕💘💓💗";
    position: absolute;
    font-size: 24px;
    opacity: 0.1;
    animation: floatEmojis 60s linear infinite;
}

@keyframes floatEmojis {
    0% { transform: translateY(0) translateX(0); }
    50% { transform: translateY(-50vh) translateX(20vw); }
    100% { transform: translateY(-100vh) translateX(0); }
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem;
    text-align: center;
    position: relative;
    z-index: 1;
}

/* 封面区样式 */
.cover-section {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 80vh;
    position: relative;
}

.title {
    font-size: 3.5rem;
    margin-bottom: 1rem;
    color: var(--light-text);
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}

.subtitle {
    font-size: 1.5rem;
    margin-bottom: 3rem;
    color: var(--light-text);
}

/* 漂浮emoji */
.floating-emojis {
    position: absolute;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.floating-emojis span {
    position: absolute;
    font-size: 24px;
    animation: floatUp 5s ease-in-out infinite;
    opacity: 0.8;
}

@keyframes floatUp {
    0% { transform: translateY(0) rotate(0deg); opacity: 0; }
    50% { opacity: 1; }
    100% { transform: translateY(-100px) rotate(360deg); opacity: 0; }
}

/* 胶囊样式 */
.capsule-container {
    position: relative;
    margin: 2rem 0;
    cursor: pointer;
}

.capsule {
    position: relative;
    width: 150px;
    height: 250px;
    margin: 0 auto;
}

.capsule-top {
    position: absolute;
    top: 0;
    width: 150px;
    height: 75px;
    background: var(--primary-color);
    border-radius: 75px 75px 0 0;
    box-shadow: inset -5px -5px 15px rgba(0, 0, 0, 0.2);
    transition: all 0.5s ease;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
}

.capsule-body {
    position: absolute;
    bottom: 0;
    width: 150px;
    height: 175px;
    background: var(--secondary-color);
    border-radius: 0 0 75px 75px;
    box-shadow: inset -5px 5px 15px rgba(0, 0, 0, 0.2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
}

/* 互动区和内容区样式 */
.hidden {
    display: none;
    opacity: 0;
    transform: translateY(20px);
}

.interaction-section, 
.content-section {
    padding: 2rem;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 20px;
    margin-top: 2rem;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
    transition: all 0.5s ease;
    position: relative;
    backdrop-filter: blur(5px);
}

.time-machine {
    position: relative;
    height: 300px;
    overflow: hidden;
}

.timeline {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 80%;
    height: 4px;
    background: var(--primary-color);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
}

.memories {
    display: flex;
    justify-content: space-around;
    position: relative;
    height: 100%;
}

.love-letter {
    padding: 2rem;
}

/* Emoji选择器 */
.emoji-picker {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-bottom: 1rem;
    flex-wrap: wrap;
}

.emoji-option {
    font-size: 1.5rem;
    cursor: pointer;
    transition: all 0.2s ease;
    padding: 5px;
    border-radius: 50%;
}

.emoji-option:hover {
    transform: scale(1.2);
    background: rgba(255, 192, 203, 0.3);
}

.letter-content {
    min-height: 300px;
    width: 90%;
    max-width: 800px;
    margin: 1rem auto;
    padding: 1.5rem;
    border: 2px dashed var(--primary-color);
    border-radius: 10px;
    text-align: left;
    font-size: 1.1rem;
    line-height: 1.6;
}

.send-btn {
    background: var(--primary-color);
    color: white;
    border: none;
    padding: 0.8rem 2rem;
    border-radius: 50px;
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.3s ease;
    margin-top: 1rem;
    display: flex;
    align-items: center;
    gap: 5px;
}

.send-btn:hover {
    background: var(--secondary-color);
    transform: translateY(-3px);
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}

/* 返回按钮样式 */
.back-btn {
    background: var(--accent-color);
    color: white;
    border: none;
    padding: 0.8rem 2rem;
    border-radius: 50px;
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.3s ease;
    margin-left: 1rem;
    display: flex;
    align-items: center;
    gap: 5px;
}

.back-btn:hover {
    background: var(--secondary-color);
    transform: translateY(-3px);
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}

/* 固定返回按钮样式 */
.fixed-back-btn {
    position: absolute;
    top: 20px;
    left: 20px;
    background: var(--accent-color);
    color: white;
    border: none;
    padding: 0.6rem 1.5rem;
    border-radius: 50px;
    font-size: 1rem;
    cursor: pointer;
    transition: all 0.3s ease;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 5px;
}

.fixed-back-btn:hover {
    background: var(--secondary-color);
    transform: translateY(-2px);
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
}

/* 粒子效果样式 */
.particles {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 100;
}

.particle {
    position: absolute;
    border-radius: 50%;
    opacity: 0.8;
    animation: float-up ease-out forwards;
}

@keyframes float-up {
    to {
        transform: translateY(-100px) rotate(360deg);
        opacity: 0;
    }
}

/* 记忆项样式 */
.memory {
    position: absolute;
    background: white;
    padding: 0.8rem;
    border-radius: 10px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
    transform: translate(-50%, -50%);
    cursor: pointer;
    transition: all 0.3s ease;
    text-align: center;
    min-width: 120px;
}

.memory:hover {
    transform: translate(-50%, -50%) scale(1.1);
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}

.memory-date {
    font-size: 0.8rem;
    color: var(--primary-color);
    margin-bottom: 0.3rem;
}

.memory-text {
    font-weight: bold;
    margin-bottom: 0.3rem;
}

.memory-emoji {
    font-size: 1.5rem;
}

/* 心形动画样式 */
.heart {
    position: fixed;
    animation: float-heart ease-out forwards;
    pointer-events: none;
    z-index: 100;
}

@keyframes float-heart {
    to {
        transform: translateY(-100px);
        opacity: 0;
    }
}

/* 响应式设计 */
@media (max-width: 768px) {
    .title {
        font-size: 2.5rem;
    }
    
    .subtitle {
        font-size: 1.2rem;
    }
    
    .capsule {
        width: 120px;
        height: 200px;
    }
    
    .capsule-top {
        width: 120px;
        height: 60px;
        font-size: 1.5rem;
    }
    
    .capsule-body {
        width: 120px;
        height: 140px;
        font-size: 1.5rem;
    }

    .send-btn, .back-btn, .fixed-back-btn {
        padding: 0.6rem 1.5rem;
        font-size: 1rem;
        margin: 0.5rem 0;
    }

    .letter-content {
        min-height: 250px;
        padding: 1rem;
    }
    
    .emoji-picker {
        gap: 8px;
    }
    
    .emoji-option {
        font-size: 1.2rem;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.
  • 272.
  • 273.
  • 274.
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
  • 280.
  • 281.
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
  • 287.
  • 288.
  • 289.
  • 290.
  • 291.
  • 292.
  • 293.
  • 294.
  • 295.
  • 296.
  • 297.
  • 298.
  • 299.
  • 300.
  • 301.
  • 302.
  • 303.
  • 304.
  • 305.
  • 306.
  • 307.
  • 308.
  • 309.
  • 310.
  • 311.
  • 312.
  • 313.
  • 314.
  • 315.
  • 316.
  • 317.
  • 318.
  • 319.
  • 320.
  • 321.
  • 322.
  • 323.
  • 324.
  • 325.
  • 326.
  • 327.
  • 328.
  • 329.
  • 330.
  • 331.
  • 332.
  • 333.
  • 334.
  • 335.
  • 336.
  • 337.
  • 338.
  • 339.
  • 340.
  • 341.
  • 342.
  • 343.
  • 344.
  • 345.
  • 346.
  • 347.
  • 348.
  • 349.
  • 350.
  • 351.
  • 352.
  • 353.
  • 354.
  • 355.
  • 356.
  • 357.
  • 358.
  • 359.
  • 360.
  • 361.
  • 362.
  • 363.
  • 364.
  • 365.
  • 366.
  • 367.
  • 368.
  • 369.
  • 370.
  • 371.
  • 372.
  • 373.
  • 374.
  • 375.
  • 376.
  • 377.
  • 378.
  • 379.
  • 380.
  • 381.
  • 382.
  • 383.
  • 384.
  • 385.
  • 386.
  • 387.
  • 388.
  • 389.
  • 390.
  • 391.
  • 392.
  • 393.
  • 394.
  • 395.
  • 396.
  • 397.
  • 398.
  • 399.
  • 400.
  • 401.
  • 402.
  • 403.
  • 404.
  • 405.
  • 406.
  • 407.
  • 408.
  • 409.
  • 410.
  • 411.
  • 412.
  • 413.
  • 414.
  • 415.
  • 416.
  • 417.
  • 418.
  • 419.
  • 420.

app.js

document.addEventListener('DOMContentLoaded', function() {
    // 获取DOM元素
    const capsule = document.querySelector('.capsule');
    const capsuleTop = document.querySelector('.capsule-top');
    const coverSection = document.getElementById('cover');
    const interactionSection = document.getElementById('interaction');
    const contentSection = document.getElementById('content');
    const sendBtn = document.querySelector('.send-btn');
    const backBtn = document.querySelector('.fixed-back-btn');
    const letterContent = document.querySelector('.letter-content');
    const emojiPicker = document.querySelector('.emoji-picker');
    const floatingEmojis = document.querySelector('.floating-emojis');
    
    // 模拟回忆数据,每个记忆点独立存储情书内容
    const memories = [
        { 
            date: '2023-01-01', 
            text: '我们第一次相遇的日子', 
            emoji: '❤️🌸🎉',
            letter: '在这里写下你想说的话...'
        },
        { 
            date: '2023-02-14', 
            text: '第一个情人节', 
            emoji: '🌹💝🍫',
            letter: '在这里写下你想说的话...'
        },
        { 
            date: '2023-05-20', 
            text: '去年的520', 
            emoji: '💌💐🎀',
            letter: '在这里写下你想说的话...'
        },
        { 
            date: '2023-12-25', 
            text: '一起度过的圣诞节', 
            emoji: '🎄🎁⛄',
            letter: '在这里写下你想说的话...'
        },
        { 
            date: '2024-02-14', 
            text: '今年的情人节', 
            emoji: '🥂💘🌠',
            letter: '在这里写下你想说的话...'
        }
    ];
    
    let currentMemoryIndex = null;

    // 初始化漂浮emoji
    function initFloatingEmojis() {
        const emojis = ['💖', '❤️', '💕', '💘', '💓', '💗', '🌸', '🌹', '💐', '🎀'];
        for (let i = 0; i < 20; i++) {
            const emoji = document.createElement('span');
            emoji.textContent = emojis[Math.floor(Math.random() * emojis.length)];
            emoji.style.left = `${Math.random() * 100}%`;
            emoji.style.top = `${Math.random() * 100}%`;
            emoji.style.animationDuration = `${Math.random() * 3 + 3}s`;
            emoji.style.animationDelay = `${Math.random() * 2}s`;
            floatingEmojis.appendChild(emoji);
        }
    }

    // 初始化emoji选择器 - 简化版
    function initEmojiPicker() {
        const emojis = ['😊', '❤️', '🥰', '😘', '💕', '🌹', '🎁', '✨', '👍', '🎉', '💯', '💋'];
        emojis.forEach(emoji => {
            const emojiOption = document.createElement('span');
            emojiOption.className = 'emoji-option';
            emojiOption.textContent = emoji;
            emojiOption.addEventListener('click', function() {
                // 确保内容框有焦点
                letterContent.focus();
                
                // 如果是默认文本则清空
                if(letterContent.textContent === '在这里写下你想说的话...') {
                    letterContent.textContent = '';
                }
                
                // 简单追加emoji到内容末尾
                letterContent.textContent += emoji;
                
                // 将光标移动到内容末尾
                const range = document.createRange();
                const selection = window.getSelection();
                range.selectNodeContents(letterContent);
                range.collapse(false);
                selection.removeAllRanges();
                selection.addRange(range);
            });
            emojiPicker.appendChild(emojiOption);
        });
        
        // 点击内容框时清空默认文本
        letterContent.addEventListener('click', function() {
            if(letterContent.textContent === '在这里写下你想说的话...') {
                letterContent.textContent = '';
            }
        });
    }

    // 胶囊点击事件
    capsule.addEventListener('click', function() {
        // 胶囊开启动画
        capsuleTop.style.transform = 'translateY(-30px) rotate(-10deg)';
        capsuleTop.style.boxShadow = 'none';
        
        // 添加粒子效果
        createParticles();
        
        // 延迟后切换页面
        setTimeout(() => {
            coverSection.classList.add('hidden');
            interactionSection.classList.remove('hidden');
            
            // 初始化时间轴
            initTimeline();
            
            // 延迟显示内容区
            setTimeout(() => {
                interactionSection.style.opacity = '1';
                interactionSection.style.transform = 'translateY(0)';
            }, 100);
        }, 1000);
    });

    // 初始化时间轴
    function initTimeline() {
        const timeline = document.querySelector('.timeline');
        const memoriesContainer = document.querySelector('.memories');
        memoriesContainer.innerHTML = '';
        
        memories.forEach((memory, index) => {
            const memoryElement = document.createElement('div');
            memoryElement.className = 'memory';
            memoryElement.innerHTML = `
                <div class="memory-date">${memory.date}</div>
                <div class="memory-text">${memory.text}</div>
                <div class="memory-emoji">${memory.emoji}</div>
            `;
            
            // 设置位置,确保首尾记忆点完全显示
            let position;
            if (index === 0) {
                position = 5; // 第一个记忆点向右偏移5%
            } else if (index === memories.length - 1) {
                position = 95; // 最后一个记忆点向左偏移5%
            } else {
                position = (index / (memories.length - 1)) * 90 + 5; // 中间记忆点均匀分布
            }
            
            memoryElement.style.left = `${position}%`;
            memoryElement.style.top = `${Math.random() * 60 + 20}%`;
            
            // 点击记忆项显示内容区
            memoryElement.addEventListener('click', () => {
                currentMemoryIndex = index;
                interactionSection.classList.add('hidden');
                contentSection.classList.remove('hidden');
                letterContent.innerHTML = memories[index].letter;
                
                setTimeout(() => {
                    contentSection.style.opacity = '1';
                    contentSection.style.transform = 'translateY(0)';
                }, 100);
            });
            
            memoriesContainer.appendChild(memoryElement);
        });
    }

    // 固定返回按钮点击事件
    backBtn.addEventListener('click', function() {
        contentSection.classList.add('hidden');
        interactionSection.classList.remove('hidden');
    });

    // 发送按钮点击事件
    sendBtn.addEventListener('click', function() {
        if (letterContent.textContent.trim() === '在这里写下你想说的话...' || 
            letterContent.textContent.trim() === '') {
            alert('请先写下你的心意!');
            return;
        }
        
        if (currentMemoryIndex === null) return;
        
        sendBtn.textContent = '发送中...';
        sendBtn.disabled = true;
        
        // 保存到对应记忆点
        memories[currentMemoryIndex].letter = letterContent.innerHTML;
        
        // 模拟发送过程
        setTimeout(() => {
            sendBtn.textContent = '已发送 💖';
            
            // 创建心形动画
            createHearts();
            
            // 重置按钮状态
            setTimeout(() => {
                sendBtn.textContent = '🚀 发送心意';
                sendBtn.disabled = false;
            }, 2000);
        }, 1500);
    });

    // 创建粒子效果
    function createParticles() {
        const particlesContainer = document.createElement('div');
        particlesContainer.className = 'particles';
        document.body.appendChild(particlesContainer);
        
        for (let i = 0; i < 50; i++) {
            const particle = document.createElement('div');
            particle.className = 'particle';
            
            // 随机位置和大小
            const size = Math.random() * 15 + 5;
            const x = Math.random() * 100;
            const y = Math.random() * 100;
            
            particle.style.width = `${size}px`;
            particle.style.height = `${size}px`;
            particle.style.left = `${x}%`;
            particle.style.top = `${y}%`;
            particle.style.backgroundColor = `hsl(${Math.random() * 60 + 330}, 100%, 70%)`;
            particle.style.animationDuration = `${Math.random() * 3 + 2}s`;
            
            particlesContainer.appendChild(particle);
        }
        
        // 动画结束后移除粒子
        setTimeout(() => {
            particlesContainer.remove();
        }, 3000);
    }

    // 创建心形动画
    function createHearts() {
        for (let i = 0; i < 10; i++) {
            const heart = document.createElement('div');
            heart.innerHTML = '💖';
            heart.className = 'heart';
            heart.style.left = `${Math.random() * 100}%`;
            heart.style.animationDuration = `${Math.random() * 2 + 1}s`;
            heart.style.fontSize = `${Math.random() * 20 + 10}px`;
            
            document.body.appendChild(heart);
            
            // 动画结束后移除
            setTimeout(() => {
                heart.remove();
            }, 2000);
        }
    }

    // 添加背景音乐控制
    const audio = new Audio('https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3');
    audio.loop = true;
    
    // 页面点击后自动播放音乐(解决浏览器自动播放限制)
    document.body.addEventListener('click', function() {
        audio.play().catch(e => console.log('自动播放被阻止:', e));
    }, { once: true });

    // 初始化
    initFloatingEmojis();
    initEmojiPicker();
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.



🌟 让技术经验流动起来

▌▍▎▏ 你的每个互动都在为技术社区蓄能 ▏▎▍▌
点赞 → 让优质经验被更多人看见
📥 收藏 → 构建你的专属知识库
🔄 转发 → 与技术伙伴共享避坑指南

点赞 ➕ 收藏 ➕ 转发,助力更多小伙伴一起成长!💪

💌 深度连接
点击 「头像」→「+关注」
每周解锁:
🔥 一线架构实录 | 💡 故障排查手册 | 🚀 效能提升秘籍