电子托盘图标根据黑暗主题改变?

时间:2017-01-15 17:39:19

标签: electron

我正在使用Electron并尝试开发托盘(菜单栏)应用程序。

enter image description here

我知道如何设置图标:

const {Tray} = require('electron')
appIcon = new Tray('/path/to/my/icon')

如何根据用户选择的主题(正常或黑暗)创建一个会改变颜色的图标(或选择另一个图标)?

在上面的例子中,我使用了一个黑暗的主题,所以我可以创建一个白色图标,但是当用户拥有正常的白色主题时会发生什么?

2 个答案:

答案 0 :(得分:6)

你应该使用模板图像(只有黑色和清晰的颜色):https://github.com/electron/electron/blob/master/docs/api/native-image.md#template-image

这样,macOS会在正常主题时自动将托盘图标调整为黑色,在黑暗主题时自动调整为白色。

确保文件名以Template.png结尾,否则无效!如果您定位hi-dpi设备,还要包含@2x.png版本。

所以你的文件夹看起来像是:

.
├── main.js
├── IconTemplate.png
└── IconTemplate@2x.png

然后在main.js

const {Tray} = require('electron')
appIcon = new Tray('./IconTemplate.png')

答案 1 :(得分:0)

我们将SVG到PNG的托盘图标构建为黑白颜色,如下所示:

"build": "",
{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "scripts": {
    "lint": "eslint .",
    "build": "",
    "serve": "firebase serve --only functions",
    "shell": "firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "12"
  },
  "main": "index.js",
  "dependencies": {
    "cookie-parser": "^1.4.5",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "firebase": "^7.22.0",
    "firebase-admin": "^9.4.1",
    "firebase-functions": "^3.11.0"
  },
  "devDependencies": {
    "eslint": "^5.12.0",
    "eslint-plugin-promise": "^4.0.1",
    "firebase-functions-test": "^0.2.0"
  },
  "private": true
}

然后在主题更新中更新托盘图标,如下所示:

// File: build/build_tray_icon.ts
// Command: yarn run ts-node build/build_tray_icon.ts

import path from "path"
import sharp from "sharp";
import jsdom from "jsdom"
import fs from "fs-extra"

export async function generateTrayIcon(
  {
    outputFilename = "tray_icon", // e.g. output tray_icon_dark@2x.png
    svgIconPath = path.resolve(__dirname, "../src/renderer/components/icon/logo.svg"),
    outputFolder = path.resolve(__dirname, "./tray"),
    dpiSuffix = "2x",
    pixelSize = 32,
    shouldUseDarkColors = false, // managed by electron.nativeTheme.shouldUseDarkColors
  } = {}) {
  outputFilename += shouldUseDarkColors ? "_dark" : ""
  dpiSuffix = dpiSuffix !== "1x" ? `@${dpiSuffix}` : ""
  const pngIconDestPath = path.resolve(outputFolder, `${outputFilename}${dpiSuffix}.png`)
  try {
    // Modify .SVG colors
    const trayIconColor = shouldUseDarkColors ? "white" : "black";
    const svgDom = await jsdom.JSDOM.fromFile(svgIconPath);
    const svgRoot = svgDom.window.document.body.getElementsByTagName("svg")[0];
    svgRoot.innerHTML += `<style>* {fill: ${trayIconColor} !important;}</style>`
    const svgIconBuffer = Buffer.from(svgRoot.outerHTML);

    // Resize and convert to .PNG
    const pngIconBuffer: Buffer = await sharp(svgIconBuffer)
      .resize({ width: pixelSize, height: pixelSize })
      .png()
      .toBuffer();

    // Save icon
    await fs.writeFile(pngIconDestPath, pngIconBuffer);
    console.info(`[DONE]: Tray icon saved at "${pngIconDestPath}"`);
  } catch (err) {
    console.error(`[ERROR]: ${err}`);
  }
}

// Run
const iconSizes: Record<string, number> = {
  "1x": 16,
  "2x": 32,
};
Object.entries(iconSizes).forEach(([dpiSuffix, pixelSize]) => {
  generateTrayIcon({ dpiSuffix, pixelSize, shouldUseDarkColors: false });
  generateTrayIcon({ dpiSuffix, pixelSize, shouldUseDarkColors: true });
});