| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- # -*- coding: utf-8 -*-
- """泓衍票据 · 应用图标方案生成器 —— 1024×1024 标准 SVG
- 每个方案输出:iOS 整图 / Android 自适应前景 / Android 自适应背景 / Android 单色
- """
- import pathlib
- OUT = pathlib.Path("/Users/guoguo/Desktop/HeHuiDeepBlue/设计/深空蓝/图标/svg")
- OUT.mkdir(parents=True, exist_ok=True)
- THEMES = {
- "deep": dict( # 深空蓝(主方案)
- bg=[("0","#3170FF"),(".48","#1B4FD8"),("1","#0A2A82")],
- glow="#A8C6FF", glowop=".42",
- ink=[("0","#FFFFFF"),("1","#D9E7FF")],
- sub="#8FB2FF",
- gold=[("0","#F8C263"),("1","#E08A17")],
- ),
- "frost": dict( # 霜白(浅色方案)
- bg=[("0","#FFFFFF"),(".52","#EDF3FF"),("1","#D6E3F9")],
- glow="#FFFFFF", glowop=".85",
- ink=[("0","#2A62EA"),("1","#0E3AAE")],
- sub="#FFFFFF",
- gold=[("0","#DCA02C"),("1","#A8680A")],
- ),
- "mono": dict( # Android 13+ 单色主题图标
- bg=[("0","#00000000"),("1","#00000000")],
- glow="#000000", glowop="0",
- ink=[("0","#FFFFFF"),("1","#FFFFFF")],
- sub="#000000",
- gold=[("0","#FFFFFF"),("1","#FFFFFF")],
- mono=True,
- ),
- }
- SAFE = 0.72 # Android 自适应安全区缩放
- def stops(l): return "".join(f'<stop offset="{o}" stop-color="{c}"/>' for o,c in l)
- # ── 图形本体:返回 (满版元素, 主体标记) ──────────────────────
- def mark_A(p): # A 三叠水 · 泓纹(水波三叠,末叠鎏金)
- def wave(x0, L, y, a=32):
- return (f"M {x0} {y} C {x0+L*0.16:.0f} {y-a} {x0+L*0.34:.0f} {y-a} {x0+L*0.5:.0f} {y} "
- f"S {x0+L*0.84:.0f} {y+a} {x0+L} {y}")
- return "", f'''
- <g fill="none" stroke-width="116" stroke-linecap="round">
- <path d="{wave(302,420,348)}" stroke="url(#inkg)"/>
- <path d="{wave(262,500,512)}" stroke="url(#inkg)"/>
- <path d="{wave(238,548,676)}" stroke="url(#goldg)"/>
- </g>'''
- def mark_B(p): # B 券印 · 票据 + 骑缝章
- return "", f'''
- <mask id="mB">
- <rect x="0" y="0" width="1024" height="1024" fill="#fff"/>
- <circle cx="734" cy="244" r="120" fill="#000"/>
- </mask>
- <g transform="translate(512,512) rotate(-7)">
- <g mask="url(#mB)" transform="rotate(7) translate(-512,-512)">
- <g transform="translate(512,512) rotate(-7)">
- <rect x="-243" y="-296" width="486" height="592" rx="70" fill="url(#inkg)"/>
- <rect x="-152" y="-150" width="238" height="50" rx="25" fill="{p['sub']}"/>
- <rect x="-152" y="-52" width="304" height="50" rx="25" fill="{p['sub']}"/>
- <rect x="-152" y="74" width="220" height="62" rx="31" fill="url(#goldg)"/>
- </g>
- </g>
- </g>
- <circle cx="734" cy="244" r="88" fill="url(#goldg)"/>'''
- def mark_C(p): # C 泓池 · 深水环 + 金色水面
- return "", f'''
- <clipPath id="cC"><circle cx="512" cy="512" r="{232 if p.get("mono") else 256}"/></clipPath>
- <circle cx="512" cy="512" r="300" fill="none" stroke="url(#inkg)" stroke-width="88"/>
- <g clip-path="url(#cC)">
- <path d="M 224 548 C 300 486 368 604 470 552 C 562 505 636 588 812 516 L 812 812 L 224 812 Z" fill="url(#goldg)"/>
- </g>'''
- def mark_D(p): # D 泓衡 · H 字标(斜梁)
- return "", f'''
- <g transform="translate(512,512) scale(.96)">
- <rect x="-250" y="-310" width="134" height="620" rx="42" fill="url(#inkg)"/>
- <rect x="116" y="-310" width="134" height="620" rx="42" fill="url(#inkg)"/>
- <path d="M -186 -12 L 186 -132 L 186 8 L -186 128 Z" fill="url(#goldg)"/>
- </g>'''
- def mark_E(p): # E 玺信 · 印章 + 泓
- return "", f'''
- <g transform="translate(512,512) rotate(-4)">
- <rect x="-302" y="-302" width="604" height="604" rx="116" fill="none" stroke="url(#goldg)" stroke-width="54"/>
- <text x="0" y="8" text-anchor="middle" dominant-baseline="central"
- font-family="PingFang SC, Heiti SC, STHeiti, sans-serif" font-weight="600" font-size="386"
- fill="url(#inkg)">泓</text>
- </g>'''
- def mark_F(p): # F 票角 · 整枚图标即一张票据,右下折角
- bleed = '<path d="M 1024 590 L 1024 1024 L 590 1024 Z" fill="url(#goldg)"/>'
- return bleed, f'''
- <g>
- <rect x="286" y="316" width="286" height="66" rx="33" fill="url(#inkg)"/>
- <rect x="286" y="440" width="400" height="66" rx="33" fill="url(#inkg)"/>
- <rect x="286" y="562" width="238" height="78" rx="39" fill="url(#goldg)"/>
- </g>'''
- MARKS = {"a":mark_A,"b":mark_B,"c":mark_C,"d":mark_D,"e":mark_E,"f":mark_F}
- NAMES = {"a":"sanshui","b":"quanyin","c":"hongchi","d":"hengbiao","e":"xixin","f":"piaojiao"}
- def build(key, theme, layer):
- """layer: full | fg | bg | mono"""
- p = THEMES["mono" if layer=="mono" else theme]
- bleed, mark = MARKS[key](p)
- d = f'''<linearGradient id="bgg" x1="0" y1="0" x2=".85" y2="1">{stops(p["bg"])}</linearGradient>
- <radialGradient id="glow" cx=".30" cy=".14" r=".82"><stop offset="0" stop-color="{p['glow']}" stop-opacity="{p['glowop']}"/><stop offset="1" stop-color="{p['glow']}" stop-opacity="0"/></radialGradient>
- <linearGradient id="inkg" x1=".2" y1="0" x2=".8" y2="1">{stops(p["ink"])}</linearGradient>
- <linearGradient id="goldg" x1=".1" y1="0" x2=".9" y2="1">{stops(p["gold"])}</linearGradient>'''
- plate = '<rect width="1024" height="1024" fill="url(#bgg)"/><rect width="1024" height="1024" fill="url(#glow)"/>'
- if layer == "full":
- inner = plate + bleed + mark
- elif layer == "bg":
- inner = plate + bleed
- elif layer == "fg":
- inner = f'<g transform="translate(512,512) scale({SAFE}) translate(-512,-512)">{mark}</g>'
- else: # mono:ink/gold→白、sub→黑,整组作为 mask 打到黑色实底上
- inner = (f'<mask id="mono"><rect width="1024" height="1024" fill="#000"/>'
- f'<g transform="translate(512,512) scale({SAFE}) translate(-512,-512)">{mark}</g></mask>'
- f'<rect width="1024" height="1024" fill="#000" mask="url(#mono)"/>')
- return (f'<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">'
- f'<defs>{d}</defs>{inner}</svg>')
- n = 0
- for k in MARKS:
- for t in ("deep","frost"):
- for layer, tag in (("full",""),("fg","-android-fg"),("bg","-android-bg")):
- (OUT/f"icon-{k}-{NAMES[k]}-{t}{tag}.svg").write_text(build(k,t,layer), encoding="utf-8")
- n += 1
- (OUT/f"icon-{k}-{NAMES[k]}-android-mono.svg").write_text(build(k,"deep","mono"), encoding="utf-8")
- n += 1
- print(f"生成 {n} 个 SVG → {OUT}")
|