【Electron】vue+electron实现无边框窗口

一、前言

无边框窗口是不带外壳(包括窗口边框、工具栏等),只含有网页内容的窗口。对于一个产品来讲,桌面应用带边框的很少,因为丑(我们的UI觉得–与我无关-.-)。因此我们就来展开说下,在做无边框窗口时候需要注意的事项以及我踩过的坑。

二、实现方案

1.创建无边框窗口

要创建无边框窗口,只需在 BrowserWindow 的 options 中将 frame 设置为 false

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800,height: 600,// 设置为 `false` 时可以创建一个无边框窗口。 默认值为 `true`frame: false,// 无标题时,在mac内,窗口将一直拥有位于左上的标准窗口控制器 (“traffic lights”)titleBarStyle: 'hidden',// mac设置控制按钮在无边框窗口中的位置。trafficLightPosition: { x: 12, y: 18 },// 在windows上,设置默认显示窗口控制工具titleBarOverlay: { color: "#fff", symbolColor: "black", }
})
win.show() 

在electron官网中有这么一段描述

titleBarStyle String (可选) macOS Windows - 窗口标题栏样式。 默认值为 default. 可能的值有

  • hidden - 在一个隐藏的标题栏和一个全尺寸大小的内容窗口中取得结果。 在 macOS 内, 窗口将一直拥有位于左上的标准窗口控制器 (“traffic lights”)。 在 Windows上,当与 titleBarOverlay: true 合并时,它将激活窗口控件叠加(详情请参阅 titleBarOverlay),否则将不会显示窗口控件

titleBarOverlay Object | Boolean (可选) - 当使用无框窗口配置win.setWindowButtonVisibility(true) 在 macOS 或使用 titleBarStyle 可使标准窗口控制可见 (“traffic lights” on macOS) ,当前属性开启 Window Controls 覆盖 JavaScript APIs 和 CSS Environment Variables 指定 true 将导致覆盖默认系统颜色。 默认值为 false.

这里说两者配合使用,即titleBarStylehidden,并且titleBarOverlaytrue或者对象时,则windows系统中,应用窗口也会默认显示出window操作系统的窗口控件工具。

如图所示

这样我们就完成了,electron应用的无边框窗口。

但是这样的无边框窗口仅能实现通用的样式,应用头部总是会被占用一条高度。并且不支持自定义标题栏。若你有自定义标题栏,或者嵌入式的windows窗口控件需求,请继续往下看

2.创建windows窗口控件组件

因为我做的项目有windows窗口控件内嵌页面的需求,而且这样也方便自定义标题栏,所以需要有这样一个控件。例如下面这种情况

// WindowsTopControl.vue

<template><div class="windows-top-control" :style="{height:mainHeight + 'px'}" :class="{'main-bottom':border}"><ul class="windows-top-control-win"><li @click="controlWindow(1)"><Icon type="最小化图标" /></li><li @click="controlWindow(isFullScreen ? 3 : 2)"><Icon :type="isFullScreen ? '最大化图标' : '恢复正常图标'" /></li><li class="close-icon"@click="controlWindow(0)"><Icon type="关闭图标" /></li></ul></div>
</template>

