最近有个需求,Electron 打开的窗口要实现拖拽功能,大概看了一眼 BrowserWindow 的 API 却只找到了一个 move 事件,这个事件默认是针对有边框窗口的,也即 frame: true
的窗口。
本来打算直接使用 drag API 来写,偶然翻到了以下 API:无边框窗口
其中提到了可拖拽区的概念,即可以将一个矩形区域设置成可拖拽区域,具体文档如下:
默认情况下, 无边框窗口是不可拖拽的。应用程序需要在 CSS 中指定 -webkit-app-region: drag 来告诉 Electron 哪些区域是可拖拽的(如操作系统的标准标题栏),在可拖拽区域内部使用 -webkit-app-region: no-drag 则可以将其中部分区域排除。请注意, 当前只支持矩形形状。
注意: -webkit-app-region: drag 在开发人员工具打开时会出现问题。查看更多信息 (包括变通方法), 请参见此 GitHub 问题 。
要使整个窗口可拖拽, 您可以添加 -webkit-app-region: drag 作为 body 的样式:
<body style="-webkit-app-region: drag">
</body>
请注意,如果您使整个窗口都可拖拽,则必须将其中的按钮标记为不可拖拽,否则用户将无法点击它们:
button {
-webkit-app-region: no-drag;
}
If you’re only setting a custom titlebar as draggable, you also need to make all buttons in titlebar non-draggable.
那接下来就简单了,你可以自定义一个 titleBar 区域,将这个区域设置成可拖拽,拖拽操作将会触发 BrowserWindow 的 move
事件。
我们的应用本身就是一个无边框窗口,假如想要整个窗口内容都可以拖拽,就需要设置 body 为 -webkit-app-region: drag
,同时将里面的所有需要点击(包括表单元素)和需要滚动的元素设置为:-webkit-app-region: no-drag;
下面是目前的做法,添加如下 css 样式:
body {
-webkit-app-region: drag;
width: 100%;
height: 100%;
}
button, a, input, textarea {
-webkit-app-region: no-drag;
}
.noDrag {
-webkit-app-region: no-drag;
}
然后在所有需要点击的元素上添加 .noDrag
类,如果一整个父级容器中里面的所有内容有很多需要点击,比如有整个表单,那可以应用到父级容器上,但是要注意应用的容器的高度需要包含内部元素。
如果一个应用里有很多需要点击交互的地方,这样添加样式就很麻烦。由于笔者的应用为 Vue.js + Electron 有以下想法有时间验证下:
上面的猜想实现起来都比较复杂,最简单的还是直接指定 no-drag 样式了,不过假如说代码编写比较规范,比如 点击只是用 button 或者 a 标签,那么剩下的样式应用应该就很少了。