Files
xianyan/design-preview/editor-bottom-toolbar.html
Developer b5157c19f4 feat: 新增壁纸图库组件和编辑器功能优化
- 新增壁纸图库相关组件(WallpaperGalleryView/WallpaperSearchBar等)
- 优化编辑器主题服务和系统UI管理
- 新增虚线边框和拖拽描边风格支持
- 完善今日诗词服务和阅读报告功能
- 修复多个UI问题和空指针异常
- 更新依赖库版本和SVG资源
- 优化交互动画和状态管理
- 补充文档和API测试脚本
2026-05-05 05:03:33 +08:00

494 lines
13 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pro编辑器 — 底部工具栏 iOS 26</title>
<style>
:root {
--primary: #6C63FF;
--primary-light: #8B83FF;
--accent: #4ECDC4;
--secondary: #FF6B6B;
--glass-bg: rgba(255, 255, 255, 0.06);
--glass-bg-hover: rgba(255, 255, 255, 0.12);
--glass-bg-active: rgba(108, 99, 255, 0.2);
--glass-border: rgba(255, 255, 255, 0.1);
--glass-border-strong: rgba(255, 255, 255, 0.2);
--text-primary: rgba(255, 255, 255, 0.95);
--text-secondary: rgba(255, 255, 255, 0.5);
--text-tertiary: rgba(255, 255, 255, 0.3);
--radius-md: 12px;
--radius-lg: 16px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', system-ui, sans-serif;
background: #000;
color: var(--text-primary);
min-height: 100vh;
overflow: hidden;
}
.canvas-bg {
position: fixed;
inset: 0;
background: linear-gradient(135deg, #0a0a0f 0%, #0f0f1a 100%);
}
.canvas-image {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
}
.canvas-image .placeholder {
width: 55vw;
height: 55vh;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
opacity: 0.5;
box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.bottom-toolbar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 100;
animation: slideUp 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes slideUp {
from { transform: translateY(100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.toolbar-main {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 12px;
background: rgba(28, 28, 30, 0.85);
backdrop-filter: blur(50px) saturate(1.8);
-webkit-backdrop-filter: blur(50px) saturate(1.8);
border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.toolbar-section {
display: flex;
align-items: center;
gap: 2px;
}
.tb-btn {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2px;
width: 52px;
height: 52px;
border: none;
background: transparent;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border-radius: var(--radius-md);
}
.tb-btn .icon { font-size: 20px; transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1); }
.tb-btn .label { font-size: 9px; font-weight: 500; line-height: 1; }
.tb-btn:hover { color: var(--text-primary); background: var(--glass-bg-hover); }
.tb-btn:active .icon { transform: scale(0.85); }
.tb-btn.active {
color: var(--primary-light);
}
.tb-btn.active::after {
content: '';
position: absolute;
bottom: 4px;
width: 4px;
height: 4px;
border-radius: 50%;
background: var(--primary-light);
}
.tb-divider {
width: 1px;
height: 28px;
background: rgba(255, 255, 255, 0.06);
margin: 0 2px;
}
.center-btn {
width: 56px;
height: 56px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, var(--primary), var(--primary-light));
border: none;
border-radius: 50%;
cursor: pointer;
font-size: 24px;
color: #fff;
margin-top: -16px;
box-shadow: 0 4px 20px rgba(108,99,255,0.35);
transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.center-btn:hover {
transform: scale(1.08);
box-shadow: 0 6px 28px rgba(108,99,255,0.5);
}
.center-btn:active { transform: scale(0.92); }
.home-indicator {
width: 134px;
height: 5px;
background: rgba(255, 255, 255, 0.15);
border-radius: 3px;
margin: 6px auto 8px;
}
.status-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px 16px;
background: rgba(28, 28, 30, 0.85);
backdrop-filter: blur(50px) saturate(1.8);
-webkit-backdrop-filter: blur(50px) saturate(1.8);
border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.status-left {
display: flex;
align-items: center;
gap: 0;
font-size: 11px;
color: var(--text-tertiary);
flex: 1;
min-width: 0;
}
.status-left .emoji { font-size: 11px; }
.status-center {
display: flex;
align-items: center;
gap: 0;
flex-shrink: 0;
}
.status-right {
display: flex;
align-items: center;
gap: 4px;
flex-shrink: 0;
}
.status-sep {
width: 1px;
height: 10px;
background: rgba(255, 255, 255, 0.12);
margin: 0 8px;
flex-shrink: 0;
}
.s-layer-name {
font-size: 11px;
font-weight: 600;
color: rgba(255, 255, 255, 0.8);
}
.s-layer-xy {
font-size: 10px;
font-weight: 500;
color: rgba(64, 196, 255, 0.5);
font-variant-numeric: tabular-nums;
margin-left: 6px;
}
.s-version {
font-size: 11px;
font-weight: 500;
color: rgba(255, 255, 255, 0.3);
letter-spacing: 0.8px;
}
.s-debug-icon {
width: 14px;
height: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: rgba(255, 255, 255, 0.3);
font-size: 13px;
margin-left: 6px;
transition: color 0.2s;
}
.s-debug-icon:hover { color: rgba(255,255,255,0.6); }
.s-debug-info {
display: flex;
align-items: center;
gap: 6px;
}
.s-fps {
font-size: 10px;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.s-fps.good { color: #4ECDC4; }
.s-fps.warn { color: #F59E0B; }
.s-fps.bad { color: #EF4444; }
.s-dpr {
font-size: 10px;
font-weight: 500;
color: rgba(64, 196, 255, 0.5);
font-variant-numeric: tabular-nums;
}
.s-screen {
font-size: 10px;
font-weight: 500;
color: rgba(255, 255, 255, 0.6);
font-variant-numeric: tabular-nums;
}
.debug-panel {
display: none;
}
.debug-panel.show {
display: flex;
}
.mini-toggle {
width: 32px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: 1px solid transparent;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
color: var(--text-tertiary);
transition: all 0.2s;
}
.mini-toggle:hover { background: var(--glass-bg-hover); color: var(--text-secondary); }
.mini-toggle.active { color: var(--primary-light); background: rgba(108,99,255,0.1); border-color: rgba(108,99,255,0.2); }
.back-link {
position: fixed;
top: 12px;
left: 16px;
z-index: 300;
display: flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
background: rgba(20, 20, 22, 0.7);
backdrop-filter: blur(20px);
border: 1px solid var(--glass-border);
border-radius: 999px;
color: var(--text-secondary);
font-size: 13px;
text-decoration: none;
transition: all 0.2s;
}
.back-link:hover { color: var(--text-primary); }
.annotation {
position: fixed;
top: 24px;
left: 50%;
transform: translateX(-50%);
padding: 10px 20px;
background: rgba(20, 20, 22, 0.75);
backdrop-filter: blur(20px);
border: 1px solid var(--glass-border);
border-radius: 999px;
font-size: 13px;
color: var(--text-secondary);
z-index: 200;
display: flex;
align-items: center;
gap: 8px;
}
.annotation .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--primary); animation: pulse 2s infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
.info-panel {
position: fixed;
top: 24px;
right: 24px;
padding: 16px 20px;
background: rgba(20, 20, 22, 0.7);
backdrop-filter: blur(20px);
border: 1px solid var(--glass-border);
border-radius: 16px;
z-index: 200;
max-width: 260px;
}
.info-panel h3 { font-size: 14px; font-weight: 600; margin-bottom: 8px; }
.info-panel .feature { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 12px; color: var(--text-secondary); }
.info-panel .feature span:first-child { font-size: 14px; }
</style>
</head>
<body>
<div class="canvas-bg"></div>
<div class="canvas-image">
<div class="placeholder">🖼️</div>
</div>
<a class="back-link" href="index.html">← 返回</a>
<div class="annotation">
<span class="dot"></span>
iOS 26 底部工具栏 — 点击按钮查看交互
</div>
<div class="info-panel">
<h3>🛠 底部工具栏</h3>
<div class="feature"><span>📝</span> 文字编辑</div>
<div class="feature"><span>🖼️</span> 壁纸背景</div>
<div class="feature"><span>🎭</span> 贴纸</div>
<div class="feature"><span>🌈</span> 渐变</div>
<div class="feature"><span>💧</span> 水印</div>
<div class="feature"><span>🧰</span> 工具箱(中心按钮)</div>
<div class="feature"><span>🎨</span> 主题色</div>
<div class="feature"><span></span> Shader</div>
<div class="feature"><span>📐</span> 画布</div>
<div style="margin-top:10px;padding-top:8px;border-top:1px solid rgba(255,255,255,0.08)">
<div style="font-size:11px;font-weight:600;margin-bottom:4px;color:rgba(255,255,255,0.7)">📊 状态栏</div>
<div class="feature"><span>🖼️</span> 图片格式·尺寸</div>
<div class="feature"><span>🏷️</span> 图层名 + XY坐标</div>
<div class="feature"><span>📦</span> xycard 1.0</div>
<div class="feature"><span></span> 调试FPS / DPR / 屏幕</div>
<div class="feature"><span>📍⏳</span> 图层轨/历史条开关</div>
</div>
</div>
<div class="bottom-toolbar">
<div class="toolbar-main">
<div class="toolbar-section">
<button class="tb-btn active" onclick="toggleBtn(this)">
<span class="icon">📝</span>
<span class="label">文字</span>
</button>
<button class="tb-btn" onclick="toggleBtn(this)">
<span class="icon">🖼️</span>
<span class="label">壁纸</span>
</button>
<button class="tb-btn" onclick="toggleBtn(this)">
<span class="icon">🎭</span>
<span class="label">贴纸</span>
</button>
<button class="tb-btn" onclick="toggleBtn(this)">
<span class="icon">🌈</span>
<span class="label">渐变</span>
</button>
</div>
<button class="center-btn" title="工具箱">🧰</button>
<div class="toolbar-section">
<button class="tb-btn" onclick="toggleBtn(this)">
<span class="icon">💧</span>
<span class="label">水印</span>
</button>
<button class="tb-btn" onclick="toggleBtn(this)">
<span class="icon">🎨</span>
<span class="label">主题</span>
</button>
<button class="tb-btn" onclick="toggleBtn(this)">
<span class="icon"></span>
<span class="label">Shader</span>
</button>
<button class="tb-btn" onclick="toggleBtn(this)">
<span class="icon">📐</span>
<span class="label">画布</span>
</button>
</div>
</div>
<div class="status-row">
<div class="status-left">
<span class="emoji">🖼️</span>&nbsp;PNG · 1080×1920
</div>
<div class="status-center">
<span class="s-layer-name">一言文字</span>
<span class="s-layer-xy">120,340</span>
<div class="status-sep"></div>
<span class="s-version">xycard 1.0</span>
<span class="s-debug-icon" id="debugToggle" onclick="toggleDebug()"></span>
<div class="debug-panel" id="debugPanel">
<div class="status-sep"></div>
<div class="s-debug-info">
<span class="s-fps good">60 FPS</span>
<span class="s-dpr">@3.0x</span>
<span class="s-screen">390×844</span>
</div>
</div>
</div>
<div class="status-right">
<button class="mini-toggle active" id="toggleLayer" onclick="toggleMini(this)" title="图层轨">📍</button>
<button class="mini-toggle active" id="toggleHistory" onclick="toggleMini(this)" title="历史条"></button>
</div>
</div>
<div class="home-indicator"></div>
</div>
<script>
function toggleBtn(btn) {
document.querySelectorAll('.tb-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
}
function toggleMini(btn) {
btn.classList.toggle('active');
}
function toggleDebug() {
const panel = document.getElementById('debugPanel');
const icon = document.getElementById('debugToggle');
panel.classList.toggle('show');
icon.textContent = panel.classList.contains('show') ? '' : '';
icon.style.opacity = panel.classList.contains('show') ? '1' : '0.3';
}
</script>
</body>
</html>