# 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)