【问题标题】:Electron tray icon change depending on dark theme?电子托盘图标根据深色主题更改?
【发布时间】:2020-11-16 05:54:33
【问题描述】:

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

我知道怎么设置图标了:

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

如何创建一个图标(或选择其他图标)以根据用户选择的主题(普通或深色)改变颜色?

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

【问题讨论】:

    标签: electron


    【解决方案1】:

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

    这样 macOS 会自动将托盘图标调整为在普通主题下为黑色,在深色主题下为白色。

    确保文件名以Template.png 结尾,否则将不起作用!如果您以高 dpi 设备为目标,还包括 @2x.png 版本。

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

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

    然后在你的main.js:

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

    【讨论】:

    • 您有更多关于如何创建这些图像的信息吗?它们是某种精灵图吗?方面?等
    • 只是一个普通的.png 文件。请记住只使用黑色和透明颜色。在我的 Mac 上,正常 dpi 为 22 像素,高 dpi 为 44 像素似乎效果很好,但请自行测试。
    • 这应该如何在 Windows 和 Ubuntu/Linux 上完成?
    【解决方案2】:

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

    // 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 });
    });
    

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

    import { nativeTheme } from "electron"
    
    // refresh icon when MacOS dark/light theme has changed
    nativeTheme.on("updated", () => trayInstance.setImage(getTrayIcon()));
    
    function getTrayIcon(isDark = nativeTheme.shouldUseDarkColors): string {
      return path.resolve(`/path/to/icons/tray_icon${isDark ? "_dark" : ""}.png`
      )
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-11
      • 1970-01-01
      • 2018-04-16
      相关资源
      最近更新 更多