实现一个不规则窗体

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

首先,把窗口的高度(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. Clickhouse Docker集群部署

    写在前面 抽空来更新一下大数据的玩意儿了,起初架构选型的时候有考虑Hadoop那一套做数仓,但是Hadoop要求的服务器数量有点高,集群至少6台或以上,所以选择了Clickhouse(后面简称CH). ...

  2. Qt Designer中自定义控件的使用(提升法与插件法)

    准备乱写一点Qt自定义Widget在Designer中的使用.可是又不想重复提升法(promotion)及插件法基本用法,因为Manual中Using Custom Widgets with Qt D ...

  3. 【笔记】KNN之分类准确度

    分类准确度 分类准确度 以sklearn中的手写数字datasets.load_digits为例,其是8*8的图形,具有64个特征值,类别由0到9 我们挑选出666这个图形,将其可视化 X = dig ...

  4. 一看就会的高效Discuz初始化入门安装方法

    在使用Discuz搭建论坛的过程中,小九发现有许多朋友对于宝塔的安装和初始化不太熟悉,找不到适合的方法.或是按照一些教程安装却出现问题得不到解决,只能选择重新再来. 今天,小九给大家介绍简单的镜像一键 ...

  5. 用python 30行代码,搞定一个简单截图调取的百度识字功能

    在做一个数据标注过程中人工需要识别文字. 想了想写了一个小脚本, 大致过程这样的. 截图功能写了好久也没写明白,索性直接调用第三方的截图工具了,在采用qq或者微信截图时,截图完成后保存大致保存在剪切板 ...

  6. Java协程编程之Loom项目尝鲜

    前提 之前很长一段时间关注JDK协程库的开发进度,但是前一段时间比较忙很少去查看OpenJDK官网的内容.Java协程项目Loom(因为项目还在开发阶段,OpenJDK给出的官网https://ope ...

  7. HCNA Routing&Switching之地址转换技术NAT

    前文我们了解了包过滤工具ACL相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15156308.html:今天我们来聊一聊地址转换技术NAT相关话题: ...

  8. APIO 2007 动物园 题解

    链接题面 看清楚找到小数据范围,第一维表示遍历到的栅栏,第二维是五位状态 先预处理每个状态会使多少小朋友高兴 方程是  f[i][j]=max(f[(i&((1<<4)-1))&l ...

  9. Maven在IDEA中的日常使用

    1.为什么使用MavenMaven是我们在开发过程中常用的工具,主要用途有两种:1)方便的下载jar包2)项目打包接下来以windows操作系统为例,介绍一下Maven在IDEA中如何设置和常用的功能 ...

  10. QT从入门到入土(九)——TCP/IP网络通信(以及文件传输)

    引言 TCP/IP通信(即SOCKET通信)是通过网线将服务器Server端和客户机Client端进行连接,在遵循ISO/OSI模型的四层层级构架的基础上通过TCP/IP协议建立的通讯.控制器可以设置 ...