Files
drawlogo/_gen_tabbar20.js

225 lines
17 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
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.
// 临时生成脚本:20 款底部导航图标方案(发房=新增加号)(勿提交)
const fs = require('fs');
const path = 'js/data/sources/';
global.window = {};
const RED = '#FF6700';
const GRAY = '#999999';
function load(sid) { eval(fs.readFileSync(path + sid + '.js', 'utf8')); return window['HGB_Source_' + sid]; }
function findIcon(data, ref) {
const namePart = ref.includes(':') ? ref.split(':')[1] : ref;
return (data.icons || []).find(i => i.id === ref || i.name === namePart) || null;
}
// style: native(path用currentColor) / fill(根fill) / stroke(根stroke) / color(自带颜色)
const SOURCES = {
fluent: { style: 'native' },
'material-symbols': { style: 'native' },
remix: { style: 'fill' },
lucide: { style: 'stroke' },
ionicons: { style: 'fill' },
mingcute: { style: 'native' },
tabler: { style: 'stroke' },
phosphor: { style: 'native' },
carbon: { style: 'native' },
boxicons: { style: 'fill' },
heroicons: { style: 'fill' },
feather: { style: 'stroke' },
twemoji: { style: 'color' },
emojione: { style: 'color' },
'fluent-emoji': { style: 'color' },
'fluent-color': { style: 'color' },
'flat-color-icons': { style: 'color' },
pixelarticons: { style: 'native' },
'icon-park': { style: 'color' },
openmoji: { style: 'color' }
};
function renderSVG(ic, style, color) {
let attrs = 'xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"';
if (style === 'stroke') attrs += ' fill="none" stroke="' + color + '" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"';
else if (style === 'fill') attrs += ' fill="' + color + '"';
else if (style === 'native') attrs += ' style="color:' + color + '"';
return '<svg ' + attrs + '>' + ic.svg + '</svg>';
}
const M = (label, n, a) => ({ label, n, a });
const SOLUTIONS = [
{ key:'01', title:'Fluent 微软圆润', desc:'微软现代风格,描边/实心双态', source:'fluent', pub:'fluent:add-circle-24-filled',
items:[M('首页','fluent:apps-24-regular','fluent:apps-24-filled'),M('租房','fluent:building-24-regular','fluent:building-24-filled'),M('消息','fluent:chat-24-regular','fluent:chat-24-filled'),M('我的','fluent:person-24-regular','fluent:person-24-filled')] },
{ key:'02', title:'Material Symbols 谷歌', desc:'Material Design,圆角厚重实心', source:'material-symbols', pub:'material-symbols:add-circle-rounded',
items:[M('首页','material-symbols:apps-outline-rounded','material-symbols:apps-rounded'),M('租房','material-symbols:apartment-outline-rounded','material-symbols:apartment-rounded'),M('消息','material-symbols:chat-outline-rounded','material-symbols:chat-rounded'),M('我的','material-symbols:person-outline-rounded','material-symbols:person-rounded')] },
{ key:'03', title:'Remix 锐克思', desc:'国内产品最常用,线条/实心双态', source:'remix', pub:'remix:add-circle-fill',
items:[M('首页','remix:dashboard-line','remix:dashboard-fill'),M('租房','remix:building-4-line','remix:building-4-fill'),M('消息','remix:message-3-line','remix:message-3-fill'),M('我的','remix:user-3-line','remix:user-3-fill')] },
{ key:'04', title:'Lucide 轻细线条', desc:'精致细线条,极简优雅', source:'lucide', pub:'lucide:circle-plus',
items:[M('首页','lucide:layout-dashboard','lucide:layout-dashboard'),M('租房','lucide:building-2','lucide:building-2'),M('消息','lucide:message-square','lucide:message-square'),M('我的','lucide:user','lucide:user')] },
{ key:'05', title:'Ionicons iOS 经典', desc:'iOS 同源,实心/描边双态', source:'ionicons', pub:'ionicons:add-circle',
items:[M('首页','ionicons:grid-outline','ionicons:grid'),M('租房','ionicons:business-outline','ionicons:business'),M('消息','ionicons:chatbox-ellipses-outline','ionicons:chatbox-ellipses'),M('我的','ionicons:person-outline','ionicons:person')] },
{ key:'06', title:'Mingcute 圆润可爱', desc:'圆头线条/实心双态,年轻活泼', source:'mingcute', pub:'mingcute:add-circle-fill',
items:[M('首页','mingcute:layout-grid-line','mingcute:layout-grid-fill'),M('租房','mingcute:building-1-line','mingcute:building-1-fill'),M('消息','mingcute:chat-1-line','mingcute:chat-1-fill'),M('我的','mingcute:user-3-line','mingcute:user-3-fill')] },
{ key:'07', title:'Tabler 现代线条', desc:'通用线条图标,简洁清晰', source:'tabler', pub:'tabler:circle-plus',
items:[M('首页','tabler:layout-dashboard','tabler:layout-dashboard'),M('租房','tabler:building-community','tabler:building-community'),M('消息','tabler:message-2','tabler:message-2'),M('我的','tabler:user','tabler:user')] },
{ key:'08', title:'Phosphor 多权重', desc:'可调粗细,四宫格/楼宇双态', source:'phosphor', pub:'phosphor:plus-circle-fill',
items:[M('首页','phosphor:squares-four','phosphor:squares-four-fill'),M('租房','phosphor:buildings','phosphor:buildings-fill'),M('消息','phosphor:chat','phosphor:chat-fill'),M('我的','phosphor:user','phosphor:user-fill')] },
{ key:'09', title:'Carbon IBM', desc:'IBM 设计语言,沉稳规范', source:'carbon', pub:'carbon:add-filled',
items:[M('首页','carbon:dashboard','carbon:dashboard'),M('租房','carbon:building','carbon:building'),M('消息','carbon:chat','carbon:chat'),M('我的','carbon:user','carbon:user')] },
{ key:'10', title:'Boxicons 简洁', desc:'经典简洁,圆润饱满', source:'boxicons', pub:'boxicons:bx-plus-circle',
items:[M('首页','boxicons:bx-grid-alt','boxicons:bx-grid-alt'),M('租房','boxicons:bx-buildings','boxicons:bx-buildings'),M('消息','boxicons:bx-chat','boxicons:bx-chat'),M('我的','boxicons:bx-user','boxicons:bx-user')] },
{ key:'11', title:'Heroicons Tailwind', desc:'Tailwind 官方,粗实心醒目', source:'heroicons', pub:'heroicons:plus-solid',
items:[M('首页','heroicons:squares-2x2-solid','heroicons:squares-2x2-solid'),M('租房','heroicons:building-office-solid','heroicons:building-office-solid'),M('消息','heroicons:chat-bubble-left-right-solid','heroicons:chat-bubble-left-right-solid'),M('我的','heroicons:user-solid','heroicons:user-solid')] },
{ key:'12', title:'Feather 轻盈线条', desc:'经典极简线条,干净利落', source:'feather', pub:'feather:plus-circle',
items:[M('首页','feather:grid','feather:grid'),M('租房','feather:home','feather:home'),M('消息','feather:message-square','feather:message-square'),M('我的','feather:user','feather:user')] },
{ key:'13', title:'Twemoji 多彩扁平', desc:'Twitter 同款扁平表情,彩色生动', source:'twemoji', pub:'twemoji:plus',
items:[M('首页','twemoji:bar-chart','twemoji:bar-chart'),M('租房','twemoji:office-building','twemoji:office-building'),M('消息','twemoji:speech-balloon','twemoji:speech-balloon'),M('我的','twemoji:bust-in-silhouette','twemoji:bust-in-silhouette')] },
{ key:'14', title:'EmojiOne 3D 立体', desc:'3D 渲染表情,立体质感色彩饱和', source:'emojione', pub:'emojione:heavy-plus-sign',
items:[M('首页','emojione:bar-chart','emojione:bar-chart'),M('租房','emojione:office-building','emojione:office-building'),M('消息','emojione:speech-balloon','emojione:speech-balloon'),M('我的','emojione:bust-in-silhouette','emojione:bust-in-silhouette')] },
{ key:'15', title:'Fluent Emoji 微软 3D', desc:'微软 Fluent 3D,圆润软萌', source:'fluent-emoji', pub:'fluent-emoji:plus',
items:[M('首页','fluent-emoji:bar-chart','fluent-emoji:bar-chart'),M('租房','fluent-emoji:office-building','fluent-emoji:office-building'),M('消息','fluent-emoji:speech-balloon','fluent-emoji:speech-balloon'),M('我的','fluent-emoji:bust-in-silhouette','fluent-emoji:bust-in-silhouette')] },
{ key:'16', title:'Fluent Color 彩色微软', desc:'微软彩色描边,蓝紫渐变', source:'fluent-color', pub:'fluent-color:add-circle-24',
items:[M('首页','fluent-color:board-24','fluent-color:board-24'),M('租房','fluent-color:building-24','fluent-color:building-24'),M('消息','fluent-color:chat-24','fluent-color:chat-24'),M('我的','fluent-color:person-24','fluent-color:person-24')] },
{ key:'17', title:'Flat Color 多彩玻璃', desc:'半透明玻璃质感,多彩扁平', source:'flat-color-icons', pub:'flat-color-icons:plus',
items:[M('首页','flat-color-icons:grid','flat-color-icons:grid'),M('租房','flat-color-icons:home','flat-color-icons:home'),M('消息','flat-color-icons:comments','flat-color-icons:comments'),M('我的','flat-color-icons:businessman','flat-color-icons:businessman')] },
{ key:'18', title:'Pixel 像素风', desc:'8-bit 像素,个性醒目', source:'pixelarticons', pub:'pixelarticons:add-box',
items:[M('首页','pixelarticons:grid','pixelarticons:grid'),M('租房','pixelarticons:building','pixelarticons:building'),M('消息','pixelarticons:message','pixelarticons:message'),M('我的','pixelarticons:user','pixelarticons:user')] },
{ key:'19', title:'Icon Park 双色', desc:'字节跳动,蓝黑双色描边', source:'icon-park', pub:'icon-park:add-one',
items:[M('首页','icon-park:dashboard','icon-park:dashboard'),M('租房','icon-park:building-two','icon-park:building-two'),M('消息','icon-park:message','icon-park:message'),M('我的','icon-park:user','icon-park:user')] },
{ key:'20', title:'OpenMoji 开源表情', desc:'开源 emoji,扁平简洁', source:'openmoji', pub:'openmoji:plus',
items:[M('首页','openmoji:bar-chart','openmoji:bar-chart'),M('租房','openmoji:office-building','openmoji:office-building'),M('消息','openmoji:speech-balloon','openmoji:speech-balloon'),M('我的','openmoji:bust-in-silhouette','openmoji:bust-in-silhouette')] }
];
const dataCache = {};
for (const sid of Object.keys(SOURCES)) {
try { dataCache[sid] = load(sid); } catch (e) { console.error('加载失败 ' + sid); process.exit(1); }
}
let cards = '';
const missList = [];
function pubBtn(sol) {
const style = SOURCES[sol.source].style;
const ic = findIcon(dataCache[sol.source], sol.pub);
if (!ic) {
missList.push(sol.pub);
return { normal: '<div class="plus gray"><span>+</span></div>', active: '<div class="plus"><span>+</span></div>' };
}
if (style === 'color') {
return {
normal: '<div class="plus-colored gray">' + renderSVG(ic, 'color', '') + '</div>',
active: '<div class="plus-colored">' + renderSVG(ic, 'color', '') + '</div>'
};
}
return {
normal: '<div class="plus gray">' + renderSVG(ic, style, '#ffffff') + '</div>',
active: '<div class="plus">' + renderSVG(ic, style, '#ffffff') + '</div>'
};
}
for (const sol of SOLUTIONS) {
const style = SOURCES[sol.source].style;
const isColor = style === 'color';
const res = [];
for (const it of sol.items) {
const nIc = findIcon(dataCache[sol.source], it.n);
const aIc = findIcon(dataCache[sol.source], it.a);
if (!nIc) missList.push(it.n);
if (!aIc) missList.push(it.a);
res.push({ label: it.label, normal: nIc ? renderSVG(nIc, style, GRAY) : '', active: aIc ? renderSVG(aIc, style, RED) : '' });
}
const plus = pubBtn(sol);
const icCls = (r, active) => {
if (isColor) return `<div class="ic${active ? '' : ' gray'}">${active ? r.active : r.normal}</div>`;
return `<div class="ic${active ? ' active' : ''}">${active ? r.active : r.normal}</div>`;
};
const arr = [res[0], res[1], null, res[2], res[3]];
const barNormal = `<div class="tabbar">${arr.map(r => r
? `<div class="tabitem">${icCls(r, false)}<div class="lb">${r.label}</div></div>`
: `<div class="tabitem"><div class="ic">${plus.active}</div><div class="lb">发房</div></div>`).join('')}</div>`;
const barActive = `<div class="tabbar">${arr.map((r, i) => r
? `<div class="tabitem${i === 0 ? ' active' : ''}">${icCls(r, i === 0)}<div class="lb">${r.label}</div></div>`
: `<div class="tabitem"><div class="ic">${plus.active}</div><div class="lb">发房</div></div>`).join('')}</div>`;
const strip = res.map(r => `<div class="state-cell">
<div class="state-ic${isColor ? ' gray' : ''}">${r.normal}</div><div class="state-lb">${r.label}·未选</div>
<div class="state-ic${isColor ? '' : ' active'}">${r.active}</div><div class="state-lb${isColor ? '' : ' active'}">${r.label}·选中</div>
</div>`).join('') +
`<div class="state-cell">
<div class="state-ic">${plus.normal}</div><div class="state-lb">发房·未选</div>
<div class="state-ic">${plus.active}</div><div class="state-lb active">发房·选中</div>
</div>`;
cards += `
<div class="card">
<div class="card-head">
<div class="card-title"><span class="tag">方案 ${sol.key}</span>${sol.title}</div>
<div class="card-desc">${sol.desc}</div>
</div>
<div class="card-body">
<div class="mock-wrap">
<div class="mock-col"><div class="mock-title">常规态(全部未选)</div><div class="phone">${barNormal}</div></div>
<div class="mock-col"><div class="mock-title">选中态(首页高亮)</div><div class="phone">${barActive}</div></div>
</div>
<div class="state-strip">${strip}</div>
</div>
</div>`;
}
const html = `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小虎租房 · 底部导航图标方案(20 款)</title>
<style>
* { margin:0; padding:0; box-sizing:border-box; }
body { font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif; background:#f5f5f7; color:#333; padding:36px 28px 80px; }
h1 { font-size:24px; margin-bottom:6px; }
.sub { color:#888; font-size:13px; margin-bottom:10px; }
.legend { font-size:12px; color:#aaa; margin-bottom:30px; line-height:1.7; }
.grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(560px,1fr)); gap:24px; }
.card { background:#fff; border-radius:16px; padding:22px 24px; box-shadow:0 1px 4px rgba(0,0,0,.06); }
.card-head { margin-bottom:16px; }
.card-title { font-size:17px; font-weight:700; display:flex; align-items:center; gap:10px; }
.tag { display:inline-block; background:#FF6700; color:#fff; font-size:12px; font-weight:600; border-radius:6px; padding:2px 8px; }
.card-desc { font-size:12px; color:#999; margin-top:6px; }
.card-body { display:flex; flex-wrap:wrap; gap:20px; align-items:flex-start; }
.mock-wrap { display:flex; gap:16px; }
.mock-col { text-align:center; }
.mock-title { font-size:11px; color:#999; margin-bottom:8px; }
.phone { width:270px; border-radius:18px; border:6px solid #222; background:#fff; overflow:hidden; }
.phone::before { content:""; display:block; height:6px; }
.tabbar { display:flex; height:52px; background:#fff; border-top:1px solid #f0f0f0; }
.tabitem { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px; }
.tabitem .ic { width:23px; height:23px; color:#999; display:flex; align-items:center; justify-content:center; }
.tabitem .ic svg { width:23px; height:23px; display:block; }
.tabitem .ic.active { color:#FF6700; }
.tabitem .lb { font-size:10px; color:#999; line-height:14px; }
.tabitem.active .lb { color:#FF6700; }
.gray { filter:grayscale(1); opacity:.62; }
.plus { width:25px; height:25px; border-radius:50%; background:linear-gradient(135deg,#ff8a00,#FF6700); box-shadow:0 1px 3px rgba(255,103,0,.3); display:flex; align-items:center; justify-content:center; color:#fff; }
.plus svg { width:17px; height:17px; display:block; }
.plus-colored { width:32px; height:32px; margin-top:-3px; margin-left:-4px; filter:drop-shadow(0 2px 4px rgba(0,0,0,.18)); }
.plus-colored svg { width:32px; height:32px; display:block; }
.state-strip { display:flex; gap:14px; flex-wrap:wrap; }
.state-cell { display:flex; flex-direction:column; align-items:center; gap:5px; background:#fafafa; border:1px solid #f0f0f0; border-radius:12px; padding:10px 8px; min-width:70px; }
.state-ic { width:26px; height:26px; color:#999; display:flex; align-items:center; justify-content:center; }
.state-ic svg { width:26px; height:26px; display:block; }
.state-ic.active { color:#FF6700; }
.state-ic .plus, .state-ic .plus-colored { margin:0; }
.state-lb { font-size:10px; color:#aaa; }
.state-lb.active { color:#FF6700; }
</style>
</head>
<body>
<h1>小虎租房 · 底部导航图标方案(20 款)</h1>
<div class="sub">数据来自「画个标」内置图标库 · 未选中 #999999 / 选中 ${RED}(小米橙)· 菜单:首页=工作台、租房=楼宇、发房=新增、消息、我的</div>
<div class="legend">「发房」= 新增(加号)语义:单色方案为橙圆内置白色加号,彩色方案为大号彩色加号。彩色方案未选置灰、选中全彩;单色方案未选灰、选中橙。每卡含常规态 + 首页选中态两个手机框,以及 5 菜单双态对比格(含发房)。</div>
<div class="grid">
${cards}
</div>
</body>
</html>`;
fs.writeFileSync('D:/SGP_KF3/ruyizu_web/docs/tabbar-icons.html', html, 'utf8');
if (missList.length) console.log('缺失图标(' + missList.length + '): ' + missList.join(', '));
else console.log('OK,已生成 docs/tabbar-icons.html(' + SOLUTIONS.length + ' 款方案,全部图标命中)');