欢迎加入开源鸿蒙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)

渲染进程实现了图片查看器的核心功能,包括图片加载、缩放、拖拽等交互逻辑:

  1. 图片加载与管理
// 加载图片列表
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;
}
  1. 缩放与拖拽功能
// 更新缩放
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');
  });
}
  1. 拖放支持
// 设置拖拽功能
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等高频事件进行优化处理
  • 资源清理:窗口关闭时释放资源,避免内存泄漏
  • 惰性加载:只加载当前需要显示的图片,节省系统资源

开发与调试

开发环境设置

  1. 克隆项目到本地
  2. 安装依赖:npm install
  3. 启动应用:npm start

调试技巧

  • 渲染进程调试:使用Ctrl+Shift+I打开Chrome DevTools
  • 主进程调试:启动时添加--inspect参数,通过Chrome访问chrome://inspect
  • 日志查看:使用console.log()输出关键信息,在终端查看
  • 样式调试:利用DevTools的Elements面板实时调整CSS样式

扩展功能建议

  1. 幻灯片播放:添加自动播放功能,支持设置播放间隔
  2. 图片编辑:基础编辑功能如旋转、裁剪、调整亮度对比度
  3. 批量处理:批量转换格式、重命名、压缩图片
  4. 主题切换:支持明暗主题切换,适应不同使用环境
  5. 图片对比:支持同时显示多张图片进行对比
  6. EXIF信息查看:显示照片的拍摄参数等详细元数据
  7. 收藏功能:标记常用图片,方便快速访问

鸿蒙PC适配改造指南

详细操作指南请看这篇文章:
Electron 鸿蒙pc开发环境搭建完整保姆级教程(window)

1. 环境准备

  • 系统要求:Windows 10/11、8GB RAM以上、20GB可用空间
  • 工具安装
    • DevEco Studio 5.0+(安装鸿蒙SDK API 20+)
    • Node.js 18.x+

2. 获取Electron鸿蒙编译产物

  1. 登录Electron 鸿蒙官方仓库
  2. 下载Electron 34+版本的Release包(.zip格式)
  3. 解压到项目目录,确认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. 配置与运行

  1. 打开项目:在DevEco Studio中打开ohos_hap目录
  2. 配置签名
    • 进入File → Project Structure → Signing Configs
    • 自动生成调试签名或导入已有签名
  3. 连接设备
    • 启用鸿蒙设备开发者模式和USB调试
    • 通过USB Type-C连接电脑
  4. 编译运行:点击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/

Logo

赋能鸿蒙PC开发者,共建全场景原生生态,共享一次开发多端部署创新价值。

更多推荐