<script> import { mapGetters, mapMutations } from 'vuex'
const { ipcRenderer, remote } = require("electron")
const WIN_CONTROL = { // 控件四种操作0: 'close',1: 'minimize',2: 'maximize',3: 'unmaximize'
}
export default {name: 'windowsTopControl',components: {},props: {mainHeight: {type: String,default: '42'},border: {type: Boolean,default: false}},computed: { ...mapGetters(['isFullScreen']) },mounted () {// 上来先设定当前窗口是否在最大化的状态this.setIsFullScreen(remote.getCurrentWindow().isMaximized())// 监听是否是最大化窗口 并 更改标识是否最大化ipcRenderer.on('toggleMax', (e, isFullScreen) => {this.setIsFullScreen(isFullScreen)})},methods: {...mapMutations(['setIsFullScreen']),controlWindow (val) {// 只有在2、3点击时,修改是否全屏状态if ([2, 3].includes(val)) {this.setIsFullScreen(val === 2)}remote.getCurrentWindow()[WIN_CONTROL[val]]()}},
} </script>
<style lang="less" scoped> .windows-top-control {width: 100%;height: 42px;display: flex;justify-content: flex-end;.windows-top-control-win {width: 100%;height: 24px;display: flex;align-items: center;justify-content: flex-end;-webkit-app-region: drag;position: relative;li {width: 40px;height: 100%;text-align: center;line-height: 22px;cursor: pointer;-webkit-app-region: no-drag;position: absolute;pointer-events: auto;top: -2px;&:hover {background: #E0E4E5;}&:active {background: #CDCED0;}&:hover {color: #0183ff;}i {font-size: 14px;font-weight: 600;color: #1f2329;}}li:nth-child(1) {right: 78px;}li:nth-child(2) {right: 38px;}li:nth-child(3) {right: -2px;}}
}

.close-icon:hover {background: #FF6161 !important;i {color: #fff !important;}
}
.close-icon:active {background: #D64141 !important;i {color: #fff !important;}
}

.main-bottom {border-bottom: 1px solid #f6f6f6;
} </style> 

下面是vuex中的配置

// selectedState.js
export default {state: {// 是否全屏(最大化)isFullScreen: window.sessionStorage.getItem('isFullScreen') || false,},getters: {isFullScreen: state => state.isFullScreen},mutations: {setIsFullScreen(state, val) {state.isFullScreen = valwindow.sessionStorage.setItem('isFullScreen', val)}}
} 

接下来 我们还需在主进程中,监听用户的放大、缩小、最小化、关闭的操作。

// background.js

// win是窗口实例
win.on('maximize', (event) => {event.sender.send('toggleMax', true)
})
win.on('unmaximize', (event) => {event.sender.send('toggleMax', false)
}) 

准备工作做完了,接下来我们就可以来引用使用组件啦,如下

// home.vue
<template><div><WindowsTopControl mainHeight="24" /></div>
</template>
<script> import WindowsTopControl from './WindowsTopControl.vue'
export default { components: {WindowsTopControl}
} </script> 

以上,我们就完成了自定义的windows控件组就完成了,记得将窗口设置中的titleBarOverlay注释掉!这样我们就能自定义标题栏和内嵌windows控件了。

三、后记

如果我们自定义控件这种方式实现的话,还需要考虑一点,那就是窗口的拖拽功能,一般情况下,我们拖拽的都是是窗口的头部。这里我们可以给窗口提前注入一个js,去创建一个拖拽条,内容如下

// WindowDrag.js

// 在顶部插入一个的dom
function initTopDrag () {const topDiv = document.createElement('div') // 创建节点topDiv.style.position = 'fixed' // 一直在顶部topDiv.style.top = '2px'topDiv.style.left = '2px'topDiv.style.height = '18px' // 顶部20px才可拖动topDiv.style.width = 'calc(100% - 122px)' // 宽度100%topDiv.style.zIndex = '9999' // 悬浮于最外层// topDiv.style.pointerEvents = 'none' // 用于点击穿透// @ts-ignoretopDiv.style['-webkit-user-select'] = 'none' // 禁止选择文字// @ts-ignoretopDiv.style['-webkit-app-region'] = 'drag' // 拖动topDiv.id = 'drag-top-line'document.body.appendChild(topDiv) // 添加节点
}

window.addEventListener('DOMContentLoaded', function onDOMContentLoaded () {initTopDrag()document.getElementById('drag-top-line').addEventListener('dblclick', e => {if (window.$isMac) {window.ipcRenderer.send('toggleMax')}})
}) 

在创建窗口时候引入

// background.js

// 这里我将WindowDrag.js文件放在了public种
const win = new BrowserWindow({ width: 800,height: 600,webPreferences: {preload: `${__static}/WindowDrag.js`,}
}) 

如此我们就完成了拖拽条的设置。(如图所示)

本篇完结!撒花!感谢观看! 希望能帮助到你!

最后,整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。



有需要的小伙伴,可以点击下方卡片领取,无偿分享文章来源地址https://uudwc.com/A/BLLX

原文地址:https://blog.csdn.net/qq_53225741/article/details/126872596

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年06月16日 15:27
Qt之QListView的简单使用(含源码+注释)
下一篇 2023年06月16日 15:27