当前位置:   article > 正文

electron + vue3 自定义窗口:移动,缩放,置顶_vue windows 桌面置顶浮窗

vue windows 桌面置顶浮窗

electron

main.js

  1. const { BrowserWindow , ipcMain } = require('electron');
  2. const path = require("path")
  3. const CustomWindow = require('./CustomWindow')
  4. const win = new BrowserWindow({
  5. frame: false,
  6. transparent: true,
  7. center: true,
  8. webPreferences: {
  9. preload: path.join(__dirname, `./preload.js`)
  10. }
  11. })
  12. const customWin = new CustomWindow(win)
  13. ipcMain.on('on-custom-win', (_, funName, ...arg) => customWin[funName](...arg));

preload.js

  1. const { contextBridge, ipcRenderer } = require('electron');
  2. const handleWin = {
  3. changeSize: (...args) => ipcRenderer.send('on-custom-win', 'autoMax', ...args),
  4. moveStart: () => ipcRenderer.send('on-custom-win', 'moveStart'),
  5. moveEnd: () => ipcRenderer.send('on-custom-win', 'moveEnd'),
  6. top: () => ipcRenderer.send('on-custom-win', 'top'),
  7. maximize: () => ipcRenderer.send('on-custom-win', 'maximize'),
  8. onStatus: (fun) => ipcRenderer.on('window-status', fun)
  9. };
  10. contextBridge.exposeInMainWorld('ipcApi', {
  11. handleWin
  12. });

CustomWindow.js

  1. const { screen } = require('electron');
  2. /**
  3. * 窗口移动|缩放|置顶
  4. */
  5. module.exports = class {
  6. constructor(win) {
  7. this.isMove = false;
  8. this.startPosition = [0, 0]
  9. this.oldPosition = [0, 0];
  10. this.maxStatus = false;
  11. this.topStatus = false;
  12. this.nowSize = null;
  13. this.nowPosition = null;
  14. this._initialization(win);
  15. };
  16. _initialization(win) {
  17. this.win = win;
  18. this.defaultSize = win.getSize();
  19. this.defaultPosition = win.getPosition();
  20. if (win.isAlwaysOnTop()) this.top();
  21. this.autoMax(...this.defaultSize);
  22. };
  23. _isWin = () => this.win && !this.win.isDestroyed();
  24. moveStart() {
  25. this.isMove = true;
  26. if (!this._isWin()) return this.moveEnd();
  27. // 获取鼠标按下位置
  28. let { x, y } = screen.getCursorScreenPoint();
  29. const winPosition = this.win.getPosition();
  30. x -= winPosition[0];
  31. y -= winPosition[1];
  32. this.startPosition = [x, y];
  33. this._moveing();
  34. };
  35. _moveing() {
  36. if (!this.isMove) return;
  37. let { x, y } = screen.getCursorScreenPoint();
  38. x -= this.startPosition[0];
  39. y -= this.startPosition[1];
  40. if (x !== this.oldPosition[0] || y !== this.oldPosition[1]) {
  41. this._restoreSize();
  42. this.win.setPosition(x, y);
  43. this.oldPosition = [x, y];
  44. };
  45. setTimeout(() => this._moveing(), 16);
  46. };
  47. moveEnd = () => this.isMove = false;
  48. _restoreSize() {
  49. if (!this.maxStatus || !this.oldPosition[0] || !this.oldPosition[1]) return;
  50. let startPositionX = parseInt(this.nowSize[0] / 2);
  51. const { x: leftBoundary, width: screenWidth } = this._getNowScreenSize();
  52. const rightBoundary = leftBoundary + screenWidth - this.nowSize[0];
  53. let { x: movePosition } = screen.getCursorScreenPoint();
  54. movePosition -= startPositionX;
  55. if (movePosition < leftBoundary) {
  56. startPositionX += movePosition - leftBoundary;
  57. };
  58. if (movePosition > rightBoundary) {
  59. startPositionX += movePosition - rightBoundary;
  60. };
  61. this.startPosition[0] = startPositionX;
  62. this.win.setSize(...this.nowSize);
  63. this.maxStatus = false;
  64. this._sendStatus('max', false);
  65. };
  66. _getNowScreenSize() {
  67. let { x, y } = this.win.getBounds();
  68. if (x < 0) x = 0;
  69. for (const display of screen.getAllDisplays()) {
  70. if (x >= display.bounds.x && x < display.bounds.x + display.bounds.width &&
  71. y >= display.bounds.y && y < display.bounds.y + display.bounds.height) {
  72. return display.bounds;
  73. };
  74. };
  75. };
  76. top() {
  77. if (!this._isWin()) return;
  78. this.topStatus = !this.topStatus;
  79. this.win.setAlwaysOnTop(this.topStatus);
  80. this._sendStatus('top', this.topStatus);
  81. };
  82. autoMax(width, height) {
  83. if (!this._isWin() || !this.win.isResizable() || this.maxStatus) return;
  84. const { width: screenWidth, height: screenHeight } = this._getNowScreenSize();
  85. if (screenWidth - width < 100 && screenHeight - height < 100) {
  86. this.nowSize = this.defaultSize;
  87. this.nowPosition = this.defaultPosition;
  88. this.maxStatus = true;
  89. this._sendStatus('max', true);
  90. this.win.maximize();
  91. this.oldPosition = [0, 0];
  92. };
  93. };
  94. maximize() {
  95. if (!this._isWin() || !this.win.isResizable()) return;
  96. this.maxStatus = !this.maxStatus;
  97. if (this.maxStatus) {
  98. this.nowSize = this.win.getSize();
  99. this.nowPosition = this.win.getPosition();
  100. this.win.maximize();
  101. } else {
  102. this.win.setSize(...this.nowSize);
  103. this.win.setPosition(...this.nowPosition);
  104. };
  105. this.oldPosition = [0, 0];
  106. this._sendStatus('max', this.maxStatus);
  107. };
  108. _sendStatus = (type, value) => this.win.webContents.send('window-status', { type, value });
  109. }

