实现一个不规则窗体

这里我们实现一个圆形窗体,实现其他形状的窗体与这个方法类似。

首先,把窗口的高度(height)和宽度(width)值修改为相同的值,使窗口成为一个正方形。

其次,把窗口的透明属性(transparent)设置为true,这样设置之后窗口还是正方形的,但只要我们控制好内容区域的Dom元素的形状,就可以让窗口看起来像一个不规则形状一样。

不规则窗口往往需要自定义边框和标题栏,所以frame也设置为false。

另外,透明的窗口不可调整大小。所以将resizable属性设置为false。

窗口显示后,为了防止双击窗口可拖拽区触发最大化事件,我们把maximizable属性也设置为false。

最终创建窗口的代码如下:

win = new BrowserWindow({
width: 380,
height: 380,
transparent: true,
frame: false,
resizable: false,
maximizable: false,
//...
})

接下来再修改样式,使内容区域的Dom元素呈现一个圆形:

html,body {
margin: 0px;
padding: 0px;
pointer-events: none;
}
#app {
box-sizing: border-box;
width: 380px;
height: 380px;
border-radius: 190px;
border: 1px solid green;
background: #fff;
overflow: hidden;
pointer-events: auto;
}

上面样式代码中通过border-radius样式把#app元素设置成了圆形。border-radius负责定义一个元素的圆角样式,如果圆角足够大,整个DIV就变成了一个圆形。

pointer-events样式,在后面会有讲解。

最终实现的窗口界面如图5-7:

如果你略微了解CSS,你会知道除了圆形,你还可以通过CSS样式控制这个窗口成为任意其他形状。

点击穿透透明区域

上面这个应用会有一点小问题,虽然窗口看起来是圆形的,但它其实还是一个正方形窗口,只不过正方形四个角是透明的,所以看起来像一个圆形的窗口。

当我点击下图中的①区域内的文本文件时,鼠标的点击事件还是发生在本窗口内,而不会点击到那个文件上。

作为开发者,我们知晓其中的道理,但作为用户来说,这就显得很诡异。为了达到更好的用户体验,我们需要让鼠标在这4个区域发生点击动作时,点击动作可以穿透本窗口,落在窗口后面的内容上。

Electron官方文档明确说“不能点击穿透透明区域”,这并没有难倒我们,有一个小trick来解决这个问题。

首先,需要用到窗口对象的setIgnoreMouseEvents方法,该方法可以使窗口忽略窗口内的所有鼠标事件,并且在此窗口中发生的所有鼠标事件都将被传递到此窗口背后的内容。

如果调用该方法时传递了forward参数,如:

setIgnoreMouseEvents(true, { forward: true }),

则只有点击事件会穿透窗口,鼠标移动事件仍会触发。

基于此,我们在页面中执行如下代码:

  const remote = require("electron").remote;
let win = remote.getCurrentWindow();
window.addEventListener("mousemove", event => {
let flag = event.target === document.documentElement;
if (flag){
win.setIgnoreMouseEvents(true, { forward: true });
}
else {
win.setIgnoreMouseEvents(false);
}
});
win.setIgnoreMouseEvents(true, { forward: true });

注意,这是实验代码,所以用了remote模块,关于remote模块的一些问题,我在“Electron团队为什么要干掉remote模块“有详细描述。

上面的代码中,设置窗口对象监听mousemove事件,当鼠标移入窗口圆形内容区的时候,不允许鼠标事件穿透。当鼠标移入透明区时,允许鼠标事件穿透。

接着我们为html,body元素增加样式:pointer-events: none,为#app元素增加样式pointer-events: auto。

设定pointer-events: none后,其所标志的元素就永远不会成为鼠标事件的target了。

为子元素#app设置了pointer-events: auto,说明子元素#app还是可以成为鼠标事件的target的。

也就是说除了圆形区域内可以接收鼠标事件外,其他部分将不再接收鼠标事件。

当鼠标在圆形区域外移动时,窗口对象的mousemove事件触发,event.target为document.documentElement对象(这个事件并不是在html或body元素上触发的,而是在窗口对象上触发的,document.documentElement就是DOM树中的根元素,也就是html节点所代表的元素)。

至此,上文代码中的判断成立,当鼠标在前文所述四个区域移动时,鼠标事件允许穿透。鼠标在圆形区域移动时,鼠标事件不允许穿透。

至此,上文所述判断成立,运行程序,鼠标在正方形四角区域内点击,鼠标事件具备了穿透效果。

