#!/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{body}\n\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, """ """)