个人技术站点JASONWU

Keep Coding


  • 主页

  • 文章

  • 搜索

Electron 悬浮窗

新建: 2021-06-03 编辑: 2021-06-22   |   分类: JavaScript   | 字数: 965 字

创建支持内容切换及拖拽的悬浮窗,包含完整目录结构及示例代码。

目录结构

Text
 1.
 2├── main
 3│   └── floating-window.js
 4├── renderer
 5│   ├── img
 6│   │   └── logo.png
 7│   ├── floating-window.html
 8│   └── style.css
 9├── sass
10│   ├── abstracts
11│   │   ├── _helpers.scss
12│   │   ├── _mixins.scss
13│   │   └── _variables.scss
14│   │── base
15│   │   └── _base.scss
16│   │── pages
17│   │   └── _floating-window.scss
18│   └── main.scss
19├── main.js
20├── package.json
21└── package-lock.json

NPM

package.json

Json
 1{
 2  "name": "floating-window",
 3  "version": "1.0.0",
 4  "description": "悬浮窗",
 5  "main": "main.js",
 6  "scripts": {
 7    "start": "electron .",
 8    "watch": "nodemon --exec electron .",
 9    "compile:sass": "sass --no-source-map --watch sass/main.scss:renderer/style.css"
10  },
11  "keywords": [],
12  "author": "",
13  "license": "ISC",
14  "devDependencies": {
15    "electron": "^13.1.1",
16    "nodemon": "^2.0.7",
17    "sass": "^1.34.1"
18  }
19}

主进程

main.js

JavaScript
 1const { app, BrowserWindow } = require('electron');
 2
 3const FloatingWindow = require('./main/floating-window');
 4
 5class Main {
 6  floWin = new FloatingWindow();
 7
 8  constructor() {
 9    app.whenReady().then(() => {
10      this._createWindow();
11      this._forMacOs();
12    });
13  }
14
15  _createWindow() {
16    this.floWin.resetWindow();
17  }
18
19  _forMacOs() {
20    app.on('activate', () => {
21      if (BrowserWindow.getAllWindows().length === 0) this._createWindow();
22    });
23
24    app.on('window-all-closed', () => {
25      if (process.platform !== 'darwin') app.quit();
26    });
27  }
28}
29
30new Main();

main/floating-window.js

JavaScript
 1const { BrowserWindow, ipcMain } = require('electron');
 2
 3class FloatingWindow {
 4  _width = 36;
 5  _height = 36;
 6  _min = true; // 是否是最小化的窗口尺寸
 7  _maxWidth = 180;
 8  _maxHeight = 180;
 9  _regIpc = false;
10
11  win;
12
13  resetWindow() {
14    if (this.win && !this.win.isDestroyed()) return;
15
16    this._createWindow();
17  }
18
19  _createWindow() {
20    this.win = new BrowserWindow({
21      width: this._width,
22      height: this._height,
23      alwaysOnTop: true,
24      hasShadow: false,
25      transparent: true,
26      frame: false,
27      resizable: false,
28      skipTaskbar: true,
29      
30      // 可避免一些在 Windows 中的 Bug,比如快捷键窗口切换时不再位于最上层等
31      type: 'toolbar', 
32
33      // 将窗口背景设置与页面背景一致,避免闪烁
34      backgroundColor: '#2d2a2e',
35
36      webPreferences: {
37        nodeIntegration: true,
38        contextIsolation: false
39      }
40    });
41
42    // this.win.webContents.openDevTools();
43
44    this.win.loadFile('renderer/floating-window.html').then(() => {
45      if (this._regIpc) return;
46      
47      this._regIpc = true;
48      this._toggleWindowSize();
49    });
50  }
51
52  _toggleWindowSize() {
53    ipcMain.handle('toggle-floating-window', async () => {
54      this._min = !this._min;
55
56      if (this._min) {
57        this.win.setSize(this._width, this._height);
58      } else {
59        this.win.setSize(this._maxWidth, this._maxHeight);
60      }
61
62      return this._min;
63    });
64  }
65}
66
67module.exports = FloatingWindow;

渲染器进程

renderer/floating-window.html

HTML
 1<!DOCTYPE html>
 2<html>
 3  <head>
 4    <meta charset="UTF-8">
 5    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'">
 6    <link rel="stylesheet" href="style.css">
 7    <title>悬浮窗</title>
 8  </head>
 9  <body style="-webkit-app-region: drag">
10    <div class="floating-window">
11      <img class="floating-window__logo" src="img/logo.png">
12      <div class="floating-window__tip hidden">双点切换</div>
13    </div>
14
15    <script>
16      const { ipcRenderer } = require('electron');
17
18      class Main {
19        containerEl = document.querySelector('.floating-window');
20        logoEl = document.querySelector('.floating-window__logo');
21        tipEl = document.querySelector('.floating-window__tip');
22
23        constructor() {
24          this._handleDoubleClick();
25        }
26
27        _handleDoubleClick() {
28          this.containerEl.addEventListener('dblclick', () => {
29            this._hideAll();
30
31            ipcRenderer.invoke('toggle-floating-window').then(min => {
32              if (min) {
33                this.logoEl.classList.remove('hidden');
34              } else {
35                this.tipEl.classList.remove('hidden');
36              }
37            });
38          });
39        }
40
41        _hideAll() {
42          !this.logoEl.classList.contains('hidden') && this.logoEl.classList.add('hidden');
43
44          !this.tipEl.classList.contains('hidden') && this.tipEl.classList.add('hidden');
45        }
46      }
47
48      new Main();
49    </script>
50  </body>
51</html>

样式(Sass)

sass/abstracts/_helpers.scss

Scss
1.hidden {
2  display: none !important;
3}

sass/abstracts/_mixins.scss

Scss
1@mixin no-drag {
2  -webkit-user-drag: none;
3}
4
5@mixin no-selection {
6  user-select: none;
7}

sass/abstracts/_variables.scss

Scss
1$color-primary: #2d2a2e;

sass/base/_base.scss

Scss
 1@use '../abstracts/mixins' as *;
 2
 3*,
 4*::after,
 5*::before {
 6  margin: 0;
 7  padding: 0;
 8  box-sizing: inherit;
 9}
10
11html {
12  font-size: 10px / 16px * 100%; // 定义 1rem = 10px
13}
14
15body {
16  font: caption; // 系统字体
17  font-size: 1.6rem;
18  box-sizing: border-box;
19}
20
21// 不需要轮廓线
22input:focus,
23select:focus,
24textarea:focus,
25button:focus {
26  outline: none;
27}
28
29img {
30  // 图片不可拖拽
31  @include no-drag;
32}

sass/pages/_floating-window.scss

Scss
 1@use '../abstracts/variables' as *;
 2@use '../abstracts/mixins' as *;
 3
 4.floating-window {
 5  height: 100vh;
 6  background-color: $color-primary;
 7  
 8  display: flex;
 9  justify-content: center;
10  align-items: center;
11
12  &__logo {
13    display: inline-block;
14    width: 100%;
15  }
16
17  &__tip {
18    color: white;
19    @include no-selection;
20  }
21}

sass/main.scss

Scss
1@use 'abstracts/helpers';
2
3@use 'base/base';
4
5@use 'pages/floating-window';
#electron# #sass#

文章:Electron 悬浮窗

链接:https://www.wuxianjie.net/posts/electron-floating-window/

作者:吴仙杰

文章: 本博客文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议,转载请注明出处!

ES6 模块
Sass 7-1 Pattern
  • 文章目录
  • 站点概览
吴仙杰

吴仙杰

🔍 Ctrl+K / ⌘K

27 文章
9 分类
25 标签
邮箱 GitHub
  • 目录结构
  • NPM
  • 主进程
  • 渲染器进程
  • 样式(Sass)
© 2021-2025 吴仙杰 保留所有权利 All Rights Reserved
浙公网安备 33010302003726号 浙ICP备2021017187号-1
0%