当前位置 : 主页 > 网络编程 > JavaScript >

vue electron实现无边框窗口示例详解

来源:互联网 收集:自由互联 发布时间:2023-02-08
目录 一、前言 二、实现方案 1.创建无边框窗口 2.创建windows窗口控件组件 三、后记 一、前言 无边框窗口是不带外壳(包括窗口边框、工具栏等),只含有网页内容的窗口。对于一个产
目录
  • 一、前言
  • 二、实现方案
    • 1.创建无边框窗口
    • 2.创建windows窗口控件组件
  • 三、后记

    一、前言

    无边框窗口是不带外壳(包括窗口边框、工具栏等),只含有网页内容的窗口。对于一个产品来讲,桌面应用带边框的很少,因为丑(我们的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 = val
                window.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-ignore
      topDiv.style['-webkit-user-select'] = 'none' // 禁止选择文字
      // @ts-ignore
      topDiv.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`,
        }
    })
    

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

    以上就是vue electron实现无边框窗口示例详解的详细内容,更多关于vue electron无边框窗口的资料请关注易盾网络其它相关文章!

    上一篇:JavaScript&nbsp;实现点击关闭全屏示例详解
    下一篇:没有了
    网友评论