# g-snow
**Repository Path**: OliverDaDa/g-snow
## Basic Information
- **Project Name**: g-snow
- **Description**: 使用electron制作的下雪特效桌面应用
- **Primary Language**: JavaScript
- **License**: GPL-2.0
- **Default Branch**: master
- **Homepage**: https://gitee.com/OliverDaDa/g-snow/wikis/pages
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2020-03-31
- **Last Updated**: 2021-08-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[TOC]
---
> [Electron桌面下雪特效_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili](https://www.bilibili.com/video/BV14J411L7st/?p=2)
> [配套源码地址](https://github.com/plter/ScreenSnow)
---
# 一、构建环境
```bash
git clone https://github.com/atom/electron-quick-start
mv electronic-quick-start g-snow
cd g-snow
npm install && npm start
```
hello world 出现
# 二、窗口透明化
修改*main.js*
```js
mainWindow = new BrowserWindow({
alwaysOnTop: true, // 窗口始终置顶
frame: false, // 窗口无边框
transparent: true, // 窗体透明
resizable: false, // 窗口大小不可调
});
```
index.html中删掉多余内容后,添加样式:
```html
...
```
在main.js中引入electron
```js
const electron = require('electron')
```
接着获取屏幕尺寸
```js
function createWindow () {
let area = electron.screen.getPrimaryDisplay().workAreaSize;
...
```
并赋值给窗口
```js
const mainWindow = new BrowserWindow({
width: area.width,
height: area.height,
x:0,
y:0,
...
```
此时窗口布满全屏
# 三、添加雪花
- 引入资源文件并通过img标签添加到index.html中
```js
```
- 创建SnowFlower.js
```js
class SnowFlower{
constructor() {
this._img = document.createElement('img')
this._img.src = 'res/SnowFlower.png'
}
get img(){
return this._img
}
}
module.exports = SnowFlower
```js
在renderer.js中引入SnowFlower类,并创建“雪花元素”
```js
const SnowFlower = require('./SnowFlower.js')
document.body.appendChild(new SnowFlower().img)
```
在main.js中添加允许使用node.js
```js
const mainWindow = new BrowserWindow({
...
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true // 允许使用node.js
}
```
# 四、移动雪花
在SnowFlower类的构造方法中初始化雪花位置和速度
```js
this.x = 0
this.y = 0
this.speedX = 1
this.speedY = 1
```
在类中创建move函数
```js
move(){
this.x += this.speedX
this.y += this.speedY
this.img.style.transform = `translate(${this.x}px,${this.y}px)`
requestAnimationFrame(this.moveBindThis)
}
```
在构造方法里把move()函数绑定上下文对象,以确保move方法中可以通过this进行回调
```js
this.moveBindThis = this.move.bind(this)
```
在构造方法里通过绑定方法执行move函数
```js
this.moveBindThis()
```
此时运行就可以看到雪花移动了,附上SnowFlower.js目前全部代码
```js
class SnowFlower{
constructor() {
this._img = document.createElement('img')
this._img.src = 'res/snowflower.png'
this.x = 0
this.y = 0
this.speedX = 1
this.speedY = 1
this.moveBindThis = this.move.bind(this)
this.moveBindThis()
}
get img(){
return this._img
}
move(){
this.x += this.speedX
this.y += this.speedY
this.img.style.transform = `translate(${this.x}px,${this.y}px)`
requestAnimationFrame(this.moveBindThis)
}
}
module.exports = SnowFlower
```
# 五、雪花旋转
在SnowFlower类的构造方法中初始化雪花旋转角度和速度
```js
this.rotation = 0
this.speedRotation = 1
```
在move方法中添加
```js
this.rotation += this.speedRotation
```
并修改
```js
this.img.style.transform = `translate(${this.x}px,${this.y}px)`
```
=>
```js
this.img.style.transform = `translate(${this.x}px,${this.y}px) rotate(${this.rotation}deg)`
```
查看效果,现在雪花边旋转边移动,附上SnowFlower.js目前全部代码
```js
class SnowFlower{
constructor() {
this._img = document.createElement('img')
this._img.src = 'res/snowflower.png'
this.x = 0
this.y = 0
this.speedX = 1
this.speedY = 1
this.rotation = 0
this.speedRotation = 1
this.moveBindThis = this.move.bind(this)
this.moveBindThis()
}
get img(){
return this._img
}
move(){
this.x += this.speedX
this.y += this.speedY
this.rotation += this.speedRotation
this.img.style.transform = `translate(${this.x}px,${this.y}px) rotate(${this.rotation}deg)`
requestAnimationFrame(this.moveBindThis)
}
}
module.exports = SnowFlower
```
# 六、参数随机
在SnowFlower类的构造方法中修改雪花的旋转方向和速度为随机
```js
this.speedRotation = (Math.random() + 1) * (Math.random() > 0.5 ? 1 : -1)
```
在renderer.js中,将引入雪花的语句嵌套进循环中,来增加雪花数量
```js
for(let i=0;i<12;i++){
document.body.appendChild(new SnowFlower().img)
}
```
在index.html中使用css初始化雪花位置
```css
img {
display: block;
position: fixed;
}
```
在SnowFlower类的构造方法中调整雪花速度随机
```js
this.speedX = (Math.random() + 1)/5 * (Math.random() > 0.5 ? 1 : -1)
this.speedY = (Math.random() + 1)/2
```
雪花大小随机
```js
this._img.width = Math.random() * 7 + 3
```
要想雪花初始位置随机需要先获取屏幕尺寸信息
在SnowFlower类文件中引入electron
```js
const electron = require('electron')
const workAreaSize = electron.remote.screen.getPrimaryDisplay().workAreaSize
```
在SnowFlower类的构造方法中设置雪花初始位置随机
```js
this.x = Math.random() * workAreaSize.width
```
在move()方法中设置雪花越界移除,并在不越界的情况下才继续移动
```js
if(this.x > workAreaSize.width || this.x < 0 || this.y > workAreaSize.height){
if(this._img.parentNode){
this._img.parentNode.removeChild(this._img)
}
}else{
requestAnimationFrame(this.moveBindThis)
}
```
# 七、完成下雪特效
持续制造雪花:每隔1秒制造一次,将制造雪花代码嵌套进去
*renderer.js*
```js
setInterval(()=>{
for(let i=0;i<10;i++){
document.body.appendChild(new SnowFlower().img)
}
},1000)
```
在SnowFlower类的构造方法中将“天空”抬高一些,显得更自然一些
```js
this.y = -20
```
让雪花特效不影响正常电脑使用:忽略鼠标事件
*main.js*
```js
function createWindow () {
...
mainWindow.setIgnoreMouseEvents(true) // 忽略鼠标事件
...
}
```
去掉背景色
完成!
# 八、打包成可执行文件
## 打包方法1
下载打包器
```bash
cnpm i -g electron-packager
```
直接打包
```
electron-packager . 'g-snow' --platform=win32 --arch=x64 --icon=snow.ico --out=./out --asar --app-version=0.0.1
```
或是配置package.json的scripts
```
"scripts": {
...
"pkg": "electron-packager . g-snow --platform=win32 --arch=x64 --icon=snow.ico --out=./out --asar --app-version=0.0.1"
},
```
在命令行中执行`npm run pkg`
尝试并没有成功,发现了第二种更好的方法,舍弃第一种。。。
## 打包方法2
在package.json中做如下配置
```json
"build": {
"productName":"桌面雪花生成器",
"appId": "top.aimooc.app",
"mac": {
"target": ["dmg","zip"]
},
"win": {
"target": ["nsis","zip"]
},
"nsis": {
"oneClick": false,
"allowElevation": true,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true
},
"files": ["**/*","res/snowflower.png"]
},
"scripts": {
"start": "electron .",
"pkg": "electron-packager . g-snow --platform=win32 --arch=x64 --icon=icon.ico --out=./out --asar --app-version=0.0.1",
"dist": "electron-builder --win --x64"
},
```
在命令行中执行`npm run dist `
配置的详细解释参见:[electron打包(electron-builder/electron-packager)及打包过程中的报错解决](https://blog.csdn.net/qq_32682301/article/details/105222411)
打包过程中出现因网络原因导致的报错参见:[electron-builder打包过程中报错——网络下载篇](https://blog.csdn.net/qq_32682301/article/details/105234408)
# 九、全部代码展示
## 工程目录
```tree
.
|-- README.md
|-- SnowFlower.js
|-- icon.ico
|-- index.html
|-- main.js
|-- package.json
|-- preload.js
|-- renderer.js
`-- res
`-- snowflower.png
```
## package.json
```json
{
"name": "g-snow",
"version": "1.0.0",
"description": "下雪特效",
"main": "main.js",
"build": {
"productName":"桌面雪花生成器",
"appId": "top.aimooc.app",
"mac": {
"target": ["dmg","zip"]
},
"win": {
"target": ["nsis","zip"]
},
"nsis": {
"oneClick": false,
"allowElevation": true,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true
},
"files": ["**/*","res/snowflower.png"]
},
"scripts": {
"start": "electron .",
"pkg": "electron-packager . g-snow --platform=win32 --arch=x64 --icon=icon.ico --out=./out --asar --app-version=0.0.1",
"dist": "electron-builder --win --x64"
},
"repository": "https://gitee.com/OliverDaDa/g-snow",
"keywords": [
"Electron",
"quick",
"start",
"snow",
"demo"
],
"author": "AImooc-Oliver",
"license": "CC0-1.0",
"devDependencies": {
"electron": "^8.2.0"
}
}
```
## index.html
```html
g-snow
```
## main.js
```js
const {app, BrowserWindow} = require('electron')
const path = require('path')
const electron = require('electron')
// var globalShortcut = electron.globalShortcut
function createWindow () {
let area = electron.screen.getPrimaryDisplay().workAreaSize;
// Create the browser window.
const mainWindow = new BrowserWindow({
width: area.width,
height: area.height,
x:0,
y:0,
alwaysOnTop: true, // 窗口始终置顶
frame: false, // 窗口无边框
transparent: true, // 窗体透明
resizable: false, // 窗口大小不可调
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true // 允许使用node.js
}
})
mainWindow.setIgnoreMouseEvents(true) // 忽略鼠标事件
mainWindow.loadFile('index.html')
// globalShortcut.register('ctrl+e',()=>{
// mainWindow.webContents.openDevTools()
// })
}
app.whenReady().then(createWindow)
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
```
## SnowFlower.js
```js
const electron = require('electron')
const workAreaSize = electron.remote.screen.getPrimaryDisplay().workAreaSize
class SnowFlower{
constructor() {
this._img = document.createElement('img')
this._img.src = 'res/snowflower.png'
this._img.width = Math.random() * 7 + 3
this.x = Math.random() * workAreaSize.width
this.y = -20
this.speedX = (Math.random() + 1)/7 * (Math.random() > 0.5 ? 1 : -1)
this.speedY = (Math.random() + 1)
this.rotation = 0
this.speedRotation = (Math.random() + 1) * (Math.random() > 0.5 ? 1 : -1)
this.moveBindThis = this.move.bind(this)
this.moveBindThis()
}
get img(){
return this._img
}
move(){
this.x += this.speedX
this.y += this.speedY
this.rotation += this.speedRotation
this.img.style.transform = `translate(${this.x}px,${this.y}px) rotate(${this.rotation}deg)`
if(this.x > workAreaSize.width || this.x < 0 || this.y > workAreaSize.height){
if(this._img.parentNode){
this._img.parentNode.removeChild(this._img)
}
}else{
requestAnimationFrame(this.moveBindThis)
}
}
}
module.exports = SnowFlower
```
## renderer.js
```js
const SnowFlower = require('./SnowFlower.js')
setInterval(()=>{
for(let i=0;i<12;i++){
document.body.appendChild(new SnowFlower().img)
}
},1000)
```
PS:打包后以及编写过程中可在**main.js**中写如下代码创建打开**DevTools**的快捷键`ctrl+e`来快速debug(记得注释掉 *忽略鼠标事件* 的代码)
```
// var globalShortcut = electron.globalShortcut
function createWindow () {
...
// globalShortcut.register('ctrl+e',()=>{
// mainWindow.webContents.openDevTools()
// })
}
```
---
完整项目地址:[g-snow](https://gitee.com/OliverDaDa/g-snow)
成品下载地址:[桌面雪花生成器 Setup 1.0.0.exe](https://download.csdn.net/download/qq_32682301/12292380)
---
制作过程中使用到的网站,在此感谢!!
> [在线生成透明ICO图标——ICO图标制作](http://ico.duduxuexi.com/)
> [electron/electron-quick-start](https://github.com/electron/electron-quick-start)
> [Electron桌面下雪特效_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili](https://www.bilibili.com/video/BV14J411L7st/?p=2)