Files
Fam Zheng bcf99ec454
deploy werewolf / build-and-deploy (push) Successful in 1m1s
werewolf(pwa): 离线 PWA — 自定义 SW 预缓存 + 全屏进度条,牌图 21M→2.8M
- vite-plugin-pwa(injectManifest)自定义 SW:install 逐个抓取并向页面广播进度,
  cache-first 服务,导航离线回退 index.html,缓存版本随清单哈希自动淘汰旧缓存
- 全屏 modal 进度条(src/pwa.ts),反映首屏预缓存真实下载进度
- 牌图 mozjpeg 压缩 + 限长边 900px,每张 ≤200K(21.2MB→2.8MB)
- 生成 PWA 图标 + manifest + apple-touch meta,index.html 接入
- 新增脚本:npm run gen:icons / compress:images
2026-05-25 18:44:46 +01:00

47 lines
1.9 KiB
JavaScript

// 从 public/werewolf/back.jpg 生成 PWA 图标。
// 运行: npm run gen:icons
import sharp from 'sharp'
import { mkdir } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import { dirname, resolve } from 'node:path'
const here = dirname(fileURLToPath(import.meta.url))
const pub = resolve(here, '../public')
const src = resolve(pub, 'werewolf/back.jpg')
// 卡背是竖图,狼头菱形大致在水平居中、垂直 ~46% 处。
// 裁一个聚焦狼头 logo 的方形区域作为图标基底(按实际尺寸夹紧,避免越界)。
const meta = await sharp(src).metadata()
const SIDE = Math.min(meta.width, Math.round(meta.width * 0.82), meta.height)
const left = Math.round(Math.max(0, Math.min(meta.width - SIDE, meta.width / 2 - SIDE / 2)))
const top = Math.round(Math.max(0, Math.min(meta.height - SIDE, meta.height * 0.46 - SIDE / 2)))
const square = await sharp(src)
.extract({ left, top, width: SIDE, height: SIDE })
.toBuffer()
const RED = { r: 0xc0, g: 0x39, b: 0x2b, alpha: 1 } // 贴近卡面红,用于 maskable 安全区留白
async function out(name, size, { maskable = false } = {}) {
await mkdir(pub, { recursive: true })
const target = resolve(pub, name)
if (maskable) {
// maskable: 内容缩到 ~80%,四周用卡红留白,保证安全区不被裁切
const inner = Math.round(size * 0.8)
const fg = await sharp(square).resize(inner, inner).toBuffer()
await sharp({ create: { width: size, height: size, channels: 4, background: RED } })
.composite([{ input: fg, gravity: 'center' }])
.png()
.toFile(target)
} else {
await sharp(square).resize(size, size).png().toFile(target)
}
console.log('wrote', name)
}
await out('pwa-192x192.png', 192)
await out('pwa-512x512.png', 512)
await out('maskable-icon-512x512.png', 512, { maskable: true })
await out('apple-touch-icon-180x180.png', 180)
await out('favicon-48x48.png', 48)
console.log('done')