feat: 全站视觉焕新与悬浮玻璃 TabBar 迁移
This commit is contained in:
@@ -0,0 +1,529 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>TabBar 指示器调试器</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg-page: #faf7f2;
|
||||
--bg-card: #ffffff;
|
||||
--text: #2e2622;
|
||||
--text-2: #8a7e76;
|
||||
--border: #ede5dc;
|
||||
--accent: #d96c6a;
|
||||
--glass: rgba(255, 255, 255, 0.55);
|
||||
--glass-line: rgba(255, 255, 255, 0.55);
|
||||
--shadow: rgba(46, 38, 34, 0.18);
|
||||
--ind: rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
html.theme-dark {
|
||||
--bg-page: #191919;
|
||||
--bg-card: #23201d;
|
||||
--text: #f5efe8;
|
||||
--text-2: #b3a79c;
|
||||
--border: #37312c;
|
||||
--accent: #f09198;
|
||||
--glass: rgba(25, 25, 25, 0.55);
|
||||
--glass-line: rgba(255, 255, 255, 0.14);
|
||||
--shadow: rgba(0, 0, 0, 0.5);
|
||||
--ind: rgba(255, 255, 255, 0.16);
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
||||
background: var(--bg-page);
|
||||
color: var(--text);
|
||||
min-height: 100vh;
|
||||
transition: background .2s, color .2s;
|
||||
}
|
||||
.appbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
padding: 16px 24px;
|
||||
background: var(--bg-card);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.appbar h1 { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: 0; }
|
||||
.actions { display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
button {
|
||||
font: inherit;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-card);
|
||||
color: var(--text);
|
||||
border-radius: 999px;
|
||||
padding: 8px 16px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
|
||||
button:active { transform: scale(0.98); }
|
||||
.layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(280px, 380px) 1fr;
|
||||
gap: 24px;
|
||||
max-width: 1080px;
|
||||
margin: 0 auto;
|
||||
padding: 24px;
|
||||
}
|
||||
.controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
align-self: start;
|
||||
padding: 18px;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 16px;
|
||||
}
|
||||
.group-title { font-size: 13px; font-weight: 700; margin: 4px 0 8px; letter-spacing: 0; }
|
||||
.group { border-top: 1px solid var(--border); padding-top: 12px; }
|
||||
.field { margin-bottom: 12px; }
|
||||
.field label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
color: var(--text-2);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.field output { color: var(--accent); font-variant-numeric: tabular-nums; }
|
||||
input[type=range] { width: 100%; accent-color: var(--accent); }
|
||||
.output { margin-top: 4px; }
|
||||
.output .group-title { display: flex; justify-content: space-between; align-items: center; }
|
||||
.output textarea {
|
||||
width: 100%;
|
||||
min-height: 118px;
|
||||
resize: vertical;
|
||||
font: 11px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
background: var(--bg-page);
|
||||
color: var(--text);
|
||||
}
|
||||
.hint { font-size: 12px; color: var(--text-2); margin: 6px 0 0; line-height: 1.5; }
|
||||
.preview { display: flex; align-items: center; justify-content: center; }
|
||||
.phone {
|
||||
width: min(100%, 380px);
|
||||
aspect-ratio: 9 / 18.5;
|
||||
border-radius: 44px;
|
||||
background: var(--bg-card);
|
||||
box-shadow: 0 24px 60px var(--shadow);
|
||||
padding: 12px;
|
||||
}
|
||||
.screen {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 34px;
|
||||
overflow: hidden;
|
||||
background: var(--bg-page);
|
||||
}
|
||||
.feed {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 52px 24px 220px;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
touch-action: pan-y;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
.feed::-webkit-scrollbar { display: none; }
|
||||
.card {
|
||||
flex: 0 0 auto;
|
||||
padding: 10px;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 7px;
|
||||
}
|
||||
.img { height: 86px; border-radius: 10px; }
|
||||
.g1 { background: linear-gradient(145deg, #e08e8b, #7c8bd6); }
|
||||
.g2 { background: linear-gradient(205deg, #67c58e, #d9a35e); }
|
||||
.g3 { background: linear-gradient(120deg, #d96c6a, #e6c08a); }
|
||||
.g4 { background: linear-gradient(160deg, #8e97e8, #5faa8a); }
|
||||
.ln {
|
||||
height: 9px;
|
||||
border-radius: 6px;
|
||||
background: var(--text-2);
|
||||
opacity: 0.35;
|
||||
}
|
||||
.w90 { width: 90%; }
|
||||
.w85 { width: 85%; }
|
||||
.w80 { width: 80%; }
|
||||
.w75 { width: 75%; }
|
||||
.w70 { width: 70%; }
|
||||
.w65 { width: 65%; }
|
||||
.w60 { width: 60%; }
|
||||
.w55 { width: 55%; }
|
||||
.w50 { width: 50%; }
|
||||
.w45 { width: 45%; }
|
||||
.w40 { width: 40%; }
|
||||
.tiles { display: flex; gap: 8px; }
|
||||
.t { width: 44px; height: 44px; border-radius: 12px; flex: 0 0 auto; }
|
||||
.t1 { background: #e07a72; }
|
||||
.t2 { background: #6c7bdb; }
|
||||
.t3 { background: #4fa477; }
|
||||
.t4 { background: #d9a35e; }
|
||||
.t5 { background: #8e97e8; }
|
||||
.gradient {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.pill {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
border-radius: 28px;
|
||||
background: var(--glass);
|
||||
border: 1px solid var(--glass-line);
|
||||
backdrop-filter: blur(32px) saturate(1.2);
|
||||
-webkit-backdrop-filter: blur(32px) saturate(1.2);
|
||||
box-shadow: 0 12px 40px var(--shadow);
|
||||
}
|
||||
.tab {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
color: var(--text-2);
|
||||
font-size: 10px;
|
||||
}
|
||||
.tab.active { color: var(--accent); font-weight: 700; }
|
||||
.tab svg, .tab > span { position: relative; z-index: 1; }
|
||||
.tab svg { width: 22px; height: 22px; }
|
||||
.ind {
|
||||
position: absolute;
|
||||
background: var(--ind);
|
||||
}
|
||||
@media (max-width: 760px) {
|
||||
.layout { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="theme-light">
|
||||
<header class="appbar">
|
||||
<h1>TabBar 指示器调试器</h1>
|
||||
<div class="actions">
|
||||
<button id="themeBtn">切换到深色</button>
|
||||
<button id="copyCss" type="button">复制 SCSS</button>
|
||||
<button id="copyJson" class="primary" type="button">复制参数</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="layout">
|
||||
<section class="controls" aria-label="参数调节">
|
||||
<div class="group">
|
||||
<div class="group-title">选中指示器</div>
|
||||
<div class="field">
|
||||
<label>高度 <output id="vIndHeight">50</output> px</label>
|
||||
<input id="indHeight" type="range" min="8" max="64" step="1" value="50">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>左右贴边 <output id="vIndSide">-18</output> px</label>
|
||||
<input id="indSide" type="range" min="-20" max="30" step="1" value="-18">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>底部贴边 <output id="vIndBottom">3</output> px</label>
|
||||
<input id="indBottom" type="range" min="-20" max="20" step="1" value="3">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>圆角 <output id="vIndRadius">25</output> px</label>
|
||||
<input id="indRadius" type="range" min="0" max="40" step="1" value="25">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>宽度 <output id="vIndWidth">60</output> px</label>
|
||||
<input id="indWidth" type="range" min="0" max="160" step="1" value="60">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>不透明度 <output id="vIndOpacity">14</output> %</label>
|
||||
<input id="indOpacity" type="range" min="0" max="100" step="1" value="14">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>阴影模糊 <output id="vIndBlur">3</output> px</label>
|
||||
<input id="indBlur" type="range" min="0" max="30" step="1" value="3">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>底色 <output id="vIndColor">#000000</output></label>
|
||||
<input id="indColor" type="color" value="#000000">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="output">
|
||||
<div class="group">
|
||||
<div class="group-title">导出的参数</div>
|
||||
<textarea id="jsonOut" readonly aria-label="导出的参数"></textarea>
|
||||
</div>
|
||||
<p class="hint">点「复制参数」把 JSON 发给我;点「复制 SCSS」得到可直接落地的样式代码。</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="preview" aria-label="预览">
|
||||
<div class="phone">
|
||||
<div class="screen">
|
||||
<div class="feed">
|
||||
<div class="card"><div class="img g1"></div><div class="ln w80"></div><div class="ln w55"></div></div>
|
||||
<div class="card"><div class="img g2"></div><div class="ln w70"></div><div class="ln w45"></div></div>
|
||||
<div class="card">
|
||||
<div class="ln w90"></div><div class="ln w60"></div><div class="ln w75"></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="tiles"><i class="t t1"></i><i class="t t2"></i><i class="t t3"></i></div>
|
||||
<div class="ln w65"></div>
|
||||
</div>
|
||||
<div class="card"><div class="img g3"></div><div class="ln w80"></div><div class="ln w50"></div></div>
|
||||
<div class="card">
|
||||
<div class="ln w85"></div><div class="ln w60"></div><div class="ln w40"></div>
|
||||
</div>
|
||||
<div class="card"><div class="img g4"></div><div class="ln w75"></div></div>
|
||||
<div class="card">
|
||||
<div class="tiles"><i class="t t4"></i><i class="t t5"></i></div>
|
||||
<div class="ln w70"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gradient" id="gradient"></div>
|
||||
<div class="pill" id="pill"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
const TABS = [
|
||||
['首页', '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m3 10 9-7 9 7"/><path d="M5 9v11h14V9"/><path d="M9 20v-6h6v6"/></svg>'],
|
||||
['商品', '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 8 12 3 3 8v8l9 5 9-5Z"/><path d="M3.5 7.5 12 12l8.5-4.5"/><path d="M12 22V12"/></svg>'],
|
||||
['设计', '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22a10 10 0 1 1 10-10c0 2.21-1.79 4-4 4h-2a2 2 0 0 0-2 2c0 .53.2 1 .54 1.36C14.78 21.4 13.5 22 12 22Z"/><circle cx="7.5" cy="10.5" r="1"/><circle cx="12" cy="7.5" r="1"/><circle cx="16.5" cy="10.5" r="1"/></svg>'],
|
||||
['订单', '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z"/><path d="M3 6h18"/><path d="M16 10a4 4 0 0 1-8 0"/></svg>'],
|
||||
['我的', '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 21s1-5 8-5 8 5 8 5"/></svg>']
|
||||
]
|
||||
|
||||
const ids = {
|
||||
indHeight: document.getElementById('indHeight'),
|
||||
indSide: document.getElementById('indSide'),
|
||||
indBottom: document.getElementById('indBottom'),
|
||||
indRadius: document.getElementById('indRadius'),
|
||||
indWidth: document.getElementById('indWidth'),
|
||||
indOpacity: document.getElementById('indOpacity'),
|
||||
indBlur: document.getElementById('indBlur'),
|
||||
indColor: document.getElementById('indColor'),
|
||||
gradient: document.getElementById('gradient'),
|
||||
pill: document.getElementById('pill'),
|
||||
indicator: document.getElementById('indicator')
|
||||
}
|
||||
|
||||
const val = (el) => Number(el.value)
|
||||
function hexToRgb(hex) {
|
||||
const h = hex.replace('#', '')
|
||||
return {
|
||||
r: parseInt(h.substring(0, 2), 16),
|
||||
g: parseInt(h.substring(2, 4), 16),
|
||||
b: parseInt(h.substring(4, 6), 16)
|
||||
}
|
||||
}
|
||||
|
||||
function themeColors() {
|
||||
return document.body.classList.contains('theme-dark')
|
||||
? { r: 25, g: 25, b: 25, label: 'dark' }
|
||||
: { r: 250, g: 247, b: 242, label: 'light' }
|
||||
}
|
||||
|
||||
function buildPill() {
|
||||
ids.pill.innerHTML = TABS.map((t, i) =>
|
||||
'<div class="tab' + (i === 0 ? ' active' : '') + '">' +
|
||||
(i === 0 ? '<div class="ind" id="indicator"></div>' : '') +
|
||||
t[1] + '<span>' + t[0] + '</span></div>'
|
||||
).join('')
|
||||
ids.indicator = document.getElementById('indicator')
|
||||
}
|
||||
|
||||
function currentParams() {
|
||||
const c = themeColors()
|
||||
return {
|
||||
theme: c.label,
|
||||
gradient: {
|
||||
height: 80,
|
||||
bottomOpacity: 50,
|
||||
midStop: 50,
|
||||
midOpacity: 10,
|
||||
endStop: 86
|
||||
},
|
||||
tabBar: {
|
||||
bottom: 18,
|
||||
sideMargin: 18,
|
||||
height: 58,
|
||||
radius: 32
|
||||
},
|
||||
indicator: {
|
||||
width: val(ids.indWidth),
|
||||
height: val(ids.indHeight),
|
||||
sideInset: val(ids.indSide),
|
||||
bottomInset: val(ids.indBottom),
|
||||
radius: val(ids.indRadius),
|
||||
opacity: val(ids.indOpacity),
|
||||
blur: val(ids.indBlur),
|
||||
color: ids.indColor.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
const c = themeColors()
|
||||
const p = currentParams()
|
||||
const g = p.gradient
|
||||
const tb = p.tabBar
|
||||
const ind = p.indicator
|
||||
const mid = Math.max(g.midStop, 1)
|
||||
const end = Math.max(g.endStop, mid + 1)
|
||||
const arr = [
|
||||
'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + (g.bottomOpacity / 100).toFixed(3) + ') 0%',
|
||||
'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + (g.midOpacity / 100).toFixed(3) + ') ' + mid + '%',
|
||||
'rgba(' + c.r + ',' + c.g + ',' + c.b + ',0) ' + end + '%'
|
||||
]
|
||||
ids.gradient.style.height = g.height + 'px'
|
||||
ids.gradient.style.background = 'linear-gradient(to top, ' + arr.join(', ') + ')'
|
||||
|
||||
ids.pill.style.bottom = tb.bottom + 'px'
|
||||
ids.pill.style.left = tb.sideMargin + 'px'
|
||||
ids.pill.style.right = tb.sideMargin + 'px'
|
||||
ids.pill.style.height = tb.height + 'px'
|
||||
ids.pill.style.borderRadius = tb.radius + 'px'
|
||||
|
||||
const rgb = hexToRgb(ind.color)
|
||||
const alpha = (ind.opacity / 100).toFixed(3)
|
||||
ids.indicator.style.bottom = ind.bottomInset + 'px'
|
||||
ids.indicator.style.height = ind.height + 'px'
|
||||
ids.indicator.style.borderRadius = ind.radius + 'px'
|
||||
ids.indicator.style.background = 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + alpha + ')'
|
||||
ids.indicator.style.boxShadow = ind.blur > 0
|
||||
? '0 0 ' + ind.blur + 'px rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + (alpha / 2) + ')'
|
||||
: 'none'
|
||||
if (ind.width > 0) {
|
||||
ids.indicator.style.width = ind.width + 'px'
|
||||
ids.indicator.style.left = '50%'
|
||||
ids.indicator.style.right = 'auto'
|
||||
ids.indicator.style.transform = 'translateX(-50%)'
|
||||
} else {
|
||||
ids.indicator.style.width = 'auto'
|
||||
ids.indicator.style.left = ind.sideInset + 'px'
|
||||
ids.indicator.style.right = ind.sideInset + 'px'
|
||||
ids.indicator.style.transform = 'none'
|
||||
}
|
||||
|
||||
document.getElementById('vIndHeight').textContent = ind.height
|
||||
document.getElementById('vIndSide').textContent = ind.sideInset
|
||||
document.getElementById('vIndBottom').textContent = ind.bottomInset
|
||||
document.getElementById('vIndRadius').textContent = ind.radius
|
||||
document.getElementById('vIndWidth').textContent = ind.width
|
||||
document.getElementById('vIndOpacity').textContent = ind.opacity
|
||||
document.getElementById('vIndBlur').textContent = ind.blur
|
||||
document.getElementById('vIndColor').textContent = ind.color
|
||||
|
||||
document.getElementById('jsonOut').value = JSON.stringify(p, null, 2)
|
||||
}
|
||||
|
||||
function scssSnippet() {
|
||||
const c = themeColors()
|
||||
const p = currentParams()
|
||||
const col = c.label === 'dark' ? '25, 25, 25' : '250, 247, 242'
|
||||
const rpx = (v) => Math.round(v * 2)
|
||||
const ind = p.indicator
|
||||
const irgb = hexToRgb(ind.color)
|
||||
const indLines = []
|
||||
if (ind.width > 0) {
|
||||
indLines.push(' width: ' + rpx(ind.width) + 'rpx;')
|
||||
indLines.push(' left: 50%;')
|
||||
indLines.push(' transform: translateX(-50%);')
|
||||
} else {
|
||||
indLines.push(' left: ' + rpx(ind.sideInset) + 'rpx;')
|
||||
indLines.push(' right: ' + rpx(ind.sideInset) + 'rpx;')
|
||||
}
|
||||
indLines.push(' bottom: ' + rpx(ind.bottomInset) + 'rpx;')
|
||||
indLines.push(' height: ' + rpx(ind.height) + 'rpx;')
|
||||
indLines.push(' border-radius: ' + rpx(ind.radius) + 'rpx;')
|
||||
indLines.push(' background: rgba(' + irgb.r + ', ' + irgb.g + ', ' + irgb.b + ', ' + (ind.opacity / 100).toFixed(2) + ');')
|
||||
if (ind.blur > 0) {
|
||||
indLines.push(' box-shadow: 0 0 ' + rpx(ind.blur) + 'rpx rgba(' + irgb.r + ', ' + irgb.g + ', ' + irgb.b + ', ' + ((ind.opacity / 100) / 2).toFixed(2) + ');')
|
||||
}
|
||||
return [
|
||||
'/* ' + c.label + ' theme */',
|
||||
'.tab-bar-root.' + c.label + ' .tab-bar-gradient {',
|
||||
' height: ' + rpx(p.gradient.height) + 'rpx;',
|
||||
' background: linear-gradient(to top,',
|
||||
' rgba(' + col + ', ' + (p.gradient.bottomOpacity / 100).toFixed(2) + ') 0%,',
|
||||
' rgba(' + col + ', ' + (p.gradient.midOpacity / 100).toFixed(2) + ') ' + p.gradient.midStop + '%,',
|
||||
' rgba(' + col + ', 0) ' + p.gradient.endStop + '%',
|
||||
' );',
|
||||
'}',
|
||||
'.custom-tab-bar {',
|
||||
' bottom: ' + rpx(p.tabBar.bottom) + 'rpx;',
|
||||
' left: ' + rpx(p.tabBar.sideMargin) + 'rpx;',
|
||||
' right: ' + rpx(p.tabBar.sideMargin) + 'rpx;',
|
||||
' height: ' + rpx(p.tabBar.height) + 'rpx;',
|
||||
' border-radius: ' + rpx(p.tabBar.radius) + 'rpx;',
|
||||
'}',
|
||||
'.tab-indicator {',
|
||||
indLines.join('\n'),
|
||||
'}'
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
function copy(text) {
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
return navigator.clipboard.writeText(text)
|
||||
}
|
||||
const ta = document.createElement('textarea')
|
||||
ta.value = text
|
||||
document.body.appendChild(ta)
|
||||
ta.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(ta)
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
document.getElementById('themeBtn').addEventListener('click', () => {
|
||||
const dark = document.body.classList.toggle('theme-dark')
|
||||
document.getElementById('themeBtn').textContent = dark ? '切换到浅色' : '切换到深色'
|
||||
render()
|
||||
})
|
||||
|
||||
document.getElementById('copyJson').addEventListener('click', () => {
|
||||
copy(JSON.stringify(currentParams(), null, 2)).then(() => { alert('参数已复制') })
|
||||
})
|
||||
document.getElementById('copyCss').addEventListener('click', () => {
|
||||
copy(scssSnippet()).then(() => { alert('SCSS 已复制') })
|
||||
})
|
||||
|
||||
Object.keys(ids).forEach((k) => {
|
||||
if (k === 'gradient' || k === 'pill' || k === 'indicator') return
|
||||
ids[k].addEventListener('input', render)
|
||||
})
|
||||
|
||||
buildPill()
|
||||
render()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user