Files
danyang-match/scripts/generate_tabbar_icons.py
T

238 lines
7.4 KiB
Python
Raw 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.
#!/usr/bin/env python3
"""
丹阳公益婚恋平台 - 底部导航栏图标生成脚本
圆润线性风格,两种状态(未选中/选中),三种尺寸
"""
from PIL import Image, ImageDraw
import math
import os
# 主题色配置
COLOR_UNSELECTED = (153, 153, 153) # #999999
COLOR_SELECTED = (233, 107, 107) # #E96B6B
COLOR_BG = (255, 255, 255) # 白色背景
def sin_deg(x):
return math.sin(math.radians(x))
def cos_deg(x):
return math.cos(math.radians(x))
def draw_heart_points(cx, cy, scale):
"""计算心形路径点"""
pts = []
for t in range(0, 360, 3):
rad = t * 3.14159 / 180
x = scale * 16 * (sin_deg(rad) ** 3)
y = -scale * (13 * cos_deg(rad) - 5 * cos_deg(2*rad) - 2 * cos_deg(3*rad) - cos_deg(4*rad))
pts.append((cx + x, cy + y))
return pts
def draw_rounded_rect(draw, x, y, w, h, r, color, width=2):
"""绘制圆角矩形(无填充,只描边)"""
r = min(r, w // 2, h // 2)
draw.rounded_rectangle([x, y, x + w, y + h], radius=r, outline=color, width=width)
def draw_house(draw, cx, cy, size, color, width=2):
"""绘制房子图标 - 首页"""
s = size * 0.35
# 房子主体
body_x, body_y = cx - s * 0.7, cy - s * 0.1
body_w, body_h = s * 1.4, s * 0.7
draw_rounded_rect(draw, body_x, body_y, body_w, body_h, 4, color, width)
# 屋顶(三角形)
roof_points = [
(cx, body_y - s * 0.5),
(body_x - s * 0.15, body_y),
(body_x + body_w + s * 0.15, body_y)
]
draw.polygon(roof_points, outline=color, width=width)
# 门
door_w, door_h = s * 0.28, s * 0.4
door_x = cx - door_w / 2
door_y = body_y + body_h - door_h
draw_rounded_rect(draw, door_x, door_y, door_w, door_h, 2, color, width)
# 烟囱
chimney_w, chimney_h = s * 0.12, s * 0.22
chimney_x = cx + s * 0.35
chimney_y = body_y - s * 0.35
draw_rounded_rect(draw, chimney_x, chimney_y, chimney_w, chimney_h, 2, color, width)
def draw_hearts(draw, cx, cy, size, color, width=2):
"""绘制双心图标 - 找对象"""
s = size * 0.016
offset = s * 4
# 左心
left_pts = draw_heart_points(cx - offset, cy - offset * 0.3, s)
right_pts = draw_heart_points(cx + offset, cy - offset * 0.3, s)
for pts in [left_pts, right_pts]:
for i in range(len(pts)):
p1 = pts[i]
p2 = pts[(i + 1) % len(pts)]
draw.line([p1, p2], fill=color, width=width)
def draw_chat_bubble(draw, cx, cy, size, color, width=2):
"""绘制对话气泡图标 - 消息"""
s = size * 0.28
# 气泡主体
bubble_x, bubble_y = cx - s, cy - s * 0.6
bubble_w, bubble_h = s * 2, s * 1.2
draw_rounded_rect(draw, bubble_x, bubble_y, bubble_w, bubble_h, 8, color, width)
# 小三角
tail_points = [
(bubble_x + s * 0.1, bubble_y + bubble_h),
(bubble_x + s * 0.3, bubble_y + bubble_h + s * 0.25),
(bubble_x + s * 0.5, bubble_y + bubble_h)
]
draw.polygon(tail_points, outline=color, width=width)
# 内部文字线条
line_y_start = bubble_y + s * 0.2
for i in range(3):
line_y = line_y_start + i * s * 0.22
draw.line([(bubble_x + s * 0.15, line_y), (bubble_x + s * 1.5, line_y)], fill=color, width=width)
def draw_calendar(draw, cx, cy, size, color, width=2):
"""绘制日历图标 - 活动"""
s = size * 0.26
# 日历主体
cal_x, cal_y = cx - s, cy - s * 0.55
cal_w, cal_h = s * 2, s * 1.3
draw_rounded_rect(draw, cal_x, cal_y, cal_w, cal_h, 6, color, width)
# 顶部横线(分隔年月和日期)
draw.line([(cal_x + s * 0.05, cal_y + s * 0.25), (cal_x + cal_w - s * 0.05, cal_y + s * 0.25)], fill=color, width=width)
# 日期点
dot_r = 2 if size >= 162 else 1
positions = [
(cal_x + s * 0.3, cal_y + s * 0.55),
(cal_x + s * 0.7, cal_y + s * 0.55),
(cal_x + s * 1.1, cal_y + s * 0.55),
(cal_x + s * 0.5, cal_y + s * 0.9),
(cal_x + s * 0.9, cal_y + s * 0.9),
]
for dx, dy in positions:
draw.ellipse([dx - dot_r, dy - dot_r, dx + dot_r, dy + dot_r], fill=color)
# 左上角挂环
ring_r = 4 if size >= 162 else 2
draw.ellipse([cal_x + s * 0.25 - ring_r, cal_y - ring_r, cal_x + s * 0.25 + ring_r, cal_y + ring_r], outline=color, width=width)
draw.ellipse([cal_x + s * 1.75 - ring_r, cal_y - ring_r, cal_x + s * 1.75 + ring_r, cal_y + ring_r], outline=color, width=width)
def draw_user(draw, cx, cy, size, color, width=2):
"""绘制用户图标 - 我的"""
s = size * 0.3
# 头部(圆形)
head_r = s * 0.38
head_x, head_y = cx, cy - s * 0.25
draw.ellipse([head_x - head_r, head_y - head_r, head_x + head_r, head_y + head_r], outline=color, width=width)
# 身体(半椭圆)
body_top = cy + s * 0.15
body_bottom = cy + s * 0.75
body_left = cx - s * 0.45
body_right = cx + s * 0.45
draw.arc([body_left, body_top, body_right, body_bottom], start=180, end=360, fill=color, width=width)
# 身体两侧竖线
side_offset = s * 0.4
draw.line([(cx - side_offset, body_top), (cx - side_offset, body_bottom)], fill=color, width=width)
draw.line([(cx + side_offset, body_top), (cx + side_offset, body_bottom)], fill=color, width=width)
ICON_FUNCTIONS = {
"home": draw_house,
"discover": draw_hearts,
"message": draw_chat_bubble,
"activity": draw_calendar,
"mine": draw_user,
}
def create_icon(icon_name, size, color):
"""创建单个图标"""
img = Image.new('RGBA', (size, size), color=(255, 255, 255, 0)) # 透明背景
draw = ImageDraw.Draw(img)
func = ICON_FUNCTIONS.get(icon_name)
if func:
func(draw, size // 2, size // 2, size, color)
return img
def main():
output_dir = r"E:\develop\公益婚恋服务平台\miniapp\assets\tabbar"
os.makedirs(output_dir, exist_ok=True)
icons = [
("home", "首页"),
("discover", "找对象"),
("message", "消息"),
("activity", "活动"),
("mine", "我的"),
]
sizes_map = [
(81, ""), # 1x
(162, "_2x"), # 2x
(243, "_3x"), # 3x
]
print("=" * 50)
print("丹阳公益婚恋平台 - 底部导航栏图标生成")
print("=" * 50)
print()
total = 0
for icon_name, label in icons:
print(f"🎨 {label} ({icon_name}):")
for size, suffix in sizes_map:
# 未选中状态
img_u = create_icon(icon_name, size, color=COLOR_UNSELECTED)
path_u = os.path.join(output_dir, f"{icon_name}{suffix}.png")
img_u.save(path_u, 'PNG')
# 选中状态
img_s = create_icon(icon_name, size, color=COLOR_SELECTED)
path_s = os.path.join(output_dir, f"{icon_name}-active{suffix}.png")
img_s.save(path_s, 'PNG')
print(f" ✓ {os.path.basename(path_u)} ({size}×{size}, {os.path.getsize(path_u)} bytes)")
print(f" ✓ {os.path.basename(path_s)} ({size}×{size}, {os.path.getsize(path_s)} bytes)")
total += 2
print()
print("=" * 50)
print(f"✅ 共生成 {total} 个图标文件")
print(f"📁 保存路径: {output_dir}")
print()
print("文件清单:")
for f in sorted(os.listdir(output_dir)):
if f.endswith('.png'):
filepath = os.path.join(output_dir, f)
print(f" {f} ({os.path.getsize(filepath)} bytes)")
if __name__ == "__main__":
main()