You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在macOS版Electron中为Template Image叠加红色徽章作菜单栏图标?

Electron Template Image叠加红色徽章实现方案

核心问题在于:Template Image会自动过滤所有颜色信息,只保留明暗轮廓,所以直接把带红色徽章的图转为Template会丢失徽章颜色。正确的做法是将基础图标设为Template,再单独叠加彩色徽章,具体有两种实现方式:

方式一:用Canvas动态绘制徽章(适合动态数字徽章)

需要先安装canvas依赖包:npm install canvas

const { app, Menu, nativeImage } = require('electron');
const { createCanvas, loadImage } = require('canvas');

async function getBadgedTemplateIcon(baseIconPath, badgeNum) {
  // 加载基础模板图标并标记为Template
  const baseTemplate = nativeImage.createFromPath(baseIconPath).setTemplateImage(true);
  const baseImg = await loadImage(baseTemplate.toDataURL());

  // 创建与基础图标尺寸一致的画布
  const canvas = createCanvas(baseImg.width, baseImg.height);
  const ctx = canvas.getContext('2d');

  // 绘制基础模板图标
  ctx.drawImage(baseImg, 0, 0);

  // 绘制红色圆形徽章(右上角位置)
  const badgeSize = Math.floor(baseImg.width * 0.3);
  const posX = baseImg.width - badgeSize - 5;
  const posY = 5;

  // 徽章背景
  ctx.fillStyle = '#ff3b30';
  ctx.beginPath();
  ctx.arc(posX + badgeSize/2, posY + badgeSize/2, badgeSize/2, 0, Math.PI * 2);
  ctx.fill();

  // 徽章数字
  ctx.fillStyle = '#ffffff';
  ctx.font = `${badgeSize * 0.6}px sans-serif`;
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText(badgeNum.toString(), posX + badgeSize/2, posY + badgeSize/2);

  // 转为Electron NativeImage返回
  return nativeImage.createFromDataURL(canvas.toDataURL());
}

// 应用启动后生成带徽章的图标并设置菜单
app.whenReady().then(async () => {
  const menuIcon = await getBadgedTemplateIcon('./base-template-icon.png', 3);
  
  const appMenu = Menu.buildFromTemplate([
    {
      label: '我的应用',
      icon: menuIcon,
      submenu: [{ role: 'quit' }]
    }
  ]);
  Menu.setApplicationMenu(appMenu);
});

方式二:预生成徽章图叠加(适合静态徽章)

如果徽章是固定样式,无需动态修改数字,可以提前做好红色徽章图片,直接用NativeImage的composite方法叠加:

const { app, Menu, nativeImage } = require('electron');

app.whenReady().then(() => {
  // 加载基础模板图标并标记为Template
  const baseTemplate = nativeImage.createFromPath('./base-template-icon.png').setTemplateImage(true);
  // 加载预制作的红色徽章图(普通彩色图,不要设为Template)
  const redBadge = nativeImage.createFromPath('./red-badge.png');

  // 计算徽章位置(右上角偏移5px)
  const baseSize = baseTemplate.getSize();
  const badgeSize = redBadge.getSize();
  const badgePos = {
    x: baseSize.width - badgeSize.width - 5,
    y: 5
  };

  // 合成图标
  const badgedIcon = baseTemplate.composite(redBadge, badgePos);

  // 设置菜单栏
  const appMenu = Menu.buildFromTemplate([
    {
      label: '我的应用',
      icon: badgedIcon,
      submenu: [{ role: 'quit' }]
    }
  ]);
  Menu.setApplicationMenu(appMenu);
});

关键注意点

  • 基础图标必须是纯黑白轮廓图,标记为Template后,系统会根据菜单栏的明暗主题自动适配图标颜色。
  • 徽章部分不能标记为Template,要保留原始颜色,叠加后不会被Template的颜色过滤规则影响。

内容的提问来源于stack exchange,提问作者Xue An Chuang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:13:12