VUE

main.js 注册指令

  1. import { createApp } from 'vue'
  2. import App from '@/App.vue'
  3. import registerDirectives from '@/directives'
  4. const app = createApp(App)
  5. registerDirectives(app)
  6. app.mount('#app')

directives 自定义指令

index.js 

  1. import interactWin from './interactWin';
  2. export default function registerDirectives(app) {
  3. app.directive("handle-win", { mounted: (...arg) => interactWin.handle(...arg) })
  4. }

interactWin.js

  1. const { handleWin } = window.ipcApi;
  2. class InteractWin {
  3. constructor() {
  4. this.el = null;
  5. };
  6. handle(el, binding = null) {
  7. if (this.el) return;
  8. this.el = el;
  9. this.el.addEventListener('mousedown', this._mouseDown);
  10. this.el.addEventListener('dblclick', this._mouseDblclick);
  11. window.addEventListener('resize', this._handleResize);
  12. if (binding?.value && typeof binding.value === 'function') {
  13. handleWin.onStatus((_, ...arg) => binding.value(...arg));
  14. };
  15. };
  16. _mouseDblclick = () => handleWin.maximize();
  17. _mouseDown = (e) => {
  18. if (e.button !== 0) return;
  19. handleWin.moveStart();
  20. window.addEventListener('mouseup', this._globalMouseUp);
  21. };
  22. _globalMouseUp = (e) => {
  23. if (e.button !== 0) return;
  24. handleWin.moveEnd();
  25. window.removeEventListener('mouseup', this._globalMouseUp);
  26. };
  27. //此处加防抖可提升性能
  28. _handleResize = () => {
  29. handleWin.changeSize(window.innerWidth, window.innerHeight);
  30. };
  31. };
  32. export default new InteractWin();

vue使用指令操作窗口

在头部DOM上使用 v-handle-win;

1:左键移动窗口;

2:双击最大化窗口与还原窗口;

3:最大化移动窗口自动还原窗口;

4:手动改变窗口尺寸至屏幕最大范围(范围阈值在CustomWindow.js内修改)时自动最大化;

  1. <template>
  2. <div v-handle-win="onWinHandle">
  3. <!-- 自定义窗口头部,使用指令并监听使用反馈 -->
  4. </div>
  5. <div @click="winTop">
  6. 是否置顶:{{ topStatus }}
  7. </div>
  8. <div @click="winMax">
  9. 是否最大化:{{ maxStatus }}
  10. </div>
  11. </template>
  12. <script setup>
  13. import { ref } from 'vue';
  14. const { handleWin } = window.ipcApi;
  15. const maxStatus = ref(false)
  16. const topStatus = ref(false)
  17. /**
  18. * 监听操作窗口头部的反馈
  19. */
  20. const onWinHandle = ({ type, value }) => {
  21. switch (type) {
  22. case 'max':
  23. maxStatus.value = value
  24. break;
  25. case 'top':
  26. topStatus.value = value
  27. break;
  28. }
  29. }
  30. /**
  31. * 窗口置顶
  32. */
  33. const winTop = () => handleWin.top();
  34. /**
  35. * 最大化与还原
  36. */
  37. const winMax = () => handleWin.maximize();

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/936104
推荐阅读
相关标签
  

闽ICP备14008679号