electron-drag-plus 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,378 +1,291 @@
1
- # electron-drag-plus
1
+ # Electron Drag Plus
2
2
 
3
- 增强版Electron窗口拖拽库,解决窗口抖动、不同分辨率/缩放导致的闪屏问题,并支持拖拽区域忽略鼠标事件。
3
+ 一个极简的 Electron 窗口拖拽增强库,通过简单的 API 实现自定义标题栏的窗口拖拽功能,并内置窗口防抖优化。
4
4
 
5
- ## 功能特性
5
+ ## 特性
6
6
 
7
- - 解决Electron原生拖拽可能出现的窗口抖动问题
8
- - ✅ 修复不同分辨率和显示器缩放导致的拖拽闪屏问题
9
- - ✅ 智能识别并忽略拖拽区域内的交互元素(按钮、输入框等)
10
- - 支持自定义忽略元素选择器
11
- - ✅ 提供平滑拖拽体验
12
- - ✅ 支持高DPI显示器
13
- - ✅ 简单易用的API
14
- - ✅ TypeScript支持
7
+ - **极简 API**:主进程仅需一个方法,渲染进程仅需两个方法
8
+ - **窗口防抖**:内置窗口拖拽时的防抖优化,解决拖拽时窗口大小抖动问题
9
+ - **自动处理**:自动识别并排除交互元素,避免交互冲突
10
+ - **TypeScript 支持**:提供完整的类型定义
11
+ - **安全可靠**:内置错误处理和延迟初始化,确保在各种环境下稳定运行
15
12
 
16
13
  ## 安装
17
14
 
18
15
  ```bash
16
+ # 使用 npm
19
17
  npm install electron-drag-plus
20
- # 或
18
+
19
+ # 使用 yarn
21
20
  yarn add electron-drag-plus
22
- # 或
21
+
22
+ # 使用 pnpm
23
23
  pnpm add electron-drag-plus
24
24
  ```
25
25
 
26
- ## 使用方法
27
-
28
- ### 主进程使用
29
-
30
- ```javascript
31
- // 在主进程中
32
- import { app, BrowserWindow } from 'electron';
33
- import { DragPlus } from 'electron-drag-plus';
34
-
35
- // 创建窗口时初始化拖拽增强
36
- function createWindow() {
37
- const win = new BrowserWindow({
38
- width: 800,
39
- height: 600,
40
- frame: false, // 无边框窗口
41
- webPreferences: {
42
- nodeIntegration: true,
43
- contextIsolation: false
44
- }
45
- });
46
-
47
- // 初始化拖拽增强
48
- const dragPlus = new DragPlus(win, {
49
- ignoreSelectors: ['.no-drag', '#close-button'],
50
- enableHighDPI: true,
51
- smoothDrag: true
52
- });
26
+ ## API 文档
53
27
 
54
- // 手动启用特定元素的拖拽
55
- dragPlus.enableDrag('.title-bar');
56
-
57
- // 手动禁用特定元素的拖拽
58
- dragPlus.disableDrag('.window-controls');
28
+ ### 主进程 API
59
29
 
60
- win.loadFile('index.html');
61
- }
30
+ #### `initializeDragPlus(window)`
62
31
 
63
- app.whenReady().then(createWindow);
64
- ```
32
+ 初始化窗口拖拽功能。
65
33
 
66
- ### 渲染进程使用
34
+ **参数:**
35
+ - `window: BrowserWindow` - Electron 窗口实例
67
36
 
68
- ```javascript
69
- // 在渲染进程中
70
- import { initDragPlus, setupDraggableArea, enableDrag, disableDrag } from 'electron-drag-plus/dist/renderer';
71
-
72
- // 初始化拖拽功能
73
- initDragPlus({
74
- ignoreSelectors: ['.no-drag', '.button'],
75
- enableHighDPI: true,
76
- smoothDrag: true
37
+ **示例:**
38
+ ```typescript
39
+ import { BrowserWindow } from 'electron';
40
+ import { initializeDragPlus } from 'electron-drag-plus';
41
+
42
+ // 创建窗口
43
+ const mainWindow = new BrowserWindow({
44
+ width: 800,
45
+ height: 600,
46
+ frame: false, // 无边框窗口
47
+ webPreferences: {
48
+ contextIsolation: true,
49
+ nodeIntegration: false,
50
+ preload: path.join(__dirname, 'preload.js')
51
+ }
77
52
  });
