🎮ArcadeLab

孔明灯 · 祈福模拟器

by HyperMaker20
530 lines17.3 KB
▶ Play
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>孔明灯 · 祈福模拟器</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      user-select: none;
    }
    body {
      background: #0a0f1e;
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
    }
    .simulator {
      position: relative;
      width: 100%;
      max-width: 1000px;
      height: 700px;
      background: radial-gradient(circle at 50% 30%, #1a1f30, #080c14);
      border-radius: 40px;
      box-shadow: 0 30px 40px rgba(0, 0, 0, 0.7), inset 0 0 60px rgba(255, 200, 100, 0.2);
      overflow: hidden;
      border: 1px solid #3e4a5e;
    }
    /* 星空点缀 */
    .stars {
      position: absolute;
      inset: 0;
      background-image: radial-gradient(2px 2px at 20px 30px, #fff, rgba(0,0,0,0)),
                        radial-gradient(2px 2px at 80px 120px, #ffe, rgba(0,0,0,0)),
                        radial-gradient(3px 3px at 240px 50px, #ffd, rgba(0,0,0,0)),
                        radial-gradient(2px 2px at 400px 300px, #fff, rgba(0,0,0,0)),
                        radial-gradient(3px 3px at 560px 180px, #ffe, rgba(0,0,0,0)),
                        radial-gradient(2px 2px at 720px 80px, #fff, rgba(0,0,0,0)),
                        radial-gradient(2px 2px at 880px 400px, #ffd, rgba(0,0,0,0)),
                        radial-gradient(3px 3px at 100px 600px, #fff, rgba(0,0,0,0)),
                        radial-gradient(2px 2px at 300px 500px, #ffe, rgba(0,0,0,0)),
                        radial-gradient(2px 2px at 600px 650px, #fff, rgba(0,0,0,0)),
                        radial-gradient(2px 2px at 800px 550px, #ffd, rgba(0,0,0,0));
      background-repeat: no-repeat;
      background-size: 1000px 700px;
      opacity: 0.9;
      pointer-events: none;
    }

    /* 孔明灯容器 */
    .lanterns-container {
      position: absolute;
      inset: 0;
      pointer-events: none;
    }

    /* 每一盏孔明灯 */
    .lantern {
      position: absolute;
      width: 90px;
      height: 130px;
      filter: drop-shadow(0 0 18px rgba(255, 180, 40, 0.7));
      animation: floatUp 14s infinite ease-in-out;
      pointer-events: none;
      will-change: transform;
    }

    /* 灯体 (主体) */
    .lantern-body {
      position: absolute;
      width: 90px;
      height: 110px;
      background: radial-gradient(circle at 30% 25%, #ffd966, #e68a00 75%, #b35900);
      border-radius: 50% 50% 45% 45% / 60% 60% 40% 40%;
      box-shadow: 0 0 35px #ffb84d, inset 0 0 25px #ffdd99;
      border: 1px solid #ffcc66;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      text-align: center;
      padding: 10px 6px 18px 6px;
      overflow: hidden;
      transform: rotate(0deg);
    }

    /* 灯体上的文字 */
    .lantern-text {
      font-size: 11px;
      font-weight: 700;
      color: #2d1b00;
      text-shadow: 0 0 6px #ffdd99, 0 0 12px #ffaa33;
      line-height: 1.4;
      letter-spacing: 1px;
      writing-mode: horizontal-tb;
      word-break: break-word;
      width: 100%;
      padding: 0 4px;
      background: rgba(255, 220, 130, 0.2);
      border-radius: 30px;
      font-family: 'Microsoft YaHei', 'PingFang SC', sans-serif;
    }

    /* 灯底/火焰口 */
    .lantern-base {
      position: absolute;
      bottom: 0;
      left: 25px;
      width: 40px;
      height: 18px;
      background: #b35900;
      border-radius: 50% 50% 30% 30% / 30% 30% 70% 70%;
      box-shadow: inset 0 -4px 8px #4a2a00, 0 4px 10px #ff9900;
      border-top: 1px solid #ffaa33;
    }

    /* 飘动的火焰 */
    .flame {
      position: absolute;
      bottom: 12px;
      left: 38px;
      width: 14px;
      height: 22px;
      background: radial-gradient(circle at 50% 20%, #ffdd44, #ff8800 70%, #cc5500);
      border-radius: 50% 50% 40% 40% / 70% 70% 30% 30%;
      filter: blur(1px) drop-shadow(0 0 10px #ffaa00);
      animation: flicker 0.5s infinite alternate;
      opacity: 0.9;
    }

    /* 不同位置与动画延迟 */
    .lantern:nth-child(1) { left: 8%; top: 55%; animation-delay: 0s; animation-duration: 16s; }
    .lantern:nth-child(2) { left: 24%; top: 70%; animation-delay: 1.2s; animation-duration: 14s; }
    .lantern:nth-child(3) { left: 43%; top: 60%; animation-delay: 2.5s; animation-duration: 18s; }
    .lantern:nth-child(4) { left: 62%; top: 75%; animation-delay: 0.8s; animation-duration: 15s; }
    .lantern:nth-child(5) { left: 78%; top: 48%; animation-delay: 3.2s; animation-duration: 17s; }
    .lantern:nth-child(6) { left: 15%; top: 25%; animation-delay: 1.8s; animation-duration: 20s; }  /* 高处的小灯,慢速 */
    .lantern:nth-child(7) { left: 85%; top: 20%; animation-delay: 0.4s; animation-duration: 19s; }
    
    /* 对第6、7盏稍微缩小一点让层次更丰富 */
    .lantern:nth-child(6) .lantern-body,
    .lantern:nth-child(7) .lantern-body {
      transform: scale(0.85);
    }
    .lantern:nth-child(6) .lantern-base,
    .lantern:nth-child(7) .lantern-base,
    .lantern:nth-child(6) .flame,
    .lantern:nth-child(7) .flame {
      transform: scale(0.85);
      transform-origin: center bottom;
    }
    .lantern:nth-child(6) .lantern-text,
    .lantern:nth-child(7) .lantern-text {
      font-size: 9px;
    }

    /* 上升漂浮动画 */
    @keyframes floatUp {
      0% {
        transform: translateY(0px) translateX(0px) rotate(0deg);
        opacity: 0.9;
      }
      30% {
        transform: translateY(-40px) translateX(8px) rotate(1.5deg);
      }
      60% {
        transform: translateY(-100px) translateX(-6px) rotate(-1deg);
      }
      100% {
        transform: translateY(-220px) translateX(4px) rotate(1deg);
        opacity: 0.3;
      }
    }

    /* 火焰闪烁 */
    @keyframes flicker {
      0% { transform: scaleY(1) scaleX(1); opacity: 0.9; }
      100% { transform: scaleY(1.2) scaleX(0.9); opacity: 1; }
    }

    /* 文字签名(装饰) */
    .credit {
      position: absolute;
      bottom: 15px;
      right: 25px;
      color: #b8a88a;
      font-size: 13px;
      letter-spacing: 2px;
      opacity: 0.5;
      font-style: italic;
      text-shadow: 0 0 8px #ffbb33;
      z-index: 10;
    }

    /* 控制区域 — 输入框和按钮 */
    .input-area {
      position: absolute;
      bottom: 30px;
      left: 50%;
      transform: translateX(-50%);
      display: flex;
      gap: 16px;
      background: rgba(10, 15, 25, 0.75);
      backdrop-filter: blur(10px);
      padding: 14px 24px;
      border-radius: 60px;
      border: 1px solid #ffbb4d;
      box-shadow: 0 0 30px rgba(255, 170, 0, 0.3);
      z-index: 20;
      align-items: center;
    }

    .input-area input {
      width: 360px;
      padding: 12px 20px;
      border-radius: 40px;
      border: none;
      outline: 2px solid #ffaa33;
      background: #1e1e2e;
      color: #ffebc2;
      font-size: 16px;
      font-weight: 500;
      letter-spacing: 1px;
      font-family: 'Microsoft YaHei', sans-serif;
      transition: all 0.2s ease;
      box-shadow: inset 0 0 12px #00000055, 0 0 12px #ffaa3333;
    }

    .input-area input:focus {
      outline: 3px solid #ffcc66;
      background: #2a2a3a;
      color: #fff2d0;
      box-shadow: inset 0 0 8px #000, 0 0 20px #ffb347;
    }

    .input-area button {
      padding: 12px 28px;
      border-radius: 40px;
      border: none;
      background: linear-gradient(145deg, #ffb347, #e68a00);
      color: #1e1408;
      font-size: 17px;
      font-weight: 700;
      letter-spacing: 2px;
      cursor: pointer;
      box-shadow: 0 6px 0 #8b5a00, 0 8px 18px #00000055;
      transition: all 0.1s ease;
      font-family: 'Microsoft YaHei', sans-serif;
      border: 1px solid #ffdd99;
    }

    .input-area button:active {
      transform: translateY(5px);
      box-shadow: 0 1px 0 #8b5a00, 0 8px 18px #00000055;
    }

    .input-area button:hover {
      background: linear-gradient(145deg, #ffc266, #ff9f1a);
      box-shadow: 0 6px 0 #a06a00, 0 10px 22px #00000077;
    }

    /* 响应式微调 */
    @media (max-width: 750px) {
      .simulator { height: 600px; border-radius: 24px; }
      .input-area { flex-direction: column; width: 90%; padding: 16px; bottom: 16px; }
      .input-area input { width: 100%; font-size: 14px; }
      .input-area button { width: 100%; padding: 10px; font-size: 16px; }
      .lantern { width: 70px; height: 100px; }
      .lantern-body { width: 70px; height: 85px; }
      .lantern-base { left: 18px; width: 34px; }
      .flame { left: 28px; width: 12px; height: 18px; }
      .lantern-text { font-size: 9px; }
    }
  </style>
</head>
<body>
<div class="simulator">
  <div class="stars"></div>
  
  <div class="lanterns-container" id="lanternsContainer">
    <!-- 7盏孔明灯,文字统一为“沈岁段久谈宥永远在一起”,但每盏会显示同样文字,不过换行略有不同让视觉更丰富 -->
    <!-- 灯1 -->
    <div class="lantern">
      <div class="lantern-body">
        <div class="lantern-text" id="lanternText1">沈岁段久<br>谈宥永远<br>在一起</div>
      </div>
      <div class="lantern-base"></div>
      <div class="flame"></div>
    </div>
    <!-- 灯2 -->
    <div class="lantern">
      <div class="lantern-body">
        <div class="lantern-text" id="lanternText2">沈岁段久<br>谈宥永远<br>在一起</div>
      </div>
      <div class="lantern-base"></div>
      <div class="flame"></div>
    </div>
    <!-- 灯3 -->
    <div class="lantern">
      <div class="lantern-body">
        <div class="lantern-text" id="lanternText3">沈岁段久<br>谈宥永远<br>在一起</div>
      </div>
      <div class="lantern-base"></div>
      <div class="flame"></div>
    </div>
    <!-- 灯4 -->
    <div class="lantern">
      <div class="lantern-body">
        <div class="lantern-text" id="lanternText4">沈岁段久<br>谈宥永远<br>在一起</div>
      </div>
      <div class="lantern-base"></div>
      <div class="flame"></div>
    </div>
    <!-- 灯5 -->
    <div class="lantern">
      <div class="lantern-body">
        <div class="lantern-text" id="lanternText5">沈岁段久<br>谈宥永远<br>在一起</div>
      </div>
      <div class="lantern-base"></div>
      <div class="flame"></div>
    </div>
    <!-- 灯6 高处 小一点 -->
    <div class="lantern">
      <div class="lantern-body">
        <div class="lantern-text" id="lanternText6">沈岁段久<br>谈宥永远<br>在一起</div>
      </div>
      <div class="lantern-base"></div>
      <div class="flame"></div>
    </div>
    <!-- 灯7 高处 小一点 -->
    <div class="lantern">
      <div class="lantern-body">
        <div class="lantern-text" id="lanternText7">沈岁段久<br>谈宥永远<br>在一起</div>
      </div>
      <div class="lantern-base"></div>
      <div class="flame"></div>
    </div>
  </div>

  <div class="credit">✨ 愿 · 长相守 ✨</div>

  <!-- 输入与按钮 -->
  <div class="input-area">
    <input type="text" id="wishInput" placeholder="输入祈福文字..." value="沈岁段久谈宥永远在一起" maxlength="30">
    <button id="updateBtn">点亮孔明灯</button>
  </div>
</div>

<script>
  (function() {
    // 固定的初始文字,用户也可以修改
    const DEFAULT_TEXT = "沈岁段久谈宥永远在一起";
    // 获取所有文字元素
    const textElements = [
      document.getElementById('lanternText1'),
      document.getElementById('lanternText2'),
      document.getElementById('lanternText3'),
      document.getElementById('lanternText4'),
      document.getElementById('lanternText5'),
      document.getElementById('lanternText6'),
      document.getElementById('lanternText7')
    ];
    const wishInput = document.getElementById('wishInput');
    const updateBtn = document.getElementById('updateBtn');

    // 格式化函数:将输入文字拆分成适合孔明灯展示的样式
    // 为了美观,在适当位置插入换行。如果文字长度小于6,不强制换行;
    // 如果长于6,尝试分成3行;每行不超过4个字符左右。
    function formatLanternText(text) {
      // 去除首尾空格,保留原意,但不可为空
      let cleanText = text.trim();
      if (cleanText === '') cleanText = '沈岁段久谈宥永远在一起'; // 空的话恢复默认

      // 针对“沈岁段久谈宥永远在一起” 共11个字,我们按优美换行:
      // 如果正好是默认文本或类似长度,使用固定换行模式,否则智能换行
      if (cleanText === '沈岁段久谈宥永远在一起') {
        return '沈岁段久<br>谈宥永远<br>在一起';
      }

      // 若文字较短(<=6),直接一行显示
      if (cleanText.length <= 6) {
        // 但可以加一点微调,若长度4-6可以中间换行
        if (cleanText.length === 5) {
          return cleanText.slice(0, 3) + '<br>' + cleanText.slice(3);
        } else if (cleanText.length === 6) {
          return cleanText.slice(0, 3) + '<br>' + cleanText.slice(3);
        }
        return cleanText;
      }

      // 对于长文本:每行最多 4~5 个字符,分成多行
      const lines = [];
      let i = 0;
      // 根据长度动态决定每行字数,保证美观
      const perLine = cleanText.length > 15 ? 5 : 4; 
      while (i < cleanText.length) {
        lines.push(cleanText.slice(i, i + perLine));
        i += perLine;
      }
      // 用<br>拼接
      return lines.join('<br>');
    }

    // 更新所有孔明灯上的文字
    function updateAllLanterns(text) {
      const formatted = formatLanternText(text);
      textElements.forEach(el => {
        if (el) el.innerHTML = formatted;
      });
    }

    // 初始化,使用默认文字
    updateAllLanterns(DEFAULT_TEXT);
    wishInput.value = DEFAULT_TEXT;

    // 点击按钮更新
    updateBtn.addEventListener('click', function() {
      const newText = wishInput.value.trim();
      if (newText === '') {
        // 若为空,使用默认文字,并同步输入框
        wishInput.value = DEFAULT_TEXT;
        updateAllLanterns(DEFAULT_TEXT);
      } else {
        updateAllLanterns(newText);
      }
      // 添加一个轻微的按钮反馈动画
      updateBtn.style.transform = 'scale(0.96)';
      setTimeout(() => { updateBtn.style.transform = ''; }, 100);
    });

    // 按回车也可以触发
    wishInput.addEventListener('keypress', function(e) {
      if (e.key === 'Enter') {
        e.preventDefault();
        updateBtn.click();
      }
    });

    // 点击输入框时如果为默认文字全选方便修改
    wishInput.addEventListener('focus', function() {
      if (this.value === DEFAULT_TEXT) {
        this.select();
      }
    });

    // 动态调整一些孔明灯的文字尺寸以适应较长文字(简单处理,仅修改样式)
    // 但当文字过长时,format 已经拆行,加上字体自适应调整
    // 监听更新后文字长度?但不必太复杂,此处保留

    // 附加:为了让文字在不同长度下都显示清晰,可以添加一个小的自适应类
    // 不过现有字体11px/9px对于大多数短句都够用,如果用户输入特别长,可以缩小字体
    // 为了更友好,给updateAllLanterns加入字体大小调整
    const originalUpdate = updateAllLanterns;
    updateAllLanterns = function(text) {
      const formatted = formatLanternText(text);
      // 计算纯文本长度(去掉<br>)
      const rawLength = text.replace(/<br>/g, '').length;
      // 动态调整字体大小 (对于过长的文字)
      let fontSize = '11px';
      let smallFontSize = '9px'; // 用于第6、7盏
      if (rawLength > 14) {
        fontSize = '9px';
        smallFontSize = '8px';
      } else if (rawLength > 10) {
        fontSize = '10px';
        smallFontSize = '8.5px';
      } else {
        fontSize = '11px';
        smallFontSize = '9px';
      }

      textElements.forEach((el, index) => {
        if (!el) return;
        el.innerHTML = formatted;
        // 第6、7盏(索引5,6)使用稍小字体
        if (index === 5 || index === 6) {
          el.style.fontSize = smallFontSize;
        } else {
          el.style.fontSize = fontSize;
        }
        // 如果原始长度特别短,也可以放大一点
        if (rawLength <= 4 && (index !== 5 && index !== 6)) {
          el.style.fontSize = '12px';
        } else if (rawLength <= 4 && (index === 5 || index === 6)) {
          el.style.fontSize = '10px';
        }
      });
    };

    // 重新绑定, 用新的函数覆盖
    // 重新执行初始化
    updateAllLanterns(DEFAULT_TEXT);
    wishInput.value = DEFAULT_TEXT;

    // 按钮监听使用新的 updateAllLanterns
    updateBtn.onclick = function() {
      const newText = wishInput.value.trim();
      if (newText === '') {
        wishInput.value = DEFAULT_TEXT;
        updateAllLanterns(DEFAULT_TEXT);
      } else {
        updateAllLanterns(newText);
      }
      updateBtn.style.transform = 'scale(0.96)';
      setTimeout(() => { updateBtn.style.transform = ''; }, 100);
    };

    // 回车键重新绑定
    wishInput.onkeypress = function(e) {
      if (e.key === 'Enter') {
        e.preventDefault();
        updateBtn.click();
      }
    };

    // 保留全选
    wishInput.onfocus = function() {
      if (this.value === DEFAULT_TEXT) {
        this.select();
      }
    };

  })();
</script>
</body>
</html>

Game Source: 孔明灯 · 祈福模拟器

Creator: HyperMaker20

Libraries: none

Complexity: complex (530 lines, 17.3 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-hypermaker20-muh5sozh" to link back to the original. Then publish at arcadelab.ai/publish.