QQ首页的弹窗和天气效果都挺好,最近琢磨了一下用electron来仿造出这样的效果,主要是弹窗控件这块,也考虑了一下窗口的复用,下面展示一下做好后的效果,注:样式只是随便调了一下,毕竟没有那么多时间去弄样式
分析思路
制作思路首先是左边鼠标放到头像上显示出窗口并且带有动画效果,鼠标在两个窗口之间来回移动窗口会跟随移动并且切换内容,不难发现此时移动的时候是复用的一个窗口,这样可以减少创建窗口的开销,天气那里窗口反转用个路由动画就可以了
解决方案
解决方案直接写代码吧,这里使用了electron-vue和electron-vue-windows两个插件,如果不了解具体可以看这里electron-vue-windows,思路是通过reuse这个属性就可以直接让窗口复用,当调用closeWin()的时候实际上是吧窗口隐藏掉了,这样就减少了创建窗口的开销,窗口打开时的动画一个效果就搞定了,但是窗口已经打开只能通过移动动画来达到移动的效果,就是animation,所以我们要加一个判断如果窗口已经打开就移动没有打开的话就创建,代码如下:
openLeft (e, index) {
clearTimeout(this.timeTap)
let width = 300
// 获取当前窗口的宽高,用于定位子窗口位置
let fatherBounds = this.$Win.win.getBounds()
// 判断右边是否过界(计算出子窗口的坐标点)
let leftWidth = e.screenX - e.offsetX - width - 15
let x = leftWidth < 0 ? leftWidth + width + fatherBounds.width : leftWidth
let y = e.screenY - e.offsetY
// 查询子窗口是否存在
let win = this.$Win.getWinByName('leftname')
if (win) {
// 如果存在跳转路由,并重新发送数据
this.$Win.routerPush({
router: '/infoWindow/' + index,
win: win,
data: {name: index}
})
win.show()
// 动画过度到新位置
this.$Win.animation({
win: win,
time: 200,
to: {
x: x,
y: y
}
})
} else {
this.$store.dispatch('changeTransition', 'default')
// 不存在子窗口就新建窗口
win = this.$Win.createWin({
width: 300,
height: 200,
windowConfig: {
router: '/infoWindow/' + index,
name: 'leftname',
customAnimation: {
fromPosition: {x: x, y: y - 50},
time: 300 // 动画时间
},
data: {name: index},
reuse: true,
reload: true,
vibrancy: true
},
x: x,
y: y,
alwaysOnTop: true,
skipTaskbar: true
})
win.show()
}
}
另外一个天气窗口,注意qq的天气窗口是可以旋转的,所以此时是不能用背景模糊的窗口来做,只能使用透明窗口,那么反转的效果也很容易,直接写css就行了,代码如下:
showwindow () {
let fatherBounds = this.$Win.win.getBounds()
// 判断右边是否过界
let leftWidth = window.screen.width - fatherBounds.width - fatherBounds.x - 300
let x = leftWidth >= 0 ? fatherBounds.width + fatherBounds.x : fatherBounds.x - 300
let y = fatherBounds.y
let win = this.$Win.createWin({
width: 300,
height: 200,
x: x,
y: y,
windowConfig: {
router: '/cloudWindow',
vibrancy: false,
name: 'cloud',
animation: 'fromBottom'
}
})
win.show()
}
窗口反转的代码如果不懂可以看这里