DMG 背景图: PIL 生成箭头 + 中文提示, 布局对齐
之前只有两个图标并排, 用户看不出来要拖拽. 现在在 DMG 挂载打开时:
- 中间一根灰箭头从 .app 指向 Applications
- 底部中文提示 "将左侧应用拖到右侧 Applications 即完成安装"
- 窗口/图标/箭头三者坐标对齐
实现:
- 用 PIL 在 staging 阶段生成 600x400 PNG, 放 .background/bg.png
(dot 前缀让 Finder 默认隐藏)
- AppleScript 里 set background picture 用 HFS path (冒号分隔)
- 图标位置 {150,200} / {450,200} 与背景图箭头两端对齐
PIL 字体查找: PingFang (默认中文) -> STHeiti -> Helvetica -> 兜底,
在打包机上都会命中至少一个.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Showing
1 changed file
with
51 additions
and
5 deletions
| ... | @@ -92,12 +92,54 @@ TMP_DMG="dist/.tmp_rw.dmg" | ... | @@ -92,12 +92,54 @@ TMP_DMG="dist/.tmp_rw.dmg" |
| 92 | STAGE="dist/.dmg_stage" | 92 | STAGE="dist/.dmg_stage" |
| 93 | VOL_NAME="ZB100ImageGenerator" | 93 | VOL_NAME="ZB100ImageGenerator" |
| 94 | 94 | ||
| 95 | # 1. 准备 staging: .app + Applications 快捷方式 | 95 | # 1. 准备 staging: .app + Applications 快捷方式 + 背景图 |
| 96 | rm -rf "$STAGE" | 96 | rm -rf "$STAGE" |
| 97 | mkdir -p "$STAGE" | 97 | mkdir -p "$STAGE/.background" |
| 98 | cp -R "dist/ZB100ImageGenerator.app" "$STAGE/" | 98 | cp -R "dist/ZB100ImageGenerator.app" "$STAGE/" |
| 99 | ln -s /Applications "$STAGE/Applications" | 99 | ln -s /Applications "$STAGE/Applications" |
| 100 | 100 | ||
| 101 | # 用 PIL 生成带箭头+中文提示的背景图 (600x400, 跟 DMG 窗口尺寸匹配) | ||
| 102 | DMG_BG_PATH="$STAGE/.background/bg.png" python3 <<'PYEOF' | ||
| 103 | import os | ||
| 104 | from PIL import Image, ImageDraw, ImageFont | ||
| 105 | |||
| 106 | W, H = 600, 400 | ||
| 107 | img = Image.new('RGB', (W, H), color=(248, 248, 250)) | ||
| 108 | d = ImageDraw.Draw(img) | ||
| 109 | |||
| 110 | # 中间箭头 (从 .app 指向 Applications) | ||
| 111 | arrow_y = 200 | ||
| 112 | arrow_color = (120, 120, 125) | ||
| 113 | d.line([(260, arrow_y), (425, arrow_y)], fill=arrow_color, width=5) | ||
| 114 | d.polygon( | ||
| 115 | [(425, arrow_y - 14), (455, arrow_y), (425, arrow_y + 14)], | ||
| 116 | fill=arrow_color, | ||
| 117 | ) | ||
| 118 | |||
| 119 | # 底部提示文字 | ||
| 120 | def load_font(size): | ||
| 121 | for path in ( | ||
| 122 | "/System/Library/Fonts/PingFang.ttc", | ||
| 123 | "/System/Library/Fonts/STHeiti Medium.ttc", | ||
| 124 | "/System/Library/Fonts/Helvetica.ttc", | ||
| 125 | ): | ||
| 126 | if os.path.exists(path): | ||
| 127 | try: | ||
| 128 | return ImageFont.truetype(path, size) | ||
| 129 | except Exception: | ||
| 130 | continue | ||
| 131 | return ImageFont.load_default() | ||
| 132 | |||
| 133 | font = load_font(22) | ||
| 134 | text = "将左侧应用拖到右侧 Applications 即完成安装" | ||
| 135 | bbox = d.textbbox((0, 0), text, font=font) | ||
| 136 | tw = bbox[2] - bbox[0] | ||
| 137 | d.text(((W - tw) // 2, 320), text, fill=(90, 90, 95), font=font) | ||
| 138 | |||
| 139 | img.save(os.environ['DMG_BG_PATH']) | ||
| 140 | print(f"[dmg] 背景图已生成: {os.environ['DMG_BG_PATH']}") | ||
| 141 | PYEOF | ||
| 142 | |||
| 101 | # 2. 先卸载可能残留的同名卷, 防止上次失败留下的挂载 | 143 | # 2. 先卸载可能残留的同名卷, 防止上次失败留下的挂载 |
| 102 | hdiutil detach "/Volumes/$VOL_NAME" -force >/dev/null 2>&1 || true | 144 | hdiutil detach "/Volumes/$VOL_NAME" -force >/dev/null 2>&1 || true |
| 103 | 145 | ||
| ... | @@ -121,12 +163,16 @@ tell application "Finder" | ... | @@ -121,12 +163,16 @@ tell application "Finder" |
| 121 | set current view of container window to icon view | 163 | set current view of container window to icon view |
| 122 | set toolbar visible of container window to false | 164 | set toolbar visible of container window to false |
| 123 | set statusbar visible of container window to false | 165 | set statusbar visible of container window to false |
| 124 | set the bounds of container window to {200, 120, 800, 470} | 166 | -- 窗口尺寸匹配背景图 600x400, 坐标系从屏幕左上角算 |
| 167 | set the bounds of container window to {200, 120, 800, 520} | ||
| 125 | set theViewOptions to the icon view options of container window | 168 | set theViewOptions to the icon view options of container window |
| 126 | set arrangement of theViewOptions to not arranged | 169 | set arrangement of theViewOptions to not arranged |
| 127 | set icon size of theViewOptions to 128 | 170 | set icon size of theViewOptions to 128 |
| 128 | set position of item "ZB100ImageGenerator.app" of container window to {160, 170} | 171 | -- 设置背景图 (HFS path, 冒号分隔) |
| 129 | set position of item "Applications" of container window to {440, 170} | 172 | set background picture of theViewOptions to file ".background:bg.png" |
| 173 | -- 图标位置要跟背景图里的箭头对齐 | ||
| 174 | set position of item "ZB100ImageGenerator.app" of container window to {150, 200} | ||
| 175 | set position of item "Applications" of container window to {450, 200} | ||
| 130 | update without registering applications | 176 | update without registering applications |
| 131 | delay 1 | 177 | delay 1 |
| 132 | close | 178 | close | ... | ... |
-
Please register or sign in to post a comment