用户:Gaoice/沙盒:修订间差异
来自Limbo Wiki Mirror
无编辑摘要 标签:(旧)WikiEditor |
无编辑摘要 标签:(旧)WikiEditor |
||
| 第1行: | 第1行: | ||
{{# | <noinclude> | ||
|bg=https://wm.gaoice.run/images/thumb/b/b6/%E5%9B%BE%E7%89%871.png/180px-%E5%9B%BE%E7%89%871.png | == 刮刮乐重构版 == | ||
使用方式:修改第 222-224 行的图片URL,然后保存此页面 | |||
当前配置的图片: | |||
}} | * 底图(bg):https://wm.gaoice.run/images/thumb/b/b6/%E5%9B%BE%E7%89%871.png/180px-%E5%9B%BE%E7%89%871.png | ||
* 覆盖图(cover):https://wm.gaoice.run/images/thumb/5/5a/%E5%88%AE%E5%BC%80%E5%89%8D.png/180px-%E5%88%AE%E5%BC%80%E5%89%8D.png | |||
* 底层图(revealed):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 | |||
</noinclude> | |||
<includeonly> | |||
<style> | |||
/* === 核心容器 === */ | |||
.ggl-game-root { | |||
max-width: 400px; /* 限制最大显示宽度,防止在大屏太巨大 */ | |||
margin: 20px auto; | |||
font-family: 'Courier New', monospace; | |||
user-select: none; | |||
} | |||
.game-header { | |||
text-align: center; | |||
color: #555; | |||
margin-bottom: 10px; | |||
font-weight: bold; | |||
} | |||
/* === 彩票视觉部分 === */ | |||
.ticket-wrapper { | |||
position: relative; | |||
width: 100%; | |||
/* 核心:保持 1075:1911 的宽高比 */ | |||
padding-bottom: 177.76%; | |||
background-size: 100% 100%; | |||
background-repeat: no-repeat; | |||
box-shadow: 0 10px 20px rgba(0,0,0,0.3); | |||
border-radius: 8px; | |||
} | |||
/* === 刮奖区定位 (关键) === */ | |||
.scratch-grid-overlay { | |||
position: absolute; | |||
/* 以下百分比是根据 1075x1911 图和 846x1020 区域计算得出 */ | |||
width: 78.7%; /* 846 / 1075 */ | |||
height: 53.4%; /* 1020 / 1911 */ | |||
left: 10.65%; /* (100% - 78.7%) / 2 */ | |||
top: 34%; /* 估算黄色区域距离顶部的距离,可根据实际效果微调 */ | |||
display: grid; | |||
grid-template-columns: repeat(5, 1fr); | |||
grid-template-rows: repeat(6, 1fr); | |||
/* 消除格子间隙,因为你的图是连续的 */ | |||
gap: 0; | |||
} | |||
/* === 格子样式 === */ | |||
.grid-cell { | |||
width: 100%; | |||
height: 100%; | |||
background-size: 100% 100%; /* 强制图片拉伸填满格子 */ | |||
background-repeat: no-repeat; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
cursor: pointer; | |||
/* 初始文字透明 (刮开前看不到字) */ | |||
color: transparent; | |||
font-weight: bold; | |||
font-size: 14px; | |||
/* 文字描边,防止在复杂背景看不清 */ | |||
text-shadow: 1px 1px 0 #fff, -1px -1px 0 #fff; | |||
} | |||
/* 刮开后的状态 */ | |||
.grid-cell.revealed { | |||
cursor: default; | |||
color: #d32f2f; /* 刮开后文字颜色 */ | |||
} | |||
/* === 底部控制区 (重写布局) === */ | |||
.controls-area { | |||
margin-top: 15px; | |||
display: flex; | |||
justify-content: space-between; /* 左右分布 */ | |||
align-items: flex-end; | |||
} | |||
/* 左侧:气泡+颜文字 */ | |||
.mascot-box { | |||
flex: 1; | |||
text-align: left; | |||
margin-right: 10px; | |||
} | |||
.speech-bubble { | |||
background: #fff; | |||
border: 1px solid #333; | |||
border-radius: 8px 8px 8px 0; | |||
padding: 8px; | |||
font-size: 12px; | |||
margin-bottom: 5px; | |||
box-shadow: 2px 2px 0 rgba(0,0,0,0.1); | |||
min-height: 20px; | |||
line-height: 1.3; | |||
} | |||
.mascot-face { | |||
font-size: 18px; | |||
font-weight: bold; | |||
color: #333; | |||
margin-left: 5px; | |||
} | |||
/* 右侧:按钮 */ | |||
.action-btn { | |||
padding: 0 20px; | |||
height: 40px; | |||
font-size: 14px; | |||
background: #2196F3; | |||
color: white; | |||
border: none; | |||
border-radius: 5px; | |||
cursor: pointer; | |||
box-shadow: 2px 2px 0 #000; | |||
white-space: nowrap; | |||
} | |||
.action-btn:active { | |||
transform: translate(2px, 2px); | |||
box-shadow: none; | |||
} | |||
.action-btn:disabled { | |||
background: #ccc; | |||
box-shadow: none; | |||
} | |||
.action-btn.next { background: #4CAF50; } | |||
.action-btn.danger { background: #000; color: red; border: 1px solid red; } | |||
/* 结局特效 */ | |||
.invert-filter { filter: invert(100%); background: black !important; } | |||
.crash-screen { | |||
position: fixed; top: 0; left: 0; width: 100%; height: 100%; | |||
background: black; color: red; z-index: 99999; | |||
display: flex; align-items: center; justify-content: center; | |||
font-size: 30px; | |||
} | |||
</style> | |||
<!-- HTML 结构 --> | |||
<!-- WIDGET_PARAMS: bg={{{bg}}}, cover={{{cover}}}, revealed={{{revealed}}} --> | |||
<div class="ggl-game-root" id="ggl-root"> | |||
<div class="game-header"> | |||
GGL-LOTTERY | 剩余: <span id="count-val">3</span> | |||
</div> | |||
<!-- 1. 彩票底图层 --> | |||
<!-- 用 data-* 属性存放参数,避免style属性中的模板解析失败 --> | |||
<div class="ticket-wrapper" id="ticket-bg" data-bg="{{{bg|图片1.png}}}" data-cover="{{{cover|刮开前.png}}}" data-revealed="{{{revealed|刮开后.jpg}}}"> | |||
<!-- 2. 刮奖区覆盖层 (绝对定位) --> | |||
<div class="scratch-grid-overlay" id="scratch-grid"> | |||
<!-- JS 生成格子 --> | |||
</div> | |||
<!-- ID 显示 (可选,定位在右上角或哪里,这里为了简洁先隐藏或微调) --> | |||
<div style="position: absolute; top: 2%; right: 5%; color: white; font-weight: bold; font-size: 12px;"> | |||
NO.<span id="ticket-id">001</span> | |||
</div> | |||
</div> | |||
<!-- 3. 底部控制 --> | |||
<div class="controls-area"> | |||
<div class="mascot-box"> | |||
<div class="speech-bubble" id="mascot-text">请刮开所有区域...</div> | |||
<div class="mascot-face" id="mascot-face">(・ω・)</div> | |||
</div> | |||
<button id="main-btn" class="action-btn">扫描结果</button> | |||
</div> | |||
</div> | |||
<!-- 伪词条 --> | |||
<div id="fake-wiki-entry" style="display:none; padding:20px; background:#fff; border:1px solid #ccc; max-width:800px; margin:20px auto;"> | |||
<h1 style="border-bottom: 1px solid #aaa;">六世恶言</h1> | |||
<div style="margin-top:10px;"> | |||
<p><b>描述:</b>“六世恶言”是一种具有高度认知危害的网络异常...</p> | |||
<hr> | |||
<p><b>收藏品3:</b> [回复] <b>“它是我藏在赛博刮刮乐内的,是被惩罚的人。”</b></p> | |||
</div> | |||
</div> | |||
<script> | |||
(function() { | |||
var root = document.getElementById('ggl-root'); | |||
if (!root) return; | |||
// ===== 参数配置 ===== | |||
// 直接在这里修改图片URL | |||
var imgBg = 'https://wm.gaoice.run/images/thumb/b/b6/%E5%9B%BE%E7%89%871.png/180px-%E5%9B%BE%E7%89%871.png'; | |||
var imgCover = 'https://wm.gaoice.run/images/thumb/5/5a/%E5%88%AE%E5%BC%80%E5%89%8D.png/180px-%E5%88%AE%E5%BC%80%E5%89%8D.png'; | |||
var imgRevealed = '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'; | |||
// 调试:打印最终获取的参数 | |||
console.log('Widget参数:', { imgBg, imgCover, imgRevealed }); | |||
// 应用背景图 | |||
var elTicketBg = document.getElementById('ticket-bg'); | |||
if (elTicketBg && imgBg) { | |||
elTicketBg.style.backgroundImage = "url('" + imgBg + "')"; | |||
} | |||
var TOTAL_CARDS = 11; | |||
var currentIdx = 0; | |||
var remain = 3; | |||
var isScanned = false; | |||
var revealedCount = 0; | |||
// DOM | |||
var elCount = root.querySelector('#count-val'); | |||
var elGrid = root.querySelector('#scratch-grid'); | |||
var elBtn = root.querySelector('#main-btn'); | |||
var elBubble = root.querySelector('#mascot-text'); | |||
var elFace = root.querySelector('#mascot-face'); | |||
var elId = root.querySelector('#ticket-id'); | |||
var elFakeEntry = document.getElementById('fake-wiki-entry'); | |||
// 数据 | |||
var cards = [ | |||
{ type: 'n', face: '', text: '结果:谢谢惠顾。' }, | |||
{ type: 'n', face: '(・ω・)', text: '检测到异常字符。' }, | |||
{ type: 'b', face: '(^▽^)', text: '恭喜!触发连击,奖励+2张!' }, | |||
{ type: 'n', face: 'o(*≧▽≦)ツ', text: '结果:1 Data 2。好耶!' }, | |||
{ type: 'c', face: '( ・_・)', text: '结果:中奖...?数据好像变了。' }, | |||
{ type: 'x', face: '', text: '对象已消失。', val: 'Data' }, | |||
{ type: 'g', face: '...', text: 'ERR_#0x00 数据损坏', val: '???' }, | |||
{ type: 'p', face: '', text: '声音检测:"好痛!"', val: 'Pain' }, | |||
{ type: 't', face: '', text: '收到文本:"你是谁?"', val: 'Info' }, | |||
{ type: 's', face: '', text: '警告:立即停止操作。', val: '停下' }, | |||
{ type: 'f', face: 'ERROR', text: '你知道的太多了。', val: '平安喜乐' } | |||
]; | |||
function setMascot(txt, face) { | |||
if(txt) elBubble.innerText = txt; | |||
if(face !== undefined) elFace.innerText = face; | |||
} | |||
function randVal() { | |||
var arr = ['10mb', '50Gb', '5Kb', '1Tb', '福', '寿', '乐', '奖', '空']; | |||
return arr[Math.floor(Math.random() * arr.length)]; | |||
} | |||
function initCard(idx) { | |||
isScanned = false; | |||
revealedCount = 0; | |||
elBtn.innerText = "扫描结果"; | |||
elBtn.className = "action-btn"; | |||
elBtn.disabled = false; | |||
elBtn.style = ""; | |||
elId.innerText = (idx+1).toString().padStart(3,'0'); | |||
elCount.innerText = remain; | |||
var d = cards[idx]; | |||
elGrid.innerHTML = ''; | |||
setMascot("请刮开所有区域...", d.face); | |||
if(d.type === 's') { // Stop | |||
elBtn.style.border = "2px solid red"; | |||
elBtn.style.color = "red"; | |||
} | |||
for(var i=0; i<30; i++) { | |||
var cell = document.createElement('div'); | |||
cell.className = 'grid-cell'; | |||
// 1. 设置刮开前的图 (覆盖层) | |||
cell.style.backgroundImage = "url('" + imgCover + "')"; | |||
// 决定内容 | |||
var val = d.val ? d.val : randVal(); | |||
if(idx === 2 && (i===10 || i===11)) val = "大奖"; | |||
if(idx === 8) val = "你是谁"; | |||
cell.dataset.val = val; | |||
// 点击事件 | |||
(function(c, cIdx, cVal, idxI){ | |||
c.addEventListener('click', function() { | |||
if(c.classList.contains('revealed') || isScanned) return; | |||
// 2. 切换为刮开后的图 | |||
c.classList.add('revealed'); | |||
c.style.backgroundImage = "url('" + imgRevealed + "')"; | |||
c.innerText = cVal; // 显示文字 | |||
revealedCount++; | |||
// 剧情触发 | |||
if(cIdx === 5) { // 消失 | |||
setMascot(["别点了","我在看你"][Math.floor(Math.random()*2)], ""); | |||
c.innerText = ""; | |||
} | |||
if(cIdx === 7) { // 痛 | |||
c.innerText = ["痛!","别!"][Math.floor(Math.random()*2)]; | |||
c.style.color = "red"; | |||
setMascot("别挠我!", ">_<"); | |||
} | |||
if(cIdx === 4 && revealedCount === 15) { // 改字 | |||
setMascot("诶...?", "(;゚д゚)"); | |||
if(elGrid.children[29]) { | |||
elGrid.children[29].dataset.val = "中奖"; | |||
} | |||
} | |||
}); | |||
})(cell, idx, val, i); | |||
elGrid.appendChild(cell); | |||
} | |||
} | |||
elBtn.addEventListener('click', function() { | |||
if(isScanned) { | |||
// Next | |||
currentIdx++; | |||
if(currentIdx < TOTAL_CARDS) initCard(currentIdx); | |||
} else { | |||
// Scan | |||
if(revealedCount < 30 && currentIdx < 9) { | |||
if(!confirm("还没刮完,确定扫描吗?")) return; | |||
} | |||
var d = cards[currentIdx]; | |||
isScanned = true; | |||
elBtn.innerText = "扫描中..."; | |||
setTimeout(function(){ | |||
setMascot(d.text); | |||
if(d.type === 'b') { remain += 2; elCount.innerText = remain; } | |||
if(d.type === 'f') { doEnd(); return; } | |||
if(d.type === 's') { | |||
setTimeout(function(){ | |||
setMascot("严重错误。排出异物..."); | |||
elBtn.innerText = "取出未知票据"; | |||
elBtn.className = "action-btn danger"; | |||
}, 800); | |||
return; | |||
} | |||
remain--; | |||
elCount.innerText = remain; | |||
if(remain < 0) { | |||
setMascot("票据耗尽。"); | |||
elBtn.disabled = true; | |||
return; | |||
} | |||
elBtn.innerText = "再来一张"; | |||
elBtn.classList.add('next'); | |||
}, 500); | |||
} | |||
}); | |||
function doEnd() { | |||
document.body.classList.add('invert-filter'); | |||
setTimeout(function(){ | |||
var div = document.createElement('div'); | |||
div.className = 'crash-screen'; | |||
div.innerText = "FATAL ERROR"; | |||
document.body.appendChild(div); | |||
setTimeout(function(){ | |||
div.remove(); | |||
document.body.classList.remove('invert-filter'); | |||
root.style.display = 'none'; | |||
if(elFakeEntry) elFakeEntry.style.display = 'block'; | |||
window.scrollTo(0,0); | |||
alert("【系统提示】收到新短信。"); | |||
}, 3000); | |||
}, 1500); | |||
} | |||
initCard(0); | |||
})(); | |||
</script> | |||
</includeonly> | |||
2026年2月1日 (日) 14:34的版本
刮刮乐重构版
使用方式:修改第 222-224 行的图片URL,然后保存此页面 当前配置的图片:
- 底图(bg):

- 覆盖图(cover):

- 底层图(revealed):