如何点击穿透Electron不规则窗体的透明区域的更多相关文章

  1. Qt 不规则窗体 – 鼠标点击穿透(Linux也可以,有对x11的配置的方法)

    之前写过如何用 Qt 现成的方法写出无边框半透明的不规则窗体:<Qt 不规则窗体 – 无边框半透明> 其实有一个很特殊的窗体属性一直以来都伴随着不规则窗体出现,这就是本文要介绍的鼠标点击穿 ...

  2. WPF界面设计技巧(1)—不规则窗体图文指南

    原文:WPF界面设计技巧(1)-不规则窗体图文指南 初到园子,奉上第一篇入门级教程,请勿见笑. 以往WinForm编程中,实现不规则窗体是有一定难度的,更难的是不规则窗体的边缘抗锯齿及局部透明处理.而 ...

  3. WPF中不规则窗体与WindowsFormsHost控件的兼容问题完美解决方案

    首先先得瑟一下,有关WPF中不规则窗体与WindowsFormsHost控件不兼容的问题,网上给出的解决方案不能满足所有的情况,是有特定条件的,比如  WPF中不规则窗体与WebBrowser控件的兼 ...

  4. 移动开发之fastclick 点击穿透

    穿透(点穿)是在mobile各种浏览器上发生的常见的bug.可能是由click事件的延迟(300ms)或者事件冒泡导致 现象:在A页面中有个 btn1<或a标签>,在B页面中有个 btn2 ...

  5. QT实现不规则窗体

    看到网上有很多不规则窗体的实现,效果很酷.于是使用QT也实现了一个,QT的不规则窗体实现非常简单,只需要设置一个mask(遮掩)图片,这个图片的格式可以使用png或bmp格式,我使用了png格式,默认 ...

  6. WPF中不规则窗体与WebBrowser控件的兼容问题解决办法

    原文:WPF中不规则窗体与WebBrowser控件的兼容问题解决办法 引言 这几天受委托开发一个网络电视项目,要求初步先使用内嵌网页形式实现视频播放和选单,以后再考虑将网页中的所有功能整合进桌面程序. ...

  7. [小结][N种方法]实现WPF不规则窗体

    原文:[小结][N种方法]实现WPF不规则窗体 WPF实现不规则窗体,方法很多很多多.... 本文总结DebugLZQ认为简洁高效的几种方法 实现WPF不规则窗体的几种常用的方法如下: 1.使用Ble ...

  8. WPF移动Window窗体(鼠标点击左键移动窗体自定义行为)

    XAML代码部分:1.引用System.Windows.Interactivity 2.为指定的控件添加一个拖动的行为 3.很简单的了解行为的作用和用法 <Window xmlns=" ...

  9. 聊聊click延迟和点击穿透

    博客原文地址:Claiyre的个人博客 https://claiyre.github.io/ 如需转载,请在文章开头注明原文地址 移动端click事件被延迟 移动端的开发经常需要监听用户的双击行为,所 ...

随机推荐

  1. 如何远程调试自定义开发的Flume应用

    一.前言 Flume作为当下最流行的大数据采集组件之一.其本身拥有分布式/高可靠/高可用等优点,但相比较于Flink/Spark/Kafka等大数据组件,其对于本地调试的功能支持度并不高,如果我们没有 ...

  2. Use Module and Function instead of Class in Python

    The following scripts run in ipython demonstrate the differences between instance method and static ...

  3. 绿色djvu阅读软件

    官方的djvu viewer都需要安装,总算找到一个绿色版的,名为STDU Viewer,可以阅读的格式包括DjVu, PDF, TIFF, XPS, FB2等,版本为1.6.2.

  4. Golang语言系列-14-单元测试

    单元测试 字符串切割函数 package split_string import ( "fmt" "strings" ) // Split:切割字符串 // e ...

  5. 使用 C# 下载文件的十八般武艺

    文件下载是一个软件开发中的常见需求.本文从最简单的下载方式开始步步递进,讲述了文件下载过程中的常见问题并给出了解决方案.并展示了如何使用多线程提升 HTTP 的下载速度以及调用 aria2 实现非 H ...

  6. HDFS 09 - HDFS NameNode 的高可用机制

    目录 1 - 为什么要高可用 2 - NameNode 的高可用发展史 3 - HDFS 的高可用架构 3.1 Standby 和 Active 的命名空间保持一致 3.2 同一时刻只有一个 Acti ...

  7. 手机摄像头作为视频画面捕捉设备与OBS连接(有线)

    手机有线连接OBS(以无他伴侣作为测试案例) 1.硬件设备 安卓手机1台.安卓手机对应的数据线.电脑2台(windows系统,1台做OBS与手机连接.1台做直播后台:配置等如果能达到要求也可以只使用一 ...

  8. virtualenv 创建python虚拟环境

    为什么要创建python虚拟环境 在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4.所有第三方的包都会被pip安装到Python3的site-packages目录下. 如 ...

  9. WPF学习笔记二 依赖属性实现原理及性能分析

    在这里讨论依赖属性实现原理,目的只是学习WPF是怎么设计依赖属性的,同时更好的使用依赖属性. 首先我们来思考一个简单的问题:我们希望能验证属性的值是否有效,属性变更时进行自己的处理.回顾一下.net的 ...

  10. Buffer和Cache的异同

    Buffer的本质是缓冲,常见实例如下面这个: 对,就是铁道端头那个巨大的弹簧一类的东西.作用是万一车没停住(是没停住啊,刹车了但是差一点没刹住那种,不是不拉刹直接撞上来),撞弹簧上减速降低危险,起到 ...