Electron for鸿蒙pc项目实战之图片查看器应用
欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
前言
Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台桌面应用程序的开源框架。通过将 Chromium 渲染引擎和 Node.js 运行时嵌入到二进制文件中,Electron 允许开发者使用统一的 Web 技术栈,创建可在 Windows、macOS、Linux 和 HarmonyOS 上运行的原生桌面应用。
系统要求
开发环境要求
- 操作系统: Windows 10/11、macOS 10.15+、Ubuntu 22.04+
- IDE: DevEco Studio 5.0+ (鸿蒙官方 IDE)
- Node.js: 建议 v18.x 或更高版本
- 内存: 至少 8GB RAM(推荐 16GB)
- 存储空间: 至少 20GB 可用空间
- 目标设备要求
- 鸿蒙设备: HarmonyOS NEXT (API 20)
- 设备类型: 平板电脑或 2in1 设备
- 连接方式: USB Type-C 数据线
重要提示: 如果需要从源码编译 Electron,必须使用 Ubuntu 22.04 环境。但对于大多数开发场景,直接使用预编译产物即可。
鸿蒙 Electron 框架导入操作指南
这里可以参考之前的文章:
Electron 鸿蒙pc开发环境搭建完整保姆级教程(window):
https://blog.csdn.net/m0_61243965/article/details/155104889
项目概述
本项目是一个基于Electron框架开发的轻量级图片查看器应用,专为鸿蒙PC平台设计与优化。该应用提供直观的图片浏览体验,支持多种图片格式,具备缩放、拖拽、全屏等核心功能,同时采用简洁易用的用户界面。

功能特点
- 多格式支持:兼容JPG、PNG、GIF、BMP、WebP、SVG等主流图片格式
- 图片操作:支持图片放大、缩小、实际尺寸显示和窗口自适应
- 浏览功能:多图片连续浏览,支持上一张/下一张快速切换
- 文件操作:通过文件对话框打开和保存图片文件
- 拖放支持:支持将图片文件直接拖入应用窗口打开
- 信息查看:显示图片的详细信息(尺寸、大小、路径等)
- 键盘快捷键:丰富的快捷键操作,提升使用效率
- 全屏模式:支持全屏浏览图片,提供沉浸式体验
- 响应式设计:自适应不同窗口大小,保持良好显示效果
- 鸿蒙PC适配:针对鸿蒙PC平台进行交互优化和兼容性处理
技术架构
核心架构
- 主进程 (Main Process):由
main.js实现,负责应用生命周期管理、窗口创建和系统级交互 - 渲染进程 (Renderer Process):由
renderer.js实现,负责UI渲染、用户交互和图片处理逻辑 - 预加载脚本 (Preload Script):由
preload.js实现,提供主进程与渲染进程间的安全通信桥接
文件结构
08-image-viewer/
├── main.js # 主进程文件,应用入口
├── preload.js # 预加载脚本,进程间通信
├── renderer.js # 渲染进程逻辑,处理UI交互
├── index.html # 应用界面结构
├── style.css # 样式文件,定义界面外观
├── assets/ # 资源目录,包含图标等
└── README.md # 项目说明文档
鸿蒙适配后结构(整合到Electron鸿蒙项目模板):
ohos_hap/
├── electron/
│ ├── libs/
│ │ └── arm64-v8a/ # 鸿蒙核心库文件
│ │ ├── libelectron.so
│ │ ├── libadapter.so
│ │ ├── libffmpeg.so
│ │ └── libc++_shared.so
├── web_engine/
│ └── src/
│ └── main/
│ └── resources/
│ └── resfile/
│ └── resources/
│ └── app/ # 放置electron应用代码
│ ├── main.js
│ ├── preload.js
│ ├── renderer.js
│ ├── index.html
│ ├── style.css
│ ├── package.json
│ └── assets/
└── module.json5 # 鸿蒙应用配置文件
核心代码解析
主进程 (main.js)
主进程负责应用的基础架构,包括窗口管理、文件对话框和进程间通信:
// 创建应用窗口
function createWindow() {
mainWindow = new BrowserWindow({
width: 1000,
height: 800,
minWidth: 600,
minHeight: 400,
title: '图片查看器',
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: false, // 禁用节点集成,增强安全性
contextIsolation: true // 启用上下文隔离
},
icon: path.join(__dirname, 'assets', 'icon.png')
});
// 加载应用界面
mainWindow.loadFile('index.html');
}
// 处理文件打开对话框
ipcMain.handle('open-file-dialog', async () => {
const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, {
properties: ['openFile', 'multiSelections'],
filters: [
{ name: '图片文件', extensions: ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'] },
{ name: '所有文件', extensions: ['*'] }
]
});
return { canceled, filePaths };
});
主进程还实现了单实例锁机制,确保只有一个应用实例运行,并处理通过命令行或拖放打开的图片文件。
预加载脚本 (preload.js)
预加载脚本作为安全的通信桥梁,暴露必要的API给渲染进程:
const { contextBridge, ipcRenderer } = require('electron');
// 安全暴露API给渲染进程
contextBridge.exposeInMainWorld('electronAPI', {
// 打开文件对话框
openFileDialog: () => ipcRenderer.invoke('open-file-dialog'),
// 保存文件对话框
saveFileDialog: () => ipcRenderer.invoke('save-file-dialog'),
// 监听文件打开事件
onOpenFile: (callback) => {
const unwrapCallback = (event, ...args) => callback(...args);
ipcRenderer.on('open-file', unwrapCallback);
return () => ipcRenderer.removeListener('open-file', unwrapCallback);
},
// 应用信息
appVersion: '1.0.0',
platform: process.platform
});
// 暴露应用基本信息
contextBridge.exposeInMainWorld('appInfo', {
name: '图片查看器',
version: '1.0.0',
description: '基于Electron的图片查看应用'
});
渲染进程 (renderer.js)
渲染进程实现了图片查看器的核心功能,包括图片加载、缩放、拖拽等交互逻辑:
- 图片加载与管理
// 加载图片列表
function loadImages(filePaths) {
if (!filePaths || filePaths.length === 0) return;
// 过滤支持的图片格式
const supportedExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'];
state.imageList = filePaths.filter(path => {
const ext = path.toLowerCase().substr(path.lastIndexOf('.'));
return supportedExtensions.includes(ext);
});
if (state.imageList.length === 0) {
showNotification('没有找到支持的图片文件', 'info');
return;
}
state.currentImageIndex = 0;
loadCurrentImage();
}
// 加载当前图片
function loadCurrentImage() {
if (state.imageList.length === 0 || state.currentImageIndex < 0) return;
const imagePath = state.imageList[state.currentImageIndex];
// 显示加载指示器
elements.loader.classList.add('show');
// 预加载图片
const img = new Image();
img.onload = () => {
elements.currentImage.src = imagePath;
elements.currentImage.width = img.width;
elements.currentImage.height = img.height;
resetPosition();
fitToWindow(); // 自动适应窗口
};
img.onerror = handleImageError;
img.src = imagePath;
}
- 缩放与拖拽功能
// 更新缩放
function updateZoom(zoom) {
state.currentZoom = zoom;
elements.zoomValue.textContent = `${zoom}%`;
elements.imageWrapper.style.transform =
`scale(${zoom / 100}) translate(${state.currentPosition.x}px, ${state.currentPosition.y}px)`;
updateButtonStates();
}
// 设置鼠标拖拽
function setupMouseDrag() {
elements.imageWrapper.addEventListener('mousedown', (e) => {
if (e.target === elements.currentImage || e.target === elements.imageWrapper) {
state.isDragging = true;
state.lastMouseX = e.clientX;
state.lastMouseY = e.clientY;
elements.imageWrapper.classList.add('dragging');
}
});
document.addEventListener('mousemove', (e) => {
if (!state.isDragging) return;
const deltaX = e.clientX - state.lastMouseX;
const deltaY = e.clientY - state.lastMouseY;
state.currentPosition.x += deltaX;
state.currentPosition.y += deltaY;
elements.imageWrapper.style.transform =
`scale(${state.currentZoom / 100}) translate(${state.currentPosition.x}px, ${state.currentPosition.y}px)`;
state.lastMouseX = e.clientX;
state.lastMouseY = e.clientY;
});
document.addEventListener('mouseup', () => {
state.isDragging = false;
elements.imageWrapper.classList.remove('dragging');
});
}
- 拖放支持
// 设置拖拽功能
function setupDragAndDrop() {
document.addEventListener('dragover', (e) => {
e.preventDefault();
elements.dropZone.classList.add('active');
});
document.addEventListener('dragleave', () => {
elements.dropZone.classList.remove('active');
});
document.addEventListener('drop', (e) => {
e.preventDefault();
elements.dropZone.classList.remove('active');
if (e.dataTransfer.files.length > 0) {
const filePaths = Array.from(e.dataTransfer.files).map(file => file.path);
loadImages(filePaths);
}
});
}
用户界面 (index.html & style.css)
应用界面采用简洁现代的设计,主要包含:
- 菜单栏:提供文件操作、导航和视图控制按钮
- 图片显示区:核心区域,用于展示图片和拖放操作
- 状态栏:显示文件信息、图片尺寸和导航信息
- 信息模态框:展示图片详细信息
- 加载指示器:提供图片加载状态反馈
样式设计采用深色主题,减少图片浏览时的视觉干扰,并通过响应式设计确保在不同尺寸的窗口上都有良好表现。
技术要点
安全最佳实践
- 上下文隔离:启用
contextIsolation: true,确保渲染进程无法直接访问Node.js API - 预加载脚本桥接:通过
preload.js安全地暴露必要功能,避免直接暴露ipcRenderer - 禁用节点集成:设置
nodeIntegration: false,防止恶意代码利用Node.js API - 文件类型验证:严格验证打开的文件类型,防止加载非图片文件
用户体验优化
- 渐进式加载:使用预加载机制,在图片完全加载前显示加载指示器
- 交互反馈:提供清晰的拖拽状态、缩放比例和导航信息
- 错误处理:图片加载失败时提供友好提示,并自动尝试加载下一张
- 键盘支持:丰富的快捷键提高操作效率,如方向键切换图片、±键缩放等
- 自适应布局:图片自动适应窗口大小,同时支持手动调整
性能优化
- 图片预加载:提前加载图片资源,减少用户等待时间
- 事件节流:对resize等高频事件进行优化处理
- 资源清理:窗口关闭时释放资源,避免内存泄漏
- 惰性加载:只加载当前需要显示的图片,节省系统资源
开发与调试
开发环境设置
- 克隆项目到本地
- 安装依赖:
npm install - 启动应用:
npm start
调试技巧
- 渲染进程调试:使用
Ctrl+Shift+I打开Chrome DevTools - 主进程调试:启动时添加
--inspect参数,通过Chrome访问chrome://inspect - 日志查看:使用
console.log()输出关键信息,在终端查看 - 样式调试:利用DevTools的Elements面板实时调整CSS样式
扩展功能建议
- 幻灯片播放:添加自动播放功能,支持设置播放间隔
- 图片编辑:基础编辑功能如旋转、裁剪、调整亮度对比度
- 批量处理:批量转换格式、重命名、压缩图片
- 主题切换:支持明暗主题切换,适应不同使用环境
- 图片对比:支持同时显示多张图片进行对比
- EXIF信息查看:显示照片的拍摄参数等详细元数据
- 收藏功能:标记常用图片,方便快速访问
鸿蒙PC适配改造指南
详细操作指南请看这篇文章:
Electron 鸿蒙pc开发环境搭建完整保姆级教程(window)
1. 环境准备
- 系统要求:Windows 10/11、8GB RAM以上、20GB可用空间
- 工具安装:
- DevEco Studio 5.0+(安装鸿蒙SDK API 20+)
- Node.js 18.x+
2. 获取Electron鸿蒙编译产物
- 登录Electron 鸿蒙官方仓库
- 下载Electron 34+版本的Release包(.zip格式)
- 解压到项目目录,确认
electron/libs/arm64-v8a/下包含核心.so库
3. 部署应用代码
将Electron应用代码按以下目录结构放置:
web_engine/src/main/resources/resfile/resources/app/
├── main.js
├── preload.js
├── renderer.js
├── index.html
├── style.css
├── package.json
└── assets/
└── icon.png
4. 配置与运行
- 打开项目:在DevEco Studio中打开ohos_hap目录
- 配置签名:
- 进入File → Project Structure → Signing Configs
- 自动生成调试签名或导入已有签名
- 连接设备:
- 启用鸿蒙设备开发者模式和USB调试
- 通过USB Type-C连接电脑
- 编译运行:点击Run按钮或按Shift+F10
5. 验证检查项
- ✅ 应用窗口正常显示,图标正确加载
- ✅ 支持通过文件对话框打开图片
- ✅ 拖放功能正常工作
- ✅ 所有缩放和导航功能正常
- ✅ 控制台无"SysCap不匹配"或"找不到.so文件"错误
- ✅ 响应式布局在不同窗口大小下正常生效
跨平台兼容性
| 平台 | 适配策略 | 特殊处理 |
|---|---|---|
| Windows | 标准Electron运行 | 无特殊配置 |
| macOS | 标准Electron运行 | 保留dock图标激活逻辑 |
| Linux | 标准Electron运行 | 确保系统依赖库完整 |
| 鸿蒙PC | 通过Electron鸿蒙适配层 | 禁用硬件加速,调整窗口创建参数 |
鸿蒙开发调试技巧
1. 日志查看
在DevEco Studio的Log面板中过滤"Electron"关键词,查看应用运行日志和错误信息,重点关注:
- 窗口创建过程中的错误
- 图片加载相关的异常
- IPC通信失败信息
2. 常见问题解决
- "SysCap不匹配"错误:检查module.json5中的reqSysCapabilities,确保包含"SystemCapability.WebEngine.Core"
- 图片显示异常:确认图片路径处理正确,鸿蒙系统中需使用绝对路径
- 拖放功能失效:在module.json5中添加文件访问权限
- 窗口大小异常:调整main.js中的初始窗口尺寸,确保适应鸿蒙PC屏幕
总结
本项目展示了如何使用Electron框架开发一个功能完整的图片查看器应用,涵盖了文件操作、图片处理、用户交互等核心功能。通过对鸿蒙PC平台的适配,验证了Electron应用跨平台运行的可行性。
项目代码结构清晰,注释完善,适合初学者学习Electron应用开发的基本概念和实践技巧,包括主进程与渲染进程的通信、UI设计、事件处理等关键技术点。
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
更多推荐
所有评论(0)