NW.js开发桌面应用,如何自定义边框
利用NW.js开发桌面应用时,NW框架的边框可能无法满足我们对产品的要求,这个时候就需要自定义边框,比如无边框、无边框+有圆角、无边框+有边+有圆角等。现在问题来了,该怎么实现自定义效果呢?笔者以最后一种情况(无边框+有边+有圆角),进行简单的设置说明。
package.json配置
"window": {
"frame": false, // 去除框架的边框
"transparent": true // 窗口透明
}
起步
<!-- 在html元素上设置软件整体边框和圆角;在body中的div上同样可以设置 -->
<html style="border:8px solid #eeca00;border-radius:8px">
<!-- 设置透明背景 -->
<body style="background-color:rgba(0,0,0,0);">
看看效果:
自定义透明背景的NW.js应用
上图所示的完整HTML代码是:
<!DOCTYPE html>
<html style="border:8px solid #eeca00;border-radius:8px">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo</title>
</head>
<body style="background-color:rgba(0,0,0,0);">
<div style="height:500px;font-size:40px">
Hello World
</div>
</body>
</html>
可拖拽
现在,这个软件不能拖动,也没有关闭、最小化、最大化窗口功能,现在我们来给这个软件添加这些功能。
想要实现拖拽,关键是使用
-webkit-app-region: drag;
CSS属性。上图中,蓝色横条上添加了这个属性,现在就能点它进行拖拽了。此外,在可拖拽的元素上双击,可以最大化窗口,再次双击则恢复窗口大小。
完整HTML代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible"content="ie=edge">
<title>demo</title>
<style>
*{padding:0;margin:0;}
html{border:8px solid #eeca00;border-radius:8px;}
body{background-color:rgba(0,0,0,0);overflow:hidden;}
.app{height:500px;font-size:40px;background:#fff;}
.drag{height:36px;line-height:36px;font-size:14px;color:#fff;text-align:center;background:#008cee;-webkit-app-region:drag;}
.main{height:calc(100% - 36px);display:flex;align-items:center;justify-content:center;}
</style>
</head>
<body>
<div class="app">
<div class="drag">拖拽我吧</div>
<div class="main">Hello World</div>
</div>
</body>
</html>
窗口控制(最小化、最大化、关闭)
我们在拖拽层的右上角添加几个按钮,然后给它们注册点击事件。需要注意,因为拖拽层上设置了-webkit-app-region: drag;
CSS属性,这个属性会吃掉所有的鼠标事件,比如鼠标悬浮、点击等。为了确保图中的三个按钮可以点击,我们要在被点击的元素上设置-webkit-app-region: no-drag;
CSS属性,去掉drag功能,就能点击了。
窗口的最大化等操作,需要用到nw的API,下面是实现代码:
let min, max, close, win
min = document.getElementById('min') // 最小化按钮
max = document.getElementById('max') // 最大化按钮
close = document.getElementById('close') // 关闭按钮
win = nw.Window.get() // 获取当前窗口实例
min.onclick = () => {
win.minimize() // 窗口最小化
}
max.onclick = () => {
win.maximize() // 窗口最大化
}
close.onclick = () => {
nw.App.quit() // 关闭软件
}
最大化窗口,是指最大化到我们设置的窗口最大尺寸。如果我们没有在package.json中设置最大尺寸,而把主页面的html
元素的宽高设置为100%, 100%, 最大化时就会撑满电脑桌面的可用区域(windows平台中会排除任务栏)。此外,还有win.enterFullscreen
接口可以考虑使用,这个接口使得窗口全屏显示,windows中会覆盖掉任务栏。
窗口恢复操作
之前提到拖拽条双击可以放大、再点击可以恢复,我们希望当点击“最大化”按钮后,再次点击可以恢复窗口大小。(之前的代码只实现了最大化功能)这里需要用到win.restore
接口。接下来的问题是,我们该如何确定窗口当前是最大化。
如果使用 win.enterFullscreen
全屏显示,那么可以通过win.isFullscreen
来判断当前窗口是否全屏。
如果使用win.maximize
最大化窗口,是不会触发win.isFullscreen
的改变的,但是我们可以监听到窗口实例的maximize事件,而当调用win.restore
触发窗口实例的restore事件。结合这两个事件就可以判断当前窗口是否最大化。
现在把窗口控制部分的js代码补充完整,如下所示:
let min, max, close, win
let flag = false // 标识当前的窗口是否最大化
min = document.getElementById('min')
max = document.getElementById('max')
close = document.getElementById('close')
win = nw.Window.get()
min.onclick = () => {
win.minimize()
}
max.onclick = () => {
if (flag) {
win.restore() // 如果是最大化,则恢复窗口
} else {
win.maximize() // 否则,最大化窗口
}
}
close.onclick = () => {
nw.App.quit()
}
// 监听窗口最大化事件
win.on('maximize', () => {
flag = true
})
// 监听窗口恢复事件
win.on('restore', () => {
flag = false
})
拖拽条双击放大触发的是maximize事件,双击恢复触发的是restore事件。和我们上面实现的点击按钮的功能完全兼容,可以随意的操作窗口了。但是如果使用win.isFullscreen
,它和拖拽条的双击功能并不兼容。
动态设置窗口最大尺寸
前面提到
如果我们没有在package.json中设置最大尺寸,而把主页面的
html
元素的宽高设置为100%, 100%, 最大化时就会撑满电脑桌面的可用区域(windows平台中会排除任务栏)。
我们可以使用win.setMaximumSize
接口动态设置窗口的最大尺寸,调用的时候把最大宽和最大高的数值传递进去,比如:
let { availHeight, availWidth } = win.window.screen // 获取电脑桌面的可用高度和可用宽度(排除任务栏)
win.setMaximumSize(availWidth, availHeight) // 设置窗口的最大尺寸
win.maximize() // 进行最大化操作
结束。