一、前言

无边框窗口是不带外壳(包括窗口边框、工具栏等),只含有网页内容的窗口。对于一个产品来讲,桌面应用带边框的很少,因为丑(我们的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无边框窗口的资料请关注Devmax其它相关文章!

vue electron实现无边框窗口示例详解的更多相关文章

  1. HTML5 播放 RTSP 视频的实例代码

    目前大多数网络摄像头都是通过 RTSP 协议传输视频流的,但是 HTML 并不标准支持 RTSP 流。本文重点给大家介绍HTML5 播放 RTSP 视频的实例代码,需要的朋友参考下吧

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. vue自定义加载指令v-loading占位图指令v-showimg

    这篇文章主要为大家介绍了vue自定义加载指令和v-loading占位图指令v-showimg的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. vue使用动画实现滚动表格效果

    这篇文章主要为大家详细介绍了vue使用动画实现滚动表格效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. 关于Vue 监控数组的问题

    这篇文章主要介绍了Vue 监控数组的示例,主要包括Vue 是如何追踪数据发生变化,Vue 如何更新数组以及为什么有些数组的数据变更不能被 Vue 监测到,对vue监控数组知识是面试比较常见的问题,感兴趣的朋友一起看看吧

  6. Vue子组件props从父组件接收数据并存入data

    这篇文章主要介绍了Vue子组件props从父组件接收数据并存入data的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  7. Vue h函数的使用详解

    本文主要介绍了Vue h函数的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  8. VUE响应式原理的实现详解

    这篇文章主要为大家详细介绍了VUE响应式原理的实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  9. vue+Element ui实现照片墙效果

    这篇文章主要为大家详细介绍了vue+Element ui实现照片墙效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. vue+elemet实现表格手动合并行列

    这篇文章主要为大家详细介绍了vue+elemet实现表格手动合并行列,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部