微件:GGLScratchGame:修订间差异

来自Limbo Wiki Mirror
Gaoice留言 | 贡献
无编辑摘要
标签(旧)WikiEditor
Gaoice留言 | 贡献
无编辑摘要
标签(旧)WikiEditor
第1行: 第1行:
<div class="ggl-frame">
<div class="ggl-root">


   <!-- 初始化遮罩 -->
   <!-- 初始化遮罩 -->
   <div class="ggl-overlay">
   <div class="ggl-mask" id="ggl-start-mask">
     <button class="ggl-start-btn">开始抽奖</button>
     <button class="ggl-start-btn">点击开始</button>
   </div>
   </div>


   <!-- 顶部信息 -->
   <!-- 顶部信息 -->
   <div class="ggl-top">
   <div class="ggl-top">
     <div class="ggl-rules">
     <div class="ggl-rule">
       点击灰色区域揭示内容,全部揭示后才能扫描。
       刮开奖券 · 每张需点完 30 格才能扫描
     </div>
     </div>
     <div class="ggl-remaining">
     <div class="ggl-left">
       剩余彩票:<span id="ggl-ticket-left"></span>
       剩余彩票:<span id="ggl-ticket-left">11</span>
     </div>
     </div>
   </div>
   </div>


   <!-- 彩票主体 -->
   <!-- 彩票主体 -->
   <div class="ggl-root">
   <div class="ggl-ticket">


     <img class="ggl-bg"
     <img class="ggl-bg"
        src="https://wm.gaoice.run/images/thumb/b/b6/%E5%9B%BE%E7%89%871.png/180px-%E5%9B%BE%E7%89%871.png">
      src="https://wm.gaoice.run/images/%E5%9B%BE%E7%89%871.png"
      alt="lottery">


     <!-- 刮奖区 -->
     <!-- 刮奖区域 -->
     <div class="ggl-scratch-area">
     <div class="ggl-scratch-area">
       <div class="ggl-grid"></div>
       <div class="ggl-grid"></div>
     </div>
     </div>


     <!-- 吉祥物 -->
     <!-- 吉祥物 & 气泡 -->
     <div class="ggl-mascot"></div>
     <div class="ggl-mascot">(^▽^)</div>
    <div class="ggl-bubble">准备开始。</div>


     <!-- 气泡 -->
     <!-- 底部控制 -->
    <div class="ggl-bubble"></div>
 
    <!-- 控制 -->
     <div class="ggl-controls">
     <div class="ggl-controls">
       <button id="ggl-scan">扫描结果</button>
       <button id="ggl-scan">扫描结果</button>
第40行: 第39行:
   </div>
   </div>
</div>
</div>
<style>
<style>
.ggl-frame {
/* ===== 根容器 ===== */
   max-width: 420px;
.ggl-root {
   margin: 20px auto;
   width: 375px;
  padding: 10px;
   margin: 0 auto;
  border: 2px solid #333;
  background: #111;
  color: #eee;
   font-family: sans-serif;
   font-family: sans-serif;
  position: relative;
}
}


/* 顶部 */
/* ===== 初始化遮罩 ===== */
.ggl-top {
.ggl-mask {
   position: absolute;
   position: absolute;
   top: 0;
   inset: 0;
   left: 0;
   background: rgba(0,0,0,.85);
   width: 100%;
   z-index: 20;
   height: 30%;
   display: flex;
   padding: 10px;
   align-items: center;
   box-sizing: border-box;
   justify-content: center;
}
}
 
.ggl-start-btn {
.ggl-rules {
  font-size: 14px;
  opacity: .8;
}
 
.ggl-remaining {
  margin-top: 6px;
   font-size: 16px;
   font-size: 16px;
   font-weight: bold;
   padding: 12px 20px;
}
}


.ggl-tickets-left {
/* ===== 顶部 ===== */
.ggl-top {
  text-align: center;
   font-size: 14px;
   font-size: 14px;
   margin-top: 4px;
   margin-bottom: 6px;
}
.ggl-rule {
  margin-bottom: 4px;
}
}


/* 彩票 */
/* ===== 彩票 ===== */
.ggl-root {
.ggl-ticket {
   position: relative;
   position: relative;
   width: 100%;
   width: 100%;
   aspect-ratio: 1075 / 1911;
   aspect-ratio: 1075 / 1911;
}
}
.ggl-bg {
.ggl-bg {
   width: 100%;
   width: 100%;
第90行: 第85行:
}
}


/* 刮奖区 */
/* ===== 刮奖区 ===== */
.ggl-scratch-area {
.ggl-scratch-area {
   position: absolute;
   position: absolute;
第98行: 第93行:
   height: 53%;
   height: 53%;
}
}
.ggl-grid {
.ggl-grid {
  width: 100%;
  height: 100%;
   display: grid;
   display: grid;
   grid-template-columns: repeat(5, 1fr);
   grid-template-columns: repeat(5, 1fr);
   grid-template-rows: repeat(6, 1fr);
   grid-template-rows: repeat(6, 1fr);
   gap: 4px;
   gap: 6px;
  width: 100%;
  height: 100%;
}
}


/* 单格 */
/* ===== 单格 ===== */
.ggl-cell {
.ggl-cell {
   position: relative;
   position: relative;
   cursor: pointer;
   overflow: hidden;
}
}
 
.ggl-cell img {
.ggl-cover,
.ggl-reveal {
   position: absolute;
   position: absolute;
   inset: 0;
   inset: 0;
   width: 100%;
   width: 100%;
   height: 100%;
   height: 100%;
  pointer-events: none;
}
.ggl-cover {
  z-index: 3;
}
.ggl-reveal {
  z-index: 1;
}
}
 
.ggl-reward {
/* 奖项层 */
.ggl-prize {
   position: absolute;
   position: absolute;
   inset: 0;
   inset: 0;
  z-index: 2;
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
   justify-content: center;
   justify-content: center;
   font-size: 12px;
   font-size: 12px;
   color: #000;
   font-weight: bold;
  text-align: center;
   pointer-events: none;
   pointer-events: none;
}
.ggl-cover {
  position: absolute;
  inset: 0;
  background: url("https://wm.gaoice.run/images/%E5%88%AE%E5%BC%80%E5%89%8D.png") center/cover;
  cursor: pointer;
}
}


/* 吉祥物 & 气泡 */
/* ===== 吉祥物 & 气泡 ===== */
.ggl-mascot {
.ggl-mascot {
   position: absolute;
   position: absolute;
   left: 6%;
   left: 6%;
   top: 105%;
   top: 105%
   bottom: 8%;
   bottom: 14%;
   font-size: 20px;
   font-size: 20px;
   color: #000;
   color: #000;
}
}
.ggl-bubble {
.ggl-bubble {
   position: absolute;
   position: absolute;
   left: 6%;
   left: 6%;
   bottom: 14%;
   bottom: 20%;
   top: 100%;
   top: 100%
   width: 60%;
   width: 60%;
   background: rgba(255,255,255,.9);
   background: rgba(255,255,255,.9);
  color: #000;
   padding: 6px;
   padding: 6px;
   font-size: 13px;
   font-size: 13px;
}
}


/* 扫描 */
/* ===== 控制 ===== */
.ggl-controls {
.ggl-controls {
   position: absolute;
   position: absolute;
   right: 6%;
   right: 6%;
   bottom: 8%;
   bottom: 10%;
}
}
#ggl-scan {
#ggl-scan {
   opacity: .3;
   opacity: .3;
  top: 105%
}
}
#ggl-scan.active {
#ggl-scan.active {
   opacity: 1;
   opacity: 1;
}
}
</style>


/* 遮罩 */
.ggl-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,.9);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ggl-start-btn {
  padding: 12px 24px;
  font-size: 16px;
}
</style>
<script>
<script>
(function () {
(function () {


  /********************
  * 全局状态
  ********************/
  const gameState = {
    totalTickets: 11,
    currentTicket: 1,
    totalCells: 30,
    revealedCells: 0,
    started: false,
    data: 0
  };
  /********************
  * DOM
  ********************/
   const grid = document.querySelector('.ggl-grid');
   const grid = document.querySelector('.ggl-grid');
   const bubble = document.querySelector('.ggl-bubble');
   const bubble = document.querySelector('.ggl-bubble');
   const mascot = document.querySelector('.ggl-mascot');
   const mascot = document.querySelector('.ggl-mascot');
   const scanBtn = document.getElementById('ggl-scan');
   const scanBtn = document.getElementById('ggl-scan');
  const ticketLeft = document.getElementById('ggl-ticket-left');
  const mask = document.getElementById('ggl-start-mask');


  const ticketLeftEl = document.getElementById('ggl-ticket-left');
   const TICKETS = [
  const startMask = document.getElementById('ggl-start-mask');
     { mascot:'(^▽^)', text:'欢迎,开始吧。', rewards:['DATA'] },
 
     { mascot:'(ノ◕ヮ◕)ノ', text:'可以连字哦。', rewards:['DATA','DATA','DATA','DATA'] },
  mascot.style.color = '#000';
     { mascot:'(・∀・)', text:'中了刮刮乐!', rewards:['DATA'] },
 
     { mascot:'(・_・)', text:'什么都没有。', rewards:[] },
  /********************
     { mascot:'(;゚Д゚)', text:'不太对劲。', rewards:['DATA'] },
  * 彩票剧情表(核心)
     { mascot:'', text:'……', rewards:[] },
  ********************/
     { mascot:'...', text:'▒▓░▒▓', rewards:['DATA'] },
   const TICKETS = {
     { mascot:'', text:'哦 嗯 嘿 哈', rewards:['DATA','DATA'] },
     1: {
     { mascot:'', text:'你是谁?', rewards:Array(30).fill('DATA') },
      mascot: '(^▽^)',
     { mascot:'', text:'停下来。', rewards:[], lock:true },
      text: '欢迎,先来三张试试吧。',
     { mascot:'平安喜乐', text:'你知道的太多了。', end:true }
      rewards: ['DATA', 'EMPTY', 'EMPTY']
   ];
    },
     2: {
      mascot: '(ノ◕ヮ◕)ノ',
      text: '四个字可以连在一起。',
      rewards: ['DATA','DATA','DATA','DATA']
    },
     3: {
      mascot: '(・∀・)',
      text: '中了刮刮乐!+1 Data',
      rewards: ['DATA']
    },
     4: {
      mascot: '(・_・)',
      text: '什么都没中。',
      rewards: []
    },
     5: {
      mascot: '(;゚Д゚)',
      text: '不对劲……又中了 Data。',
      rewards: ['DATA']
    },
     6: {
      mascot: '',
      text: '什么都没有。',
      rewards: []
    },
     7: {
      mascot: '...',
      text: '▒▓░▒▓░▒▓',
      rewards: ['DATA']
    },
     8: {
      mascot: '(^▽^)',
      text: '中了两张 Data!',
      rewards: ['DATA','DATA']
    },
     9: {
      mascot: '(・_・)',
      text: '……全部都是 Data?',
      rewards: Array(30).fill('DATA')
    },
     10: {
      mascot: '(;゚Д゚)',
      text: '停下来。',
      rewards: [],
      lock: true
    },
     11: {
      mascot: '平安喜乐',
      text: '你知道的太多了。',
      rewards: [],
      end: true
    }
  };
 
   /********************
  * 奖项坐标生成
  ********************/
  function buildRewardMap(ticket) {
    const map = Array(30).fill('EMPTY');
    const rewards = TICKETS[ticket].rewards || [];
    rewards.forEach((r, i) => map[i] = r);
    return map;
  }


   /********************
   let ticketIndex = 0;
  * UI 刷新
   let revealed = 0;
  ********************/
   function updateTopUI() {
    if (!ticketLeftEl) return;
    ticketLeftEl.textContent =
      gameState.totalTickets - gameState.currentTicket + 1;
  }


   function updateMascot(ticket) {
   function updateTop() {
     mascot.textContent = TICKETS[ticket].mascot || '';
     ticketLeft.textContent = TICKETS.length - ticketIndex;
    bubble.textContent = TICKETS[ticket].text || '';
   }
   }


  /********************
   function buildTicket() {
  * 构建 30 格
  ********************/
   function buildGrid(ticket) {
     grid.innerHTML = '';
     grid.innerHTML = '';
     gameState.revealedCells = 0;
     revealed = 0;
     scanBtn.classList.remove('active');
     scanBtn.classList.remove('active');


     const rewardMap = buildRewardMap(ticket);
    const t = TICKETS[ticketIndex];
     const locked = TICKETS[ticket].lock;
    mascot.textContent = t.mascot || '';
    bubble.textContent = t.text || '';
 
     const rewardMap = Array(30).fill('');
     (t.rewards||[]).forEach((r,i)=>rewardMap[i]=r);


     for (let i = 0; i < 30; i++) {
     for (let i=0;i<30;i++) {
       const cell = document.createElement('div');
       const cell = document.createElement('div');
       cell.className = 'ggl-cell';
       cell.className = 'ggl-cell';
       cell.innerHTML = `
       cell.innerHTML = `
         <img src="https://wm.gaoice.run/images/thumb/4/4a/%E5%88%AE%E5%BC%80%E5%90%8E.jpg/180px-%E5%88%AE%E5%BC%80%E5%90%8E.jpg">
         <img src="https://wm.gaoice.run/images/%E5%88%AE%E5%BC%80%E5%90%8E.jpg">
         <div class="ggl-reward">${rewardMap[i] === 'DATA' ? 'DATA' : ''}</div>
         <div class="ggl-reward">${rewardMap[i]}</div>
         <div class="ggl-cover"></div>
         <div class="ggl-cover"></div>
       `;
       `;
       const cover = cell.querySelector('.ggl-cover');
       const cover = cell.querySelector('.ggl-cover');
 
       if (!t.lock) {
       if (!locked) {
         cover.onclick = () => {
         cover.addEventListener('click', () => {
           if (cell.dataset.done) return;
           if (cell.dataset.done) return;
           cell.dataset.done = '1';
           cell.dataset.done = 1;
           cover.style.opacity = '0';
           cover.style.display = 'none';
           gameState.revealedCells++;
           revealed++;
 
           if (revealed === 30) scanBtn.classList.add('active');
           if (rewardMap[i] === 'DATA') {
         };
            gameState.data++;
          }
 
          if (gameState.revealedCells >= gameState.totalCells) {
            scanBtn.classList.add('active');
            bubble.textContent = '可以扫描了。';
          }
         });
       }
       }
       grid.appendChild(cell);
       grid.appendChild(cell);
     }
     }
   }
   }


   /********************
   scanBtn.onclick = () => {
  * 下一张彩票
     if (!scanBtn.classList.contains('active')) return;
  ********************/
     ticketIndex++;
  function nextTicket() {
     updateTop();
     gameState.currentTicket++;
     if (TICKETS[ticketIndex]?.end) {
     updateTopUI();
       document.body.style.filter='invert(1)';
 
       setTimeout(()=>location.href='/index.php?title=六世恶言之一',1200);
     if (gameState.currentTicket > gameState.totalTickets) return;
    } else {
 
       buildTicket();
     if (gameState.currentTicket === 11) {
       document.body.style.filter = 'invert(1)';
       bubble.style.background = '#000';
       bubble.style.color = 'red';
     }
     }
  };


    updateMascot(gameState.currentTicket);
   mask.onclick = () => {
    buildGrid(gameState.currentTicket);
     mask.remove();
  }
     updateTop();
 
     buildTicket();
   /********************
   };
  * 扫描按钮
  ********************/
  scanBtn.addEventListener('click', () => {
    if (!scanBtn.classList.contains('active')) return;
 
    bubble.textContent = '扫描中……';
 
    setTimeout(() => {
      if (TICKETS[gameState.currentTicket].end) {
        location.href = '/index.php?title=六世恶言之一';
      } else {
        nextTicket();
      }
    }, 800);
  });
 
  /********************
  * 初始化遮罩
  ********************/
  if (startMask) {
     startMask.addEventListener('click', () => {
      startMask.remove();
      gameState.started = true;
      updateTopUI();
      updateMascot(1);
      buildGrid(1);
     });
  } else {
    updateTopUI();
     updateMascot(1);
    buildGrid(1);
   }


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

2026年2月1日 (日) 19:39的版本

   <button class="ggl-start-btn">点击开始</button>
     刮开奖券 · 每张需点完 30 格才能扫描
     剩余彩票:11
   <img class="ggl-bg"
     src="%E5%9B%BE%E7%89%871.png"
     alt="lottery">
(^▽^)
准备开始。
     <button id="ggl-scan">扫描结果</button>

<style> /* ===== 根容器 ===== */ .ggl-root {

 width: 375px;
 margin: 0 auto;
 font-family: sans-serif;
 position: relative;

}

/* ===== 初始化遮罩 ===== */ .ggl-mask {

 position: absolute;
 inset: 0;
 background: rgba(0,0,0,.85);
 z-index: 20;
 display: flex;
 align-items: center;
 justify-content: center;

} .ggl-start-btn {

 font-size: 16px;
 padding: 12px 20px;

}

/* ===== 顶部 ===== */ .ggl-top {

 text-align: center;
 font-size: 14px;
 margin-bottom: 6px;

} .ggl-rule {

 margin-bottom: 4px;

}

/* ===== 彩票 ===== */ .ggl-ticket {

 position: relative;
 width: 100%;
 aspect-ratio: 1075 / 1911;

} .ggl-bg {

 width: 100%;
 display: block;

}

/* ===== 刮奖区 ===== */ .ggl-scratch-area {

 position: absolute;
 left: 10%;
 top: 35%;
 width: 80%;
 height: 53%;

} .ggl-grid {

 width: 100%;
 height: 100%;
 display: grid;
 grid-template-columns: repeat(5, 1fr);
 grid-template-rows: repeat(6, 1fr);
 gap: 6px;

}

/* ===== 单格 ===== */ .ggl-cell {

 position: relative;
 overflow: hidden;

} .ggl-cell img {

 position: absolute;
 inset: 0;
 width: 100%;
 height: 100%;

} .ggl-reward {

 position: absolute;
 inset: 0;
 display: flex;
 align-items: center;
 justify-content: center;
 font-size: 12px;
 font-weight: bold;
 pointer-events: none;

} .ggl-cover {

 position: absolute;
 inset: 0;
 background: url("%E5%88%AE%E5%BC%80%E5%89%8D.png") center/cover;
 cursor: pointer;

}

/* ===== 吉祥物 & 气泡 ===== */ .ggl-mascot {

 position: absolute;
 left: 6%;
 top: 105%
 bottom: 14%;
 font-size: 20px;
 color: #000;

} .ggl-bubble {

 position: absolute;
 left: 6%;
 bottom: 20%;
 top: 100%
 width: 60%;
 background: rgba(255,255,255,.9);
 padding: 6px;
 font-size: 13px;

}

/* ===== 控制 ===== */ .ggl-controls {

 position: absolute;
 right: 6%;
 bottom: 10%;

}

  1. ggl-scan {
 opacity: .3;
 top: 105%

}

  1. ggl-scan.active {
 opacity: 1;

} </style>

<script> (function () {

 const grid = document.querySelector('.ggl-grid');
 const bubble = document.querySelector('.ggl-bubble');
 const mascot = document.querySelector('.ggl-mascot');
 const scanBtn = document.getElementById('ggl-scan');
 const ticketLeft = document.getElementById('ggl-ticket-left');
 const mask = document.getElementById('ggl-start-mask');
 const TICKETS = [
   { mascot:'(^▽^)', text:'欢迎,开始吧。', rewards:['DATA'] },
   { mascot:'(ノ◕ヮ◕)ノ', text:'可以连字哦。', rewards:['DATA','DATA','DATA','DATA'] },
   { mascot:'(・∀・)', text:'中了刮刮乐!', rewards:['DATA'] },
   { mascot:'(・_・)', text:'什么都没有。', rewards:[] },
   { mascot:'(;゚Д゚)', text:'不太对劲。', rewards:['DATA'] },
   { mascot:, text:'……', rewards:[] },
   { mascot:'...', text:'▒▓░▒▓', rewards:['DATA'] },
   { mascot:, text:'哦 嗯 嘿 哈', rewards:['DATA','DATA'] },
   { mascot:, text:'你是谁?', rewards:Array(30).fill('DATA') },
   { mascot:, text:'停下来。', rewards:[], lock:true },
   { mascot:'平安喜乐', text:'你知道的太多了。', end:true }
 ];
 let ticketIndex = 0;
 let revealed = 0;
 function updateTop() {
   ticketLeft.textContent = TICKETS.length - ticketIndex;
 }
 function buildTicket() {
   grid.innerHTML = ;
   revealed = 0;
   scanBtn.classList.remove('active');
   const t = TICKETS[ticketIndex];
   mascot.textContent = t.mascot || ;
   bubble.textContent = t.text || ;
   const rewardMap = Array(30).fill();
   (t.rewards||[]).forEach((r,i)=>rewardMap[i]=r);
   for (let i=0;i<30;i++) {
     const cell = document.createElement('div');
     cell.className = 'ggl-cell';
     cell.innerHTML = `
       <img src="%E5%88%AE%E5%BC%80%E5%90%8E.jpg">
${rewardMap[i]}
     `;
     const cover = cell.querySelector('.ggl-cover');
     if (!t.lock) {
       cover.onclick = () => {
         if (cell.dataset.done) return;
         cell.dataset.done = 1;
         cover.style.display = 'none';
         revealed++;
         if (revealed === 30) scanBtn.classList.add('active');
       };
     }
     grid.appendChild(cell);
   }
 }
 scanBtn.onclick = () => {
   if (!scanBtn.classList.contains('active')) return;
   ticketIndex++;
   updateTop();
   if (TICKETS[ticketIndex]?.end) {
     document.body.style.filter='invert(1)';
     setTimeout(()=>location.href='/index.php?title=六世恶言之一',1200);
   } else {
     buildTicket();
   }
 };
 mask.onclick = () => {
   mask.remove();
   updateTop();
   buildTicket();
 };

})(); </script>