Skip to content

Instantly share code, notes, and snippets.

@carddass2018-svg
Created April 30, 2026 11:29
Show Gist options
  • Select an option

  • Save carddass2018-svg/815d31a74aa4adda6ecdcb97c1b443b0 to your computer and use it in GitHub Desktop.

Select an option

Save carddass2018-svg/815d31a74aa4adda6ecdcb97c1b443b0 to your computer and use it in GitHub Desktop.
<!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