#!/usr/bin/env python3
"""
生成教材项目 8(智慧校园管理平台)用到的素材 SVG:名字和尺寸与教材配套资源一致,内容全部自绘(扁平插画)。
运行后用 build-gallery.sh 渲染成 PNG:python3 project8.py && sh build-gallery.sh
"""
from pathlib import Path
OUT = Path(__file__).parent / "svg"
OUT.mkdir(exist_ok=True)
FONT = "Source Han Sans CN, Noto Sans CJK SC, sans-serif"
def save(name, width, height, body):
(OUT / f"{name}.svg").write_text(
f'\n',
encoding="utf-8",
)
# ---------- 标题图:智慧校园 ----------
save("ico_title", 226, 54, f"""
智慧校园
""")
# ---------- 校园建筑:主界面背景、路灯场景共用的元素 ----------
def building(x, y, w, h, color, window="#cfe3f5", rows=4, cols=6, roof="#b36b45"):
parts = [f'',
f'']
gap_x = w / cols
gap_y = (h - 30) / rows
for r in range(rows):
for c in range(cols):
parts.append(f'')
return "\n".join(parts)
def tree(x, y, s=1.0, color="#4f9a45"):
return (f''
f''
f'')
save("bg_home", 1440, 748, f"""
{building(380, 260, 680, 300, "#f2e3c9")}
{building(1080, 360, 220, 200, "#e8d6bd", rows=3, cols=4)}
{building(150, 380, 210, 180, "#e8d6bd", rows=3, cols=4)}
{tree(120, 600, 1.1)}{tree(330, 620, 0.9)}{tree(1130, 610, 1.0)}{tree(1350, 600, 1.2)}
""")
def street(lit):
sky = ('' if lit
else '')
window = "#ffd37a" if lit else "#cfe3f5"
lamps = []
for x in (180, 520, 860, 1200):
lamps.append(f''
f''
f'')
if lit:
lamps.append(f''
f'')
else:
lamps.append(f'')
return f"""
{sky}
{'' if lit else ''}
{building(80, 220, 560, 330, "#e9d8bf", window=window, rows=5, cols=7)}
{building(760, 260, 580, 290, "#dcc7a8", window=window, rows=4, cols=7)}
{''.join(f'' for x in range(30, 1440, 140))}
{''.join(lamps)}
{tree(700, 560, 0.8, "#3f7f45")}{tree(1390, 560, 0.9, "#3f7f45")}
"""
save("day_01", 1440, 716, street(lit=True))
save("day_02", 1440, 716, street(lit=False))
# ---------- 主界面的三个功能图标 ----------
def tile(name, color, icon, label):
save(name, 180, 210, f"""
{icon}
{label}
""")
tile("icon_02", "#2e9e5b", """
""", "校园环境")
tile("icon_03", "#2f7fe0", """
""", "校园安防")
tile("icon_04", "#e2803a", """
""", "退 出")
# ---------- 面板背景(半透明深蓝) ----------
for name, width in (("bg_from1", 555), ("bg_from2", 425)):
save(name, width, 670, f"""
""")
# ---------- 监控:无画面时的图标、方向盘底座、方向键 ----------
save("icon_monitor", 280, 280, """
""")
save("panel_video_ctrl", 500, 500, """
""")
ROTATE = {"up": 0, "right": 90, "down": 180, "left": 270}
for direction, angle in ROTATE.items():
for state, (fill, stroke) in {"normal": ("#ffffff", "#5b6472"), "press": ("#2f7fe0", "#ffffff")}.items():
save(f"btn_arrow_{direction}_{state}", 28, 28, f"""
""")
for direction, angle in (("left", 270), ("right", 90)):
save(f"arrow_{direction}_normal", 60, 60, f"""
""")
save("windowstate_closed_hover", 36, 36, """
""")