深色模式¶
概述¶
自动更新原生界面¶
"原生界面"包括文件选择器、窗口边框、对话框、上下文菜单等——凡是 UI 来自操作系统而非应用本身的部分。默认行为是采用操作系统的自动主题。
自动更新您自己的界面¶
如果您的应用自带深色模式,则应跟随系统的深色模式设置同步开启或关闭。您可以通过 prefers-color-scheme CSS 媒体查询来实现。
手动更新您自己的界面¶
如果您想手动在浅色/深色模式之间切换,可以通过设置 nativeTheme 模块的
themeSource
属性来实现。该属性的值会传播到您的渲染进程。任何与 prefers-color-scheme 相关的 CSS 规则都会相应更新。
macOS 设置¶
在 macOS 10.14 Mojave 中,Apple 为所有 macOS 电脑引入了新的系统级深色模式。如果您的 Electron 应用带有深色模式,您可以使用 the nativeTheme API 让它跟随系统级的深色模式设置。
在 macOS 10.15 Catalina 中,Apple 为所有 macOS 电脑引入了新的"自动"深色模式选项。为了让 nativeTheme.shouldUseDarkColors 和 Tray API 在 Catalina 的此模式下正常工作,您需要使用 Electron >=7.0.0,或为旧版本在 Info.plist 文件中将 NSRequiresAquaSystemAppearance 设置为 false。Electron Packager 和 Electron Forge 都有 darwinDarkModeSupport 选项,可在应用构建时自动完成 Info.plist 的更改。
如果您在使用 Electron > 8.0.0 时希望退出此功能,则必须将 Info.plist 文件中的 NSRequiresAquaSystemAppearance 键设置为 true。请注意,由于使用了 macOS 10.14 SDK,Electron 8.0.0 及以上版本不允许您退出此主题。
示例¶
此示例演示了一个从 nativeTheme 获取主题颜色的 Electron 应用。此外,它还提供了使用 IPC 通道的主题切换和重置控件。
```fiddle docs/fiddles/features/dark-mode
### 这是如何工作的? {#how-does-this-work}
从 `index.html` 文件开始:
```html title='index.html'
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Current theme source: <strong id="theme-source">System</strong></p>
<button id="toggle-dark-mode">Toggle Dark Mode</button>
<button id="reset-to-system">Reset to System Theme</button>
<script src="renderer.js"></script>
</body>
</html>
以及 styles.css 文件:
@media (prefers-color-scheme: dark) {
body { background: #333; color: white; }
}
@media (prefers-color-scheme: light) {
body { background: #ddd; color: black; }
}
该示例渲染了一个包含几个元素的 HTML 页面。<strong id="theme-source"> 元素显示当前选择的主题,两个 <button> 元素是控件。CSS 文件使用 prefers-color-scheme 媒体查询来设置 <body> 元素的背景和文本颜色。
preload.js 脚本向 window 对象添加了一个名为 darkMode 的新 API。该 API 向渲染进程暴露了两个 IPC 通道:'dark-mode:toggle' 和 'dark-mode:system'。它还分配了两个方法 toggle 和 system,将消息从渲染进程传递到主进程。
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('darkMode', {
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
system: () => ipcRenderer.invoke('dark-mode:system')
})
现在,渲染进程可以安全地与主进程通信,并对 nativeTheme 对象执行必要的修改。
renderer.js 文件负责控制 <button> 的功能。
```js title='renderer.js' @ts-expect-error=[2,7] document.getElementById('toggle-dark-mode').addEventListener('click', async () => { const isDarkMode = await window.darkMode.toggle() document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light' })
document.getElementById('reset-to-system').addEventListener('click', async () => { await window.darkMode.system() document.getElementById('theme-source').innerHTML = 'System' })
通过使用 `addEventListener`,`renderer.js` 文件为每个按钮元素添加了 `'click'` [事件监听器][event-listeners]。每个事件监听器处理程序都会调用相应的 `window.darkMode` API 方法。
最后,`main.js` 文件代表主进程,并包含实际的 `nativeTheme` API。
```js
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
const path = require('node:path')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('index.html')
ipcMain.handle('dark-mode:toggle', () => {
if (nativeTheme.shouldUseDarkColors) {
nativeTheme.themeSource = 'light'
} else {
nativeTheme.themeSource = 'dark'
}
return nativeTheme.shouldUseDarkColors
})
ipcMain.handle('dark-mode:system', () => {
nativeTheme.themeSource = 'system'
})
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
ipcMain.handle 方法是主进程响应 HTML 页面上按钮点击事件的方式。
该 'dark-mode:toggle' IPC 通道处理方法会检查 shouldUseDarkColors 布尔属性,
设置对应的 themeSource,然后返回当前的 shouldUseDarkColors 属性。
回顾该 IPC 通道的渲染进程事件监听器,此处理方法的返回值被用于为 <strong id='theme-source'> 元素分配正确的文本。
该 'dark-mode:system' IPC 通道处理方法会将字符串 'system' 赋值给 themeSource,
并且不返回任何值。这也与相应的渲染进程事件监听器一致,因为该方法被 await 且预期没有返回值。
使用 Electron Fiddle 运行示例,然后单击 “Toggle Dark Mode” 按钮;应用应开始在浅色和深色背景颜色之间交替。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 el/electron