78
53
 
79
- // 方法1: 设置整个区域为可拖拽,并自动忽略交互元素
80
- setupDraggableArea('.title-bar');
81
-
82
- // 方法2: 手动为元素启用拖拽
83
- const header = document.getElementById('app-header');
84
- enableDrag(header, { ignoreChildren: true });
85
-
86
- // 方法3: 手动为元素禁用拖拽
87
- const closeButton = document.getElementById('close-btn');
88
- disableDrag(closeButton);
54
+ // 初始化拖拽功能 - 无需key参数
55
+ initializeDragPlus(mainWindow);
89
56
  ```
90
57
 
91
- ### 在现代框架中使用
92
-
93
- #### Vue 3 (Composition API)
94
-
95
- ```vue
96
- <template>
97
- <div class="app">
98
- <div ref="titleBar" class="title-bar">
99
- <h1>应用标题</h1>
100
- <div class="window-controls">
101
- <button @click="minimize">-</button>
102
- <button @click="maximize">□</button>
103
- <button @click="close">×</button>
104
- </div>
105
- </div>
106
- <div class="content">
107
- <!-- 应用内容 -->
108
- </div>
109
- </div>
110
- </template>
111
-
112
- <script setup>
113
- import { ref, onMounted } from 'vue';
114
- import { setupDraggableArea } from 'electron-drag-plus/dist/renderer';
115
-
116
- // 使用 ref 获取DOM元素
117
- const titleBar = ref(null);
58
+ ### 渲染进程 API
118
59
 
119
- // 窗口控制函数
120
- const minimize = () => {
121
- window.electron.ipcRenderer.send('window:minimize');
122
- };
60
+ #### `enableWindowDrag(element)`
123
61
 
124
- const maximize = () => {
125
- window.electron.ipcRenderer.send('window:maximize');
126
- };
62
+ 启用指定元素的窗口拖拽功能。
127
63
 
128
- const close = () => {
129
- window.electron.ipcRenderer.send('window:close');
130
- };
64
+ **参数:**
65
+ - `element: HTMLElement | string` - DOM 元素或 CSS 选择器
131
66
 
132
- // 组件挂载后设置拖拽区域
133
- onMounted(() => {
134
- if (titleBar.value) {
135
- setupDraggableArea(titleBar.value);
136
- }
137
- });
138
- </script>
139
-
140
- <style scoped>
141
- .title-bar {
142
- height: 40px;
143
- background: #333;
144
- color: white;
145
- display: flex;
146
- justify-content: space-between;
147
- align-items: center;
148
- padding: 0 10px;
149
- user-select: none;
150
- }
67
+ **示例:**
68
+ ```typescript
69
+ import { enableWindowDrag } from 'electron-drag-plus/renderer';
151
70
 
152
- .window-controls button {
153
- width: 30px;
154
- height: 30px;
155
- background: none;
156
- border: none;
157
- color: white;
158
- cursor: pointer;
159
- }
71
+ // 使用 CSS 选择器
72
+ enableWindowDrag('#title-bar');
160
73
 
161
- /* 确保按钮不会触发拖拽 */
162
- .window-controls button {
163
- -webkit-app-region: no-drag;
74
+ // 或使用 DOM 元素
75
+ const titleBar = document.getElementById('title-bar');
76
+ if (titleBar instanceof HTMLElement) {
77
+ enableWindowDrag(titleBar);
164
78
  }
165
- </style>
166
79
  ```
167
80
 
168
- #### Vue 3 组合式函数封装
81
+ #### `disableWindowDrag(element)`
169
82
 
170
- ```vue
171
- <script setup>
172
- import { ref, onMounted, onUnmounted } from 'vue';
173
- import { setupDraggableArea, destroyDragPlus } from 'electron-drag-plus/dist/renderer';
83
+ 禁用指定元素的窗口拖拽功能。
174
84
 
175
- // 创建可拖拽标题栏组件
176
- const titleBar = ref(null);
85
+ **参数:**
86
+ - `element: HTMLElement | string` - DOM 元素或 CSS 选择器
177
87
 
178
- // 组件挂载时初始化拖拽
179
- onMounted(() => {
180
- if (titleBar.value) {
181
- setupDraggableArea(titleBar.value);
182
- }
183
- });
184
-
185
- // 组件卸载时清理
186
- onUnmounted(() => {
187
- // 如果需要全局清理
188
- // destroyDragPlus();
189
- });
190
- </script>
191
- ```
192
-
193
- #### React
194
-
195
- ```jsx
196
- import React, { useEffect, useRef } from 'react';
197
- import { setupDraggableArea } from 'electron-drag-plus/dist/renderer';
88
+ **示例:**
89
+ ```typescript
90
+ import { disableWindowDrag } from 'electron-drag-plus/renderer';
198
91
 
199
- function App() {
200
- const titleBarRef = useRef(null);
201
-
202
- useEffect(() => {
203
- // 设置标题栏为可拖拽区域
204
- if (titleBarRef.current) {
205
- setupDraggableArea(titleBarRef.current);
206
- }
207
- }, []);
208
-
209
- const minimize = () => {
210
- window.electron.ipcRenderer.send('window:minimize');
211
- };
212
-
213
- const maximize = () => {
214
- window.electron.ipcRenderer.send('window:maximize');
215
- };
216
-
217
- const close = () => {
218
- window.electron.ipcRenderer.send('window:close');
219
- };
220
-
221
- return (
222
- <div className="app">
223
- <div ref={titleBarRef} className="title-bar">
224
- <h1>应用标题</h1>
225
- <div className="window-controls">
226
- <button onClick={minimize}>-</button>
227
- <button onClick={maximize}>□</button>
228
- <button onClick={close}>×</button>
229
- </div>
230
- </div>
231
- <div className="content">
232
- {/* 应用内容 */}
233
- </div>
234
- </div>
235
- );
92
+ // 禁用按钮的拖拽,使其可以正常点击
93
+ const closeButton = document.getElementById('close-button');
94
+ if (closeButton instanceof HTMLElement) {
95
+ disableWindowDrag(closeButton);
236
96
  }
237
-
238
- export default App;
239
97
  ```
240
98
 
241
- #### React 自定义Hook
99
+ ## 完整示例
100
+
101
+ ### 主进程示例 (main.js)
242
102
 
243
- ```jsx
244
- import { useEffect } from 'react';
245
- import { setupDraggableArea } from 'electron-drag-plus/dist/renderer';
103
+ ```javascript
104
+ const { app, BrowserWindow } = require('electron');
105
+ const path = require('path');
106
+ const { initializeDragPlus } = require('electron-drag-plus');
246
107
 
247
- // 创建一个自定义Hook来管理拖拽区域
248
- export function useDraggable(ref) {
249
- useEffect(() => {
250
- if (ref.current) {
251
- setupDraggableArea(ref.current);
108
+ function createWindow() {
109
+ const mainWindow = new BrowserWindow({
110
+ width: 800,
111
+ height: 600,
112
+ frame: false, // 无边框窗口
113
+ webPreferences: {
114
+ preload: path.join(__dirname, 'preload.js'),
115
+ contextIsolation: true,
116
+ nodeIntegration: false
252
117
  }
253
- }, [ref]);
254
- }
118
+ });
255
119
 
256
- // 使用示例
257
- function DraggableTitleBar() {
258
- const titleBarRef = useRef(null);
259
- useDraggable(titleBarRef);
260
-
261
- return (
262
- <div ref={titleBarRef} className="title-bar">
263
- <h1>拖拽标题栏</h1>
264
- </div>
265
- );
120
+ // 初始化拖拽功能 - 简化版,无需key参数
121
+ initializeDragPlus(mainWindow);
122
+
123
+ // 加载页面
124
+ mainWindow.loadFile('index.html');
266
125
  }
267
126
 
268
- ## API 参考
127
+ app.whenReady().then(() => {
128
+ createWindow();
269
129
 
270
- ### 主进程 API
271
-
272
- #### DragPlus 类
130
+ app.on('activate', () => {
131
+ if (BrowserWindow.getAllWindows().length === 0) createWindow();
132
+ });
133
+ });
273
134
 
274
- ```typescript
275
- constructor(window: BrowserWindow, options?: DragPlusOptions);
135
+ app.on('window-all-closed', () => {
136
+ if (process.platform !== 'darwin') app.quit();
137
+ });
276
138
  ```
277
139
 
278
- **参数**:
279
- - `window`: Electron BrowserWindow 实例
280
- - `options`: 配置选项
281
- - `ignoreSelectors`: 忽略的CSS选择器数组
282
- - `enableHighDPI`: 是否启用高DPI支持
283
- - `smoothDrag`: 是否启用平滑拖拽
284
-
285
- **方法**:
286
-
287
- - `enableDrag(elementSelector: string)`: 为指定选择器的元素启用拖拽
288
- - `disableDrag(elementSelector: string)`: 为指定选择器的元素禁用拖拽
289
- - `updateOptions(newOptions: Partial<DragPlusOptions>)`: 更新配置选项
290
- - `static getInstance(webContentsId: number)`: 获取特定webContents的DragPlus实例
140
+ ### 预加载脚本 (preload.js)
291
141
 
292
- ### 渲染进程 API
293
-
294
- #### 初始化
142
+ ```javascript
143
+ // 预加载脚本,用于暴露必要的API给渲染进程
144
+ const { contextBridge, ipcRenderer } = require('electron');
295
145
 
296
- ```typescript
297
- function initDragPlus(options?: RendererDragOptions): void;
146
+ contextBridge.exposeInMainWorld('electron', {
147
+ // 这里可以暴露其他必要的API
148
+ });
298
149
  ```
299
150
 
300
- **参数**:
301
- - `options`: 配置选项,与主进程相同
302
-
303
- #### 拖拽管理
151
+ ### 渲染进程示例 (renderer.js)
304
152
 
305
- ```typescript
306
- // 设置可拖拽区域,自动忽略交互元素
307
- function setupDraggableArea(container: HTMLElement | string): void;
153
+ ```javascript
154
+ import { enableWindowDrag, disableWindowDrag } from 'electron-drag-plus/renderer';
308
155
 
309
- // 为元素启用拖拽
310
- function enableDrag(element: HTMLElement | string, options?: { ignoreChildren?: boolean }): void;
156
+ // 启用标题栏拖拽功能 - 简化版,无需key参数
157
+ const titleBar = document.getElementById('title-bar');
158
+ if (titleBar) {
159
+ enableWindowDrag(titleBar);
160
+ }
311
161
 
312
- // 为元素禁用拖拽
313
- function disableDrag(element: HTMLElement | string): void;
162
+ // 禁用控制按钮的拖拽
163
+ const minimizeButton = document.getElementById('minimize-button');
164
+ const maximizeButton = document.getElementById('maximize-button');
165
+ const closeButton = document.getElementById('close-button');
314
166
 
315
- // 更新配置选项
316
- function updateDragPlusOptions(options: Partial<RendererDragOptions>): void;
167
+ if (minimizeButton) disableWindowDrag(minimizeButton);
168
+ if (maximizeButton) disableWindowDrag(maximizeButton);
169
+ if (closeButton) disableWindowDrag(closeButton);
317
170
 
318
- // 销毁拖拽管理器
319
- function destroyDragPlus(): void;
171
+ // 添加窗口控制功能
172
+ closeButton?.addEventListener('click', () => {
173
+ window.close();
174
+ });
320
175
  ```
321
176
 
322
- ## 常见问题
323
-
324
- ### 1. 拖拽区域内的按钮无法点击
325
-
326
- 确保为按钮元素设置了`no-drag`样式:
327
-
328
- ```css
329
- .button {
330
- -webkit-app-region: no-drag;
331
- }
177
+ ### HTML 示例
178
+
179
+ ```html
180
+ <!DOCTYPE html>
181
+ <html>
182
+ <head>
183
+ <meta charset="UTF-8">
184
+ <title>Electron Drag Plus Example</title>
185
+ <style>
186
+ body {
187
+ margin: 0;
188
+ font-family: Arial, sans-serif;
189
+ }
190
+
191
+ #title-bar {
192
+ height: 32px;
193
+ background-color: #252525;
194
+ color: white;
195
+ display: flex;
196
+ align-items: center;
197
+ justify-content: space-between;
198
+ padding: 0 8px;
199
+ }
200
+
201
+ .title {
202
+ font-size: 14px;
203
+ }
204
+
205
+ .controls {
206
+ display: flex;
207
+ gap: 8px;
208
+ }
209
+
210
+ button {
211
+ width: 24px;
212
+ height: 24px;
213
+ border: none;
214
+ border-radius: 4px;
215
+ display: flex;
216
+ align-items: center;
217
+ justify-content: center;
218
+ cursor: pointer;
219
+ }
220
+
221
+ #close-button {
222
+ background-color: #ff5f56;
223
+ }
224
+
225
+ #minimize-button {
226
+ background-color: #ffbd2e;
227
+ }
228
+
229
+ #maximize-button {
230
+ background-color: #27c93f;
231
+ }
232
+
233
+ #content {
234
+ padding: 16px;
235
+ }
236
+ </style>
237
+ </head>
238
+ <body>
239
+ <div id="title-bar">
240
+ <div class="title">Electron Drag Plus Example</div>
241
+ <div class="controls">
242
+ <button id="minimize-button"></button>
243
+ <button id="maximize-button"></button>
244
+ <button id="close-button"></button>
245
+ </div>
246
+ </div>
247
+ <div id="content">
248
+ <h1>自定义标题栏示例</h1>
249
+ <p>拖动上方标题栏可以移动窗口</p>
250
+ </div>
251
+
252
+ <script src="renderer.js"></script>
253
+ </body>
254
+ </html>
332
255
  ```
333
256
 
334
- 或者使用`setupDraggableArea`函数,它会自动为交互元素添加`no-drag`。
257
+ ## 窗口防抖机制
335
258
 
336
- ### 2. 在高DPI显示器上拖拽仍然有问题
259
+ 该库内置了窗口防抖优化,解决了 Electron 拖拽时窗口大小抖动的问题。实现方式包括:
337
260
 
338
- 确保在创建`DragPlus`实例时启用了高DPI支持:
261
+ 1. **临时禁用窗口调整大小**:拖拽开始时保存窗口原始可调整大小状态,并临时禁用调整大小功能
262
+ 2. **强制写回窗口尺寸**:拖拽过程中强制保持窗口尺寸不变
263
+ 3. **恢复原始状态**:拖拽结束后恢复窗口原始的可调整大小状态
339
264
 
340
- ```javascript
341
- const dragPlus = new DragPlus(win, {
342
- enableHighDPI: true
343
- });
344
- ```
265
+ ## 注意事项
345
266
 
346
- ### 3. 窗口拖拽时仍然有抖动
267
+ 1. **初始化时机**:确保在窗口创建后、加载页面之前初始化拖拽功能
347
268
 
348
- 尝试调整`smoothDrag`选项,或者检查是否有其他事件监听器干扰拖拽行为:
269
+ 2. **WebPreferences 配置**:在创建窗口时,需要正确配置 webPreferences:
270
+ - 建议启用 `contextIsolation: true` 和 `nodeIntegration: false` 以增强安全性
271
+ - 如需要在渲染进程中使用 Electron API,请通过预加载脚本暴露必要的功能
349
272
 
350
- ```javascript
351
- const dragPlus = new DragPlus(win, {
352
- smoothDrag: true
353
- });
354
- ```
273
+ 3. **元素识别**:库会自动识别并排除常见的交互元素(如按钮、输入框等),避免交互冲突
355
274
 
356
- ## 开发
275
+ 4. **错误处理**:库内置了基本的错误处理和日志警告,便于调试
357
276
 
358
- ```bash
359
- # 安装依赖
360
- pnpm install
361
-
362
- # 开发模式
363
- pnpm run dev
277
+ 5. **DOM 就绪**:库会自动检测 DOM 就绪状态,确保在合适的时机初始化
364
278
 
365
- # 构建
366
- pnpm run build
279
+ ## 兼容性
367
280
 
368
- # 运行测试
369
- pnpm run test
370
- ```
281
+ - 支持 Electron 13.x 及以上版本
282
+ - 支持 Windows、macOS 和 Linux 平台
283
+ - 需要 TypeScript 4.0+(如果使用 TypeScript)
371
284
 
372
285
  ## 许可证
373
286
 
374
- [MIT](LICENSE)
287
+ MIT License
375
288
 
376
289
  ## 贡献
377
290
 
378
- 欢迎提交Issue和Pull Request
291
+ 欢迎提交 Issues Pull Requests
package/dist/example.d.ts CHANGED
@@ -1 +1,4 @@
1
+ /**
2
+ * electron-drag-plus 简化版API使用示例
3
+ */
1
4
  export {};