Created
April 30, 2026 11:29
-
-
Save carddass2018-svg/815d31a74aa4adda6ecdcb97c1b443b0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="zh-Hant"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>龍珠閃卡 - 終極穩定版</title> | |
| <style> | |
| body { background: #000; margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center; overflow: hidden; font-family: sans-serif; } | |
| /* 啟動按鈕 */ | |
| #auth-overlay { position: fixed; inset: 0; background: #000; z-index: 9999; display: flex; flex-direction: column; align-items: center; justify-content: center; } | |
| #auth-btn { background: #f1c40f; border: none; padding: 20px 40px; border-radius: 12px; font-size: 20px; font-weight: bold; } | |
| /* 設定按鈕 */ | |
| #set-btn { position: fixed; top: 20px; left: 20px; z-index: 1000; background: #333; color: #fff; border: 1px solid #555; padding: 10px 15px; border-radius: 8px; cursor: pointer; display: none; } | |
| /* 上傳面板 */ | |
| .panel { position: fixed; top: 0; left: 0; width: 100%; background: #1a1a1a; padding: 25px; border-bottom: 2px solid #444; z-index: 999; box-sizing: border-box; transform: translateY(-110%); transition: 0.3s; } | |
| .panel.active { transform: translateY(0); } | |
| .row { margin-bottom: 12px; text-align: left; } | |
| label { display: block; font-size: 12px; color: #888; margin-bottom: 5px; } | |
| input[type="file"] { width: 100%; color: #0f0; font-size: 14px; } | |
| /* 展示舞台 */ | |
| .stage { perspective: 1200px; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; } | |
| #card { width: 85vw; max-width: 320px; aspect-ratio: 1 / 1.4; position: relative; border-radius: 18px; overflow: hidden; background: #111; box-shadow: 0 0 50px #000; } | |
| .layer { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; } | |
| #c-base { width: 100%; height: 100%; object-fit: cover; z-index: 1; } | |
| /* 核心修復:iPhone 強制遮罩 */ | |
| #foil-wrap { | |
| z-index: 2; | |
| mix-blend-mode: color-dodge; | |
| /* 使用暴力對比,將所有非純白位變黑,解決漏閃 */ | |
| filter: contrast(1200%) brightness(100%); | |
| -webkit-mask-size: 100% 100%; | |
| mask-size: 100% 100%; | |
| -webkit-mask-repeat: no-repeat; | |
| mask-repeat: no-repeat; | |
| display: block; | |
| } | |
| #c-foil { | |
| background-size: cover; | |
| background-position: center; | |
| opacity: 0.15; | |
| background-image: repeating-linear-gradient(45deg, #fff1 0, #fff1 1px, transparent 1px, transparent 10px); | |
| } | |
| #c-shine { | |
| z-index: 3; | |
| background: linear-gradient(110deg, transparent 40%, rgba(255,255,255,0.4) 50%, transparent 60%); | |
| background-size: 250% 250%; | |
| mix-blend-mode: overlay; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="auth-overlay"><button id="auth-btn" onclick="init()">啟動 iPhone 強制遮罩版</button></div> | |
| <button id="set-btn" onclick="document.getElementById('p').classList.toggle('active')">⚙️ 設定</button> | |
| <div class="panel" id="p"> | |
| <div class="row"><label>1. 原圖 (Card Art)</label><input type="file" accept="image/*" onchange="up(event,'b')"></div> | |
| <div class="row"><label>2. 遮罩 (黑色不閃)</label><input type="file" accept="image/*" onchange="up(event,'m')"></div> | |
| <div class="row"><label>3. 閃紋 (Foil Texture)</label><input type="file" accept="image/*" onchange="up(event,'f')"></div> | |
| <button onclick="document.getElementById('p').classList.remove('active')" style="width:100%; padding:12px; background:#444; color:#fff; border:none; border-radius:8px;">完成設定</button> | |
| </div> | |
| <div class="stage"> | |
| <div id="card"> | |
| <img id="c-base" src="https://asobi-center.com"> | |
| <div id="foil-wrap" class="layer"> | |
| <div id="c-foil" class="layer"></div> | |
| </div> | |
| <div id="c-shine" class="layer"></div> | |
| </div> | |
| </div> | |
| <!-- 隱形 Canvas --> | |
| <canvas id="cvs" style="display:none;"></canvas> | |
| <script> | |
| const foil = document.getElementById('c-foil'), | |
| wrap = document.getElementById('foil-wrap'), | |
| base = document.getElementById('c-base'), | |
| shine = document.getElementById('c-shine'), | |
| cvs = document.getElementById('cvs'), | |
| ctx = cvs.getContext('2d'); | |
| function up(e, type) { | |
| const file = e.target.files[0]; | |
| if (!file) return; | |
| const reader = new FileReader(); | |
| reader.onload = (ev) => { | |
| const img = new Image(); | |
| img.onload = () => { | |
| // 核心修復:透過 Canvas 重新繪製圖片,轉化為 iPhone 可識別的穩定數據 | |
| cvs.width = img.width; | |
| cvs.height = img.height; | |
| ctx.clearRect(0, 0, cvs.width, cvs.height); | |
| ctx.drawImage(img, 0, 0); | |
| const dataUrl = cvs.toDataURL('image/png'); | |
| if(type==='b') base.src = dataUrl; | |
| if(type==='f') foil.style.backgroundImage = `url('${dataUrl}')`; | |
| if(type==='m') { | |
| // iPhone Safari 必須強制重新注入 Webkit 屬性 | |
| wrap.style.webkitMaskImage = `url('${dataUrl}')`; | |
| wrap.style.maskImage = `url('${dataUrl}')`; | |
| // 強制重繪 | |
| wrap.style.display = 'none'; | |
| wrap.offsetHeight; | |
| wrap.style.display = 'block'; | |
| } | |
| }; | |
| img.src = ev.target.result; | |
| }; | |
| reader.readAsDataURL(file); | |
| } | |
| function init() { | |
| if (typeof DeviceOrientationEvent!=='undefined' && typeof DeviceOrientationEvent.requestPermission==='function') { | |
| DeviceOrientationEvent.requestPermission().then(res => { if(res==='granted') start(); }); | |
| } else { start(); } | |
| } | |
| function start() { | |
| document.getElementById('auth-overlay').style.display='none'; | |
| document.getElementById('set-btn').style.display='block'; | |
| window.addEventListener('deviceorientation', e => { | |
| let lr = e.gamma || 0, fb = (e.beta || 45) - 45; | |
| foil.style.filter = `hue-rotate(${lr*10}deg) brightness(${0.85 + Math.abs(lr)/60}) contrast(1.5)`; | |
| foil.style.opacity = 0.12 + Math.abs(lr)/150; | |
| shine.style.backgroundPosition = `${50+lr*2}% ${50+fb*2}%`; | |
| }); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment