// 生成「甄房」LOGO 素材挑选页(自包含单文件 HTML,可直接双击打开)
// 用法: node _design-test/build-page.js
const fs = require('fs');
const path = require('path');
const data = JSON.parse(fs.readFileSync(path.join(__dirname, 'house-icons.json'), 'utf8'));
const TIERS = data.tiers;
// ── 字体清单(本地 OFL + 本机系统字体)────────────────────────────
const FONTS = JSON.parse(fs.readFileSync(path.join(__dirname, 'font-specimens.json'), 'utf8'));
const FONT_CATS = Object.keys(FONTS.cats);
const fontFaces = FONTS.fonts.filter(f => f.kind === 'ofl').map(f =>
"@font-face{font-family:'" + f.family + "';src:url('" + f.src + "') format('" +
(f.fmt === 'ttf' ? 'truetype' : (f.fmt || 'woff2')) + "');font-display:swap}"
).join('\n');
const LIC_BAD = /BY-SA|BY-NC|BY-ND|GPL|-NC-|NonCommercial|非商业/i;
// ── 「甄房」LOGO 概念方案(本次设计)──────────────────────────────
const CONCEPTS = [
{
id: 'zhen-01', name: '甄选之屋', en: 'Selected House', tag: '对勾 · 最直白',
desc: '屋顶 + 墙体 + 对勾。一套图形讲完「甄选好房」,识别度最高,缩小到 favicon 仍清晰。适合做主标。',
mode: 'stroke',
svg: ''
},
{
id: 'zhen-02', name: '檐瓦徽章', en: 'Eave Tile Badge', tag: '中式 · 圆章',
desc: '圆形徽章内一条上翘屋檐 + 两重瓦纹。「甄」本义为陶瓦甄别,此稿把字义直接画进图形,最有文化底子。',
mode: 'stroke',
svg: ''
},
{
id: 'zhen-03', name: '窗格之家', en: 'Window House', tag: '几何 · 秩序',
desc: '屋顶 + 田字窗格。窗格本身有「筛选、框选」的隐喻,结构方正,延展做栅格、水印、加载态都很顺。',
mode: 'stroke',
svg: ''
},
{
id: 'zhen-04', name: '印章 · 甄', en: 'Seal Zhen', tag: '汉字 · 印鉴',
desc: '圆角方印 + 甄字。最贴近「甄房」二字的字面表达,气质正统稳重,适合政务、金融类房产业务线。',
mode: 'mixed',
svg: '' +
'甄'
},
{
id: 'zhen-05', name: '钥匙之家', en: 'Key House', tag: '门锁 · 交付',
desc: '实心屋形挖出钥匙孔。指向「交付钥匙 = 成交」,适合交易、租售、代办过户等业务。',
mode: 'stroke',
svg: ''
},
{
id: 'zhen-06', name: '找房定位', en: 'Find A Home', tag: '定位 · 找房',
desc: '地图定位针内嵌小屋。天然表达「在你想要的位置找到房」,适合 C 端找房 App、地图找房入口。',
mode: 'stroke',
svg: ''
},
{
id: 'zhen-07', name: '联排双屋', en: 'Twin Houses', tag: '多房源 · 平台',
desc: '两栋联排小屋并列。强调「房源多、成规模」,适合房产平台、小区/楼盘库这类主标。',
mode: 'stroke',
svg: '' +
''
},
{
id: 'zhen-08', name: '层叠甄选', en: 'Layered Pick', tag: '抽象 · 现代',
desc: '屋顶下三层递减横线,像层层筛选的房源列表,也呼应「甄」字的多横结构。最现代、最像互联网品牌。',
mode: 'stroke',
svg: ''
}
];
// ── 第二批:home-04 外框 + 字母 Z(直接用 home-04 原始路径,外框几何固定)────
// 外框 = 素材库 hugeicons:home-04(MIT)的原始 path,按 24→64 网格等比放大(stroke 同步放大,粗细比例与原图一致)
// 唯一改动:去掉原图底部那条内部横线(M16 17H8)——它正好落在 Z 的位置,且不属于「外框」
const H04 = 'M3 11.99v2.51c0 3.3 0 4.95 1.025 5.975S6.7 21.5 10 21.5h4c3.3 0 4.95 0 5.975-1.025S21 17.8 21 14.5v-2.51c0-1.682 0-2.522-.356-3.25s-1.02-1.244-2.346-2.276l-2-1.555C14.233 3.303 13.2 2.5 12 2.5s-2.233.803-4.298 2.409l-2 1.555C4.375 7.496 3.712 8.012 3.356 8.74S3 10.308 3 11.99';
const FG = 'translate(5.3304 5.3294) scale(2.22222)'; // 24 网格 → 64 网格,外框落位 12~52 / 10.9~53.1,中心 (32,32)
const INK = '#0C2340', GOLD = '#C6A15B', WH = '#FFFFFF'; // #0C2340 = 定稿色板「甄房蓝 900」
// 定稿字形:Forte 的 Z(已由 fontTools 抽成真实曲线,见 logo/glyphs.json)
const GLYPH_FILE = path.join(__dirname, 'logo', 'glyphs.json');
const GLYPHS = fs.existsSync(GLYPH_FILE) ? JSON.parse(fs.readFileSync(GLYPH_FILE, 'utf8')) : {};
const FORTEZ = GLYPHS.forteZ ? GLYPHS.forteZ.d : '';
const ZCX = GLYPHS.forteZ ? GLYPHS.forteZ.placed[0] + GLYPHS.forteZ.placed[2] / 2 : 32; // Z 着墨中心 x
// 水平拉伸(只拉宽、不动高):绕 Z 自身中心缩放,宽度倍数 sx
const wideZ = (sx) => '';
const frame = (sw, color) => '';
const ZSTD = 'M21.5 30 H42.5 V35.4 L30 42.1 H42.5 V47.5 H21.5 V42.1 L34 35.4 H21.5 Z'; // 实心方块 Z(深底反白用)
const ZSKEL = 'M23 31.5 H41 L23 46 H41'; // 圆角 Z 骨架
// Z 统一字面框:x 21.5~42.5、y 30~47.5(各款按笔画宽自动内缩,保证字面大小一致)
const ZB = { x0: 21.5, x1: 42.5, y0: 30, y1: 47.5 };
// 骨架式 Z:给定笔画宽度与端点,自动算出中心线端点,使描边后的外沿正好落进字面框
function zline(w, o) {
o = o || {};
var caps = o.caps || 'butt', pad = caps === 'round' ? w / 2 : 0;
var x0 = ZB.x0 + w / 2 + pad, x1 = ZB.x1 - w / 2 - pad;
var y0 = ZB.y0 + w / 2 + pad, y1 = ZB.y1 - w / 2 - pad;
return '';
}
const CONCEPTS_FRAME = [
// ── 已定稿 ───────────────────────────────────────────
...(FORTEZ ? [{
id: 'zf-final', star: 2, name: 'Forte Z', en: 'Final', tag: '已定稿 ✓',
desc: '你选定的最终字形:Forte 的大写 Z。已用 fontTools 从字体里抽出真实曲线(不是位图描摹),所以不依赖字体环境即可使用;完整资产(SVG + 36 个位图 + 色板)见顶部「定稿交付」链接。',
mode: 'solid',
svg: frame(1.5, INK) + ''
},
{
id: 'zf-w115', name: 'Forte Z · 拉宽 15%', en: 'Wide 115', tag: '水平拉伸 ×1.15',
desc: '外框与字高完全不动,只把 Z 水平拉宽 15%。最克制的一档,比原版略舒展,几乎看不出被拉过——想要「稳」就选它。',
mode: 'solid',
svg: frame(1.5, INK) + wideZ(1.15)
},
{
id: 'zf-w130', name: 'Forte Z · 拉宽 30%', en: 'Wide 130', tag: '水平拉伸 ×1.30',
desc: '明显变宽的一档:横画被拉长、字腔更开阔,整体更「阔气」。放在方框里左右留白更窄,视觉重心更稳,是我建议优先考虑的一档。',
mode: 'solid',
svg: frame(1.5, INK) + wideZ(1.30)
},
{
id: 'zf-w145', name: 'Forte Z · 拉宽 45%', en: 'Wide 145', tag: '水平拉伸 ×1.45',
desc: '宽体感最强的一档,接近专业字体的「extended」字重观感。注意:水平拉伸会让竖画显厚、斜画变缓,再往上就会开始显胖。',
mode: 'solid',
svg: frame(1.5, INK) + wideZ(1.45)
}] : []),
// ── 保留三款 ─────────────────────────────────────────
{
id: 'zf-k1', star: 1, name: '深底反白', en: 'Dark Reverse', tag: '已保留 · 深色场景',
desc: '深墨蓝圆角底 + 白框白 Z。深色界面、App 图标、深色名片用这一版。',
mode: 'solid',
svg: '' +
frame(1.5, WH) + ''
},
{
id: 'zf-k2', star: 1, name: '圆角 Z', en: 'Round Z', tag: '已保留 · 亲和',
desc: 'Z 用 5.2 圆头描边,转角全圆,跟圆润的框最统一。',
mode: 'solid',
svg: frame(1.5, INK) +
''
},
{
id: 'zf-k3', star: 1, name: '线框 Z', en: 'Line Z', tag: '已保留 · 轻',
desc: 'Z 用 3.6 描边空心字,整体透气,设计工作室调性。',
mode: 'solid',
svg: frame(1.5, INK) +
''
},
// ── 新增 Z 字形(外框不动,只换 Z)──────────────────────
{
id: 'zf-01', name: '锐折 Z', en: 'Sharp Z', tag: '尖角 · 硬朗',
desc: '3.6 等宽细线,但转角是尖的(miter 直角),端点平切。比圆角版硬朗、比实心版轻,最有「精密工具」气质。',
mode: 'solid',
svg: frame(1.5, INK) + zline(3.6, { caps: 'butt', join: 'miter' })
},
{
id: 'zf-02', name: '方头粗 Z', en: 'Square Bold', tag: '几何 · 压得住',
desc: '5.4 粗线、方头方角,像 Helvetica 的骨架直接画出来。远近都清楚,做门头招牌没问题。',
mode: 'solid',
svg: frame(1.5, INK) + zline(5.4, { caps: 'butt', join: 'miter' })
},
{
id: 'zf-03', name: '细线 Z', en: 'Hairline', tag: '极细 · 高级',
desc: '笔画只有 2.4,跟外框的细线等重。整个标看起来像一张线描稿,适合高端、克制的物料。',
mode: 'solid',
svg: frame(1.5, INK) + zline(2.4, { caps: 'butt', join: 'miter' })
},
{
id: 'zf-04', name: '超粗 Z', en: 'Heavy', tag: '最重 · 冲击力',
desc: '笔画 6.6,几乎把框内填满。远看是一个厚重的方块符号,适合做车贴、导视、单色印章。',
mode: 'solid',
svg: frame(1.5, INK) + zline(6.6, { caps: 'butt', join: 'miter' })
},
{
id: 'zf-05', name: '宽体 Z', en: 'Extended', tag: '宽扁 · 稳',
desc: '字面拉宽到 27(比标准宽 28%),笔画 4.4。宽扁的字给人「稳、可信」的心理暗示,适合金融/政务向。',
mode: 'solid',
svg: frame(1.5, INK) + ''
},
{
id: 'zf-06', name: '窄体 Z', en: 'Condensed', tag: '瘦高 · 利落',
desc: '字面收到 13(标准的一半多点),笔画 5.4。瘦高的字显精致、有设计感,也留出更多呼吸。',
mode: 'solid',
svg: frame(1.5, INK) + ''
},
{
id: 'zf-07', name: '曲线斜画', en: 'Curved Z', tag: '柔 · 流动',
desc: '把 Z 的斜画改成一条 S 弯。硬邦邦的字母一下有了流动感,和外框的圆弧线条也更呼应。',
mode: 'solid',
svg: frame(1.5, INK) + ''
},
{
id: 'zf-08', name: '断笔 Z', en: 'Stencil', tag: '断开 · 有节奏',
desc: '三笔全断开,像模板喷字。笔画的间隙让这个 Z 有了节奏感,也更容易在低精度场景下不糊成一团。',
mode: 'solid',
svg: frame(1.5, INK) +
'' +
'' +
''
},
{
id: 'zf-09', name: '空心字 Z', en: 'Hollow', tag: '真·空心',
desc: '不是用线画的,是把一个实心 Z 内部挖空——所以横竖有真实的粗细与字腔,放大看是很正经的字母设计。',
mode: 'solid',
svg: frame(1.5, INK) +
''
},
{
id: 'zf-10', name: '勾尾 Z', en: 'Check Tail', tag: '甄选 · 语义',
desc: 'Z 的底横末端收笔上扬成一个勾,等于把「甄选/通过」这层意思藏进了字母里。形义双关,是这批里最有故事的一稿。',
mode: 'solid',
svg: frame(1.5, INK) +
''
},
{
id: 'zf-11', name: '粗细对比 Z', en: 'Contrast', tag: '衬线感 · 优雅',
desc: '横画加粗到 6、斜画压细到 2.3,做出传统衬线字的粗细对比。优雅、有书卷气,适合线下高端品牌。',
mode: 'solid',
svg: frame(1.5, INK) +
''
},
{
id: 'zf-12', name: '金线 Z', en: 'Gold Line', tag: '墨蓝 + 金',
desc: '线框 Z 的配色版:框留墨蓝、Z 换金色 #C6A15B。比实心金 Z 更含蓄,烫金、压凹工艺都能做。',
mode: 'solid',
svg: frame(1.5, INK) + zline(3.6, { caps: 'butt', join: 'miter', color: GOLD })
}
];
// ── 数据瘦身 + 预置检索字段 ──────────────────────────────────────
const items = data.list.map((it, i) => ({
i: i,
id: it.id, n: it.name, t: it.tier, s: it.source, sn: it.sourceName,
ty: it.type, lic: it.license, bad: LIC_BAD.test(it.license || '') ? 1 : 0,
svg: it.svg
}));
const sources = {};
items.forEach(x => { sources[x.s] = (sources[x.s] || 0) + 1; });
const sourceList = Object.keys(sources).sort((a, b) => sources[b] - sources[a]);
const payload = {
builtAt: new Date().toISOString().slice(0, 16).replace('T', ' '),
total: items.length,
sourceCount: sourceList.length,
tiers: TIERS.map(t => ({ key: t.key, label: t.label, desc: t.desc })),
sources: sourceList.map(id => ({ id: id, count: sources[id], name: (items.find(x => x.s === id) || {}).sn || id })),
items: items
};
const html = `
甄房 ZhenFang · LOGO 素材挑选台
「甄房」LOGO · 素材挑选台
Z H E N F A N G · L O G O P I C K E R
第一步:从你的设计项目素材库(画个标 · 共享图标库 222 源 / 37 万图标)里,把跟「房子」相关的素材全部捞了出来,
去重、分层、按风格精选成 ${items.length} 款可挑选图形;
第二步:基于这批素材的造型语言,我另外设计了两批「甄房」LOGO 概念方案(下方 ${8 + CONCEPTS_FRAME.length} 稿,均为原创矢量,可直接用)——
第一批 8 稿走线条 / 中式 / 印章路线;第二批 ${CONCEPTS_FRAME.length} 稿是home-04 房子外框 + Z 字形(外框一路不动,只换 Z 的字形与笔画);
第三步:Z 的字形不再手画,直接扫你机器上已装的${FONTS.total} 款真字体(素材库 OFL 12 款 + 系统字体 ${FONTS.total - 12} 款)渲染对比(第三节)。
${items.length}精选房子类素材
${sourceList.length}覆盖图标库源
${8 + CONCEPTS_FRAME.length}甄房 LOGO 方案
${FONTS.total}可试 Z 的字体
${payload.builtAt}素材生成时间
一、甄房 LOGO 概念方案 · 第一批(线条 / 中式 / 印章 · 8 稿)
取名「甄房」:甄,本义为制陶甄别、去伪存真,引申为甄选;房即房源。
因此所有方案都围绕「房子 + 甄选」两条线索做叠加。每稿都附合体字标(甄房 / ZHENFANG),可直接定为终稿方向。
二、home-04 外框 + Z 字形探索(12 款新字形 + 3 款已留)
外框固定不动 = hugeicons:home-04(MIT)原图路径等比放大,形状/比例/线宽全部不动。这一节只换里面的 Z:字面统一锁在 21×17.5 的字面框内,各款按笔画宽度自动内缩,所以 12 款的字面大小一致、只有字形不同。
★ 标记的三款是你已选定保留的(深底反白 / 圆角 Z / 线框 Z),放在最前面方便对照。
三、Z 字母 · 字体精选(${FONTS.total} 款)
不再手画字形——直接用真字体渲染 Z。外框依旧是 home-04 原图(不动),Z 用各款字体的大写 Z,并等比放大到填满同一个字面框(21.5 × 20)——与你保留的三款(Z 约 21 宽 × 19.7 高、竖直中心 38.75)取同一比例,所以不存在「大小不一」的干扰,只看字形本身的宽窄与笔画性格。
● 本地素材库字体(OFL-1.1,可直接商用)
● 你本机已安装的系统字体(仅作预览,商用需自行取得授权)
点任意一张卡片即可复制它的 SVG。注意:SVG 里的 Z 是活文字(依赖字体),定稿后我可以把你选中的那一款转成曲线路径。
四、房子类素材挑选(${items.length} 款 · 点击即预览成标)
分五层:房屋本体(做主图形首选)、门户构件(屋顶/门窗/钥匙)、楼宇建筑(楼宇/公共建筑/城市)、
房产交易(成交/租售/服务)、品牌标志(知名品牌 Logo,仅作参考,有商标风险)。
点任意一款 → 右侧实时看它套上「甄房」字标的效果,可换主色、换形状、复制/下载 SVG。
`;
fs.writeFileSync(path.join(__dirname, 'zhenfang-logo-picker.html'), html);
console.log('已生成:', path.join(__dirname, 'zhenfang-logo-picker.html'), (Buffer.byteLength(html) / 1024).toFixed(0) + 'KB');