3. 动态生成图标
任务说明
本案例需要完成一个完整的PWA图标动态生成方案:通过Canvas在运行时绘制应用图标,并输出为不同尺寸的PNG文件,最终将这些图标引用到Web App Manifest中。这样即使没有设计资源,也能快速生成一套适配不同设备的图标。
实现方案
核心思路是编写一个独立的Node.js脚本,使用纯Canvas API(通过canvas包)绘制一个带渐变背景和文字标识的图标,然后按PWA规范输出192px和512px两种必需尺寸,同时生成favicon.ico所需的源图。脚本执行后会在icons/目录下生成图标文件,随后我们创建一个引用这些图标的manifest.webmanifest文件。
代码实现
// generate-icons.js
const fs = require('fs');
const path = require('path');
const { createCanvas } = require('canvas');
// 图标绘制函数:绘制渐变背景 + 中心文字
function drawIcon(size) {
const canvas = createCanvas(size, size);
const ctx = canvas.getContext('2d');
// 背景渐变(从左上到右下)
const gradient = ctx.createLinearGradient(0, 0, size, size);
gradient.addColorStop(0, '#4facfe');
gradient.addColorStop(1, '#00f2fe');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, size, size);
// 绘制白色圆角边框(模拟应用图标风格)
ctx.strokeStyle = 'rgba(255,255,255,0.6)';
ctx.lineWidth = Math.max(2, size * 0.02);
const margin = size * 0.08;
ctx.beginPath();
ctx.roundRect(margin, margin, size - 2 * margin, size - 2 * margin, size * 0.15);
ctx.stroke();
// 绘制中心文字 "PWA"
ctx.fillStyle = '#ffffff';
ctx.font = `bold ${Math.floor(size * 0.28)}px "Arial", sans-serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('PWA', size / 2, size / 2);
return canvas.toBuffer('image/png');
}
// 确保输出目录存在
const outDir = path.join(__dirname, 'icons');
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir);
}
// 生成PWA所需尺寸
const sizes = [192, 512];
sizes.forEach(size => {
const buffer = drawIcon(size);
fs.writeFileSync(path.join(outDir, `icon-${size}x${size}.png`), buffer);
console.log(`已生成 icon-${size}x${size}.png`);
});
// 额外生成一个180px用于苹果touch-icon(可选)
const appleBuffer = drawIcon(180);
fs.writeFileSync(path.join(outDir, 'apple-touch-icon.png'), appleBuffer);
console.log('已生成 apple-touch-icon.png');
console.log('所有图标生成完毕!');
Manifest配置
// manifest.webmanifest
{
"name": "Canvas图标演示应用",
"short_name": "图标演示",
"start_url": "./index.html",
"display": "standalone",
"background_color": "#4facfe",
"theme_color": "#00f2fe",
"icons": [
{
"src": "icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
]
}
落地与运行
首先安装依赖:
npm install canvas
然后执行脚本生成图标:
node generate-icons.js
执行后会在当前目录下生成icons/文件夹,其中包含icon-192x192.png、icon-512x512.png和apple-touch-icon.png三个文件。将manifest.webmanifest与icons/目录放在Web应用的根目录下,并在HTML中通过<link rel="manifest" href="#" aria-disabled="true" data-keke-missing-local-link="1" onclick="return false">引用即可。
验证方法
1. 运行node generate-icons.js后,检查icons/目录下是否生成三个PNG文件,且文件大小不为0。
2. 用图片查看器打开任意图标,确认尺寸分别为192×192、512×512和180×180像素,背景为蓝白渐变,中央有白色"PWA"文字。
3. 在Chrome浏览器中启动本地HTTP服务器(如npx serve)访问页面,打开DevTools → Application → Manifest面板,确认图标列表正确加载且无404错误。
4. 在Lighthouse面板运行PWA审计,确认"安装提示"相关检查项中图标配置通过。