- A+
所属分类:.NET技术
前一段时间我用 WPF 开发了一个查看 emoji 表情的小工具 https://github.com/he55/EmojiViewer ,由于最近我使用 macOS 系统比较多,我想能在 macOS 系统上也能使用这个工具。于是我尝试将 WPF 应用迁移到 Electron 框架,感觉这个框架很强大,在这里记录一下应用迁移的过程。
安装 Electron 环境
- 安装 nodejs。到官网 https://nodejs.org/en 下载最新的 nodejs,然后安装
- 打开命令行输入
git clone https://github.com/electron/electron-quick-start.git
命令克隆 Electron 模板项目,使用模板可以快速搭建应用。 - 然后使用
cd electron-quick-start
目录进入到目录,接着运行npm install
命令还原项目。 - 使用 vscode 打开文件夹,项目文件如下
编写代码
- Electron 分为主进程和渲染进程,对文件、系统和窗口的操作需要在主线程,界面渲染在渲染进程。创建窗口属于主进程的工作,需要到
main.js
文件编写代码。创建窗口使用BrowserWindow
对象,width
和height
分别设置窗口宽度和高度,autoHideMenuBar
设置是否隐藏菜单,最后使用loadFile
加载页面文件并显示窗口。
function createWindow() { const mainWindow = new BrowserWindow({ width: 915, height: 560, autoHideMenuBar: true, webPreferences: { preload: path.join(__dirname, 'preload.js') } }) mainWindow.loadFile('index.html') }
- 监听
whenReady
事件,等待应用初始化完成后显示窗口
app.whenReady().then(() => { createWindow() app.on('activate', function () { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) })
- 修改
index.html
文件,界面部分使用了 vue 进行渲染
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="vue.global.js"></script> <link href="./styles.css" rel="stylesheet"> <title>EmojiViewer</title> </head> <body> <div id="app" class="container"> <ul class="left"> <li v-for="(item, key) in categories" :class="{active: item.isActive}" @click="catetoryItemClick(item)">{{ key }}</li> </ul> <ul class="main" ref="mainElement"> <li v-for="emoji in emojis" :class="{active: emoji.isActive}" @click="emojiItemClick(emoji)"> <img :src="emoji.previewImage" alt=""> <p>{{emoji.name}}</p> </li> </ul> <div class="right"> <img :src="selectedEmoji.previewImage"> <p>{{ selectedEmoji.name }}</p> <button @click="copyEmoji(selectedEmoji)" type="button">Copy Emoji</button> <button @click="copyImage(selectedEmoji)" type="button">Copy Image</button> <button @click="openFile(selectedEmoji)" type="button">Open File</button> </div> </div> <script src="./renderer.js"></script> </body> </html>
- 在
renderer.js
文件中编写页面处理代码
window.addEventListener('DOMContentLoaded', async () => { const { createApp, ref, onMounted } = Vue let emojiData = await ipc.getData() createApp({ setup() { const mainElement = ref(null) const categories = ref(emojiData) const emojis = ref([]) const selectedEmoji = ref({}) function copyEmoji(emoji) { ipc.ipc('writeText', emoji.metadata.glyph) } function copyImage(emoji) { ipc.ipc('writeImage', emoji.previewImage) } function openFile(emoji) { ipc.ipc('showItemInFolder', emoji.previewImage) } let lastSelectedEmojis function catetoryItemClick(items) { if (lastSelectedEmojis) { lastSelectedEmojis.isActive = false } items.isActive = true lastSelectedEmojis = items // const main = document.querySelector('.main') mainElement.value.scrollTop = 0 emojis.value = items } function emojiItemClick(emoji) { if (selectedEmoji.value) { selectedEmoji.value.isActive = false } emoji.isActive = true selectedEmoji.value = emoji } onMounted(() => { catetoryItemClick(emojiData['Activities']) emojiItemClick(emojiData['Activities'][0]) }) return { mainElement, categories, emojis, selectedEmoji, catetoryItemClick, emojiItemClick, copyEmoji, copyImage, openFile, } } }).mount('#app') })
- 读取文件,node 提供了文件操作相关的 api 可以很方便的操作文件系统。
function loadData(assetPath) { const dirs = fs.readdirSync(assetPath) const data = [] const groupData = {} for (const dir of dirs) { const fullPath = path.resolve(assetPath, dir) const metadata = require(path.resolve(fullPath, 'metadata.json')) let previewImage let imagePaths = [path.resolve(fullPath, '3D'), path.resolve(fullPath, 'Default', '3D')] for (const imagePath of imagePaths) { if (fs.existsSync(imagePath)) { let files = fs.readdirSync(imagePath) if (files.length === 0) return previewImage = path.resolve(imagePath, files[0]) } } const { unicode, group } = metadata const obj = { metadata, id: unicode, name: dir, previewImage, } data.push(obj) if (!groupData[group]) groupData[group] = [] groupData[group].push(obj) } return groupData }
完整代码(WPF 版本) https://github.com/he55/EmojiViewer
完整代码(vue 版本) https://github.com/he55/web-learn/tree/main/9.electron-emoji-viewer(vue)
完整代码(js 原生版本) https://github.com/he55/web-learn/tree/main/6.electron-emoji-viewer