ElectronJS是一个开源框架,用于使用 HTML、CSS 和 JavaScript 等 Web 技术构建跨平台原生桌面应用程序,这些技术能够在Windows 、 macOS和Linux操作系统上运行。它将 Chromium 引擎和NodeJS 组合成一个单一的运行时。
为了使桌面应用程序对用户更具吸引力和吸引力,开发人员除了使用CSS 外,还应开发应用程序以使其与本机系统主题兼容。应用程序应提供一项功能,用户可以在其中控制应用程序的外观和感觉,并在运行时动态更改主题。这增强了应用程序的UI并使其与系统环境融为一体。 Electron 提供了一种方法,我们可以使用内置的nativeTheme模块的 Instance 属性和事件来实现这一点。本教程将演示如何使用nativeTheme模块。任何额外的 CSS 应该只应用于本机系统主题,以便为应用程序设计样式。
我们假设您熟悉上述链接中介绍的先决条件。为了让 Electron 正常工作,需要在系统中预装node和npm 。
- 项目结构:
示例:按照ElectronJS中的动态样式中给出的步骤设置基本的 Electron 应用程序。复制文章中提供的main.js文件和index.html文件的样板代码。还要执行package.json文件中提到的必要更改以启动电子应用程序。我们将继续使用相同的代码库构建我们的应用程序。
包.json:
{
"name": "electron-theme",
"version": "1.0.0",
"description": "Themes in Electron",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"keywords": [
"electron"
],
"author": "Radhesh Khanna",
"license": "ISC",
"dependencies": {
"electron": "^8.3.0"
}
}
根据项目结构文件夹中创建的资产,分别创建light.css文件和dark.css文件。我们将在执行期间动态地将这些CSS文件注入到应用程序中。
输出:此时,我们的基本电子应用程序已设置。启动应用程序后,我们应该会看到以下结果。
Electron 中的原生主题: nativeTheme模块用于读取、响应和应用对 Chromium 原生颜色主题的更改。原生系统主题也适用于 Chromium 的原生颜色主题。该模块是Main Process 的一部分。为了在Renderer Process 中导入和使用nativeTheme模块,我们将使用 Electron远程模块。
注意: nativeTheme模块仅支持实例事件和实例属性。它确实有任何与之关联的 Instance 方法。
index.html:启用深色主题和启用浅色主题按钮还没有任何与之相关的功能。要更改此设置,请在index.js文件中添加以下代码。
HTML
Javascript
const electron = require("electron");
// Importing the nativeTheme module
// using Electron remote
const nativeTheme = electron.remote.nativeTheme;
const path = require("path");
console.log("By Default, Dark Theme Enabled - ",
nativeTheme.shouldUseDarkColors);
console.log("High Contrast Colors - ",
nativeTheme.shouldUseHighContrastColors);
console.log("Inverted Colors - ",
nativeTheme.shouldUseInvertedColorScheme);
nativeTheme.on("updated", () => {
console.log("Updated Event has been Emitted");
if (nativeTheme.shouldUseDarkColors) {
console.log("Dark Theme Chosen by User");
} else {
console.log("Light Theme Chosen by User");
}
});
var dark = document.getElementById("dark");
dark.addEventListener("click", () => {
nativeTheme.themeSource = "dark";
});
var light = document.getElementById("light");
light.addEventListener("click", () => {
nativeTheme.themeSource = "light";
});
Javascript
const electron = require("electron");
// Importing the nativeTheme module
// using Electron remote
const nativeTheme = electron.remote.nativeTheme;
const path = require("path");
console.log("By Default, Dark Theme Enabled - ",
nativeTheme.shouldUseDarkColors);
console.log("High Contrast Colors - ",
nativeTheme.shouldUseHighContrastColors);
console.log("Inverted Colors - ",
nativeTheme.shouldUseInvertedColorScheme);
function loadCSS(load) {
var head = document.getElementsByTagName("head")[0];
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = path.join(__dirname, "../assets/"
+ load + ".css");
head.appendChild(link);
}
nativeTheme.on("updated", () => {
console.log("Updated Event has been Emitted");
if (nativeTheme.shouldUseDarkColors) {
console.log("Dark Theme Chosen by User");
console.log("Dark Theme Enabled - ",
nativeTheme.shouldUseDarkColors);
loadCSS("dark");
} else {
console.log("Light Theme Chosen by User");
console.log("Dark Theme Enabled - ",
nativeTheme.shouldUseDarkColors);
loadCSS("light");
}
});
var dark = document.getElementById("dark");
dark.addEventListener("click", () => {
nativeTheme.themeSource = "dark";
});
var light = document.getElementById("light");
light.addEventListener("click", () => {
nativeTheme.themeSource = "light";
});
index.js :在该文件中添加以下代码段。
Javascript
const electron = require("electron");
// Importing the nativeTheme module
// using Electron remote
const nativeTheme = electron.remote.nativeTheme;
const path = require("path");
console.log("By Default, Dark Theme Enabled - ",
nativeTheme.shouldUseDarkColors);
console.log("High Contrast Colors - ",
nativeTheme.shouldUseHighContrastColors);
console.log("Inverted Colors - ",
nativeTheme.shouldUseInvertedColorScheme);
nativeTheme.on("updated", () => {
console.log("Updated Event has been Emitted");
if (nativeTheme.shouldUseDarkColors) {
console.log("Dark Theme Chosen by User");
} else {
console.log("Light Theme Chosen by User");
}
});
var dark = document.getElementById("dark");
dark.addEventListener("click", () => {
nativeTheme.themeSource = "dark";
});
var light = document.getElementById("light");
light.addEventListener("click", () => {
nativeTheme.themeSource = "light";
});
代码中用到的nativeTheme模块的所有Instance Properties的详细解释如下:
- nativeTheme.shouldUseDarkColors此实例属性是只读属性。此属性返回一个布尔值,说明系统操作系统或 Chromium 当前是否启用了暗模式,或者指示它显示暗主题UI 。要修改此属性(更改应用程序的主题),我们需要使用nativeTheme.themeSource Instance 属性。
- nativeTheme.shouldUseHighContrastColors此实例属性是只读属性。此实例属性仅在Windows和macOS上受支持。此属性返回一个布尔值,说明系统操作系统或 Chromium 当前是否启用了高对比度模式,或者被指示显示高对比度主题UI 。不能使用nativeTheme模块直接从代码修改此属性。要修改此属性,用户需要从系统设置中启用高对比度UI 。
- nativeTheme.shouldUseInvertedColorScheme此实例属性是只读属性。此实例属性仅在Windows和macOS上受支持。此属性返回一个布尔值,说明系统操作系统或 Chromium 当前是否启用了反转配色方案,或者指示它在UI 中使用反转配色方案。不能使用nativeTheme模块直接从代码修改此属性。要修改此属性,用户需要从系统设置中启用反转配色方案。
- nativeTheme.themeSource此实例属性用于更改应用程序的主题。此属性可以在执行期间动态更改。此字符串属性用于覆盖和取代 Chromium 根据系统主题选择在内部使用的值(指定主题)。此属性可以采用以下字符串值之一:
- system将此实例属性设置为system将删除覆盖值并将所有内容重置为操作系统默认值。这意味着如果 System 主题启用了暗模式,则 Chromium 将自动将此作为其默认主题并将其应用于 Electron 应用程序。当系统主题启用了灯光模式时,同样的情况也适用。默认情况下, themeSource属性的值为system 。该值与系统的默认操作系统模式一致。
- 暗将此实例属性设置为暗将对应用程序产生以下影响。该值与系统的暗模式一致。
- nativeTheme.shouldUseDarkColors Instance 属性将设置为true 。
- 在Linux和Windows上由 Electron 应用程序呈现的任何UI ,包括上下文菜单、开发工具等,都将使用深色主题UI 。输出中也证明了这一点。系统在macOS上呈现的任何UI ,包括菜单、窗口框架等,都将使用深色主题UI 。
- 首选颜色方案CSS 查询将匹配暗模式。
- Updated Instance 事件将被发出,如代码所示。输出中也演示了相同的内容。
- light将此 Instance 属性设置为light将对应用程序产生以下影响。该值与系统的Light模式一致。
- nativeTheme.shouldUseDarkColors Instance 属性将设置为false 。
- 在Linux和Windows上由 Electron 应用程序呈现的任何UI ,包括上下文菜单、开发工具等,都将使用浅色主题UI 。输出中也证明了这一点。系统在macOS上呈现的任何UI ,包括菜单、窗口框架等,都将使用浅色主题UI 。
- 首选颜色方案CSS 查询将匹配灯光模式。
- Updated Instance 事件将被发出,如代码所示。输出中也演示了相同的内容。
代码中使用的nativeTheme模块的Instance Event的详细解释如下:
- 更新:事件当底层原生 Chromium 主题中的某些属性发生更改时,会发出此实例事件。这意味着任何只读实例属性的值已更改。如上所述,可以通过更改nativeTheme.themeSource属性的值来更改nativeTheme.shouldUseDarkColors属性的值。发出此事件后,我们需要手动检查哪个Readonly属性已更改,因为此 Instance 事件不返回任何 Promise/Callback。
至此,我们应该可以成功的从上面的代码中确定并更改Electron应用的Native Theme了。
输出:
注意:在上面的输出中,系统操作系统主题默认设置为暗模式,因此nativeTheme.shouldUseDarkColors实例属性返回true 。此外,在重新加载应用程序时,对主题所做的任何更改都将恢复为默认的系统操作系统主题,因为我们没有在应用程序的本地存储中持久化nativeTheme.themeSource Instance 属性的值。
在我们使应用程序成功适应原生系统主题后,我们需要为应用程序动态应用与该主题兼容的相应CSS 。这很重要,因为样式的某些属性不能同时应用于这两个主题。例如,我们不能对暗模式和亮模式使用相同的字体颜色。下面的教程将演示如何根据应用的主题动态注入相应的 CSS。
- dark.css :在该文件中添加以下代码段。
body {
background-color: darkgray;
color: white;
}
- light.css :在该文件中添加以下代码段。
body {
background-color: lightgray;
color: black;
}
index.js :对此文件进行以下更改。函数loadCSS(load)根据传递给它的亮或暗字符串值动态地将 CSS 插入到HTML DOM 结构中。我们只是使用appendChild方法将另一个带有相应 CSS 文件和属性的链接标记附加到index.html文档的 head 标记。
Javascript
const electron = require("electron");
// Importing the nativeTheme module
// using Electron remote
const nativeTheme = electron.remote.nativeTheme;
const path = require("path");
console.log("By Default, Dark Theme Enabled - ",
nativeTheme.shouldUseDarkColors);
console.log("High Contrast Colors - ",
nativeTheme.shouldUseHighContrastColors);
console.log("Inverted Colors - ",
nativeTheme.shouldUseInvertedColorScheme);
function loadCSS(load) {
var head = document.getElementsByTagName("head")[0];
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = path.join(__dirname, "../assets/"
+ load + ".css");
head.appendChild(link);
}
nativeTheme.on("updated", () => {
console.log("Updated Event has been Emitted");
if (nativeTheme.shouldUseDarkColors) {
console.log("Dark Theme Chosen by User");
console.log("Dark Theme Enabled - ",
nativeTheme.shouldUseDarkColors);
loadCSS("dark");
} else {
console.log("Light Theme Chosen by User");
console.log("Dark Theme Enabled - ",
nativeTheme.shouldUseDarkColors);
loadCSS("light");
}
});
var dark = document.getElementById("dark");
dark.addEventListener("click", () => {
nativeTheme.themeSource = "dark";
});
var light = document.getElementById("light");
light.addEventListener("click", () => {
nativeTheme.themeSource = "light";
});
输出:当动态指定 CSS 文件时,我们不会删除之前的 CSS 文件(如果有),因此应用于应用程序的样式包括这两个 CSS 文件。如果我们在任何一个 CSS 文件中遗漏了一个属性,它仍然会在更改主题时应用于应用程序。因此,我们可以先删除链接标签,然后使用 JS 动态重新附加它,或者通过制作相同的副本并简单地更改值来覆盖先前 CSS 文件的所有属性。