
个人首页: VON
鸿蒙系列专栏: 鸿蒙开发小型案例总结
综合案例 :鸿蒙综合案例开发
鸿蒙6.0:从0开始的开源鸿蒙6.0.0
鸿蒙5.0:鸿蒙5.0零基础入门到项目实战
本文章所属专栏:Electron for HarmonyOS
文章专属视频教程:别再拉伸图片了!教你3秒保持原比例缩放
纯图片尺寸调节工具(支持锁定纵横比)
- 前言
- 功能概述
- ✅ 功能清单
- 项目结构
- 完整代码
- 1. `main.js`(主进程)
- 2. `preload.js`(安全暴露 API)
- 3. `index.html`(核心功能)
- 4. `package.json`
- ▶️ 如何运行?
- 技术亮点
- 鸿蒙部分
- 测试
- ✅ 总结

前言
通过前面两篇文章的学习想必大家已经对Electron有所了解了,接下来仅进入实战环节。
先说一下为何做这么一个项目?
不知道大家有没有遇到这种情况,就是有些网页需要指定图片尺寸才可以进行上传,网上也有这样的网页但是网上那些网页不是广告就是付费,真正实现免费的并不多,我在wps上面以及电脑自带的图库上面也都没有找到类似的功能,所以就自己开发了一个,可以直接运行到我的真机上面,也可以打包成应用程序供大家来使用
功能概述
一句话功能:上传图片 → 输入目标尺寸 → 自动/手动缩放 → 保存高清结果
✅ 功能清单
| 功能 | 说明 |
|---|---|
| 图片上传 | 支持 JPG / PNG / WebP 等常见格式 |
| 尺寸输入 | 可分别设置宽度和高度(单位:px) |
| 锁定纵横比 | 勾选后修改宽/高自动计算另一值 |
| 高质量缩放 | 使用 Canvas 高质量重绘(非简单拉伸) |
| 一键保存 | 导出为 PNG(透明通道保留) |
项目结构
image-resize-app/
├── main.js # 主进程:窗口 + 文件保存
├── preload.js # 安全桥接 API
├── index.html # 前端界面 + 缩放逻辑
└── package.json
完整代码
1. main.js(主进程)
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
const path = require('path');
const fs = require('fs');
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 650,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true
}
});
win.loadFile('index.html');
}
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
// 保存图片到本地
ipcMain.handle('save-image', async (_, { dataUrl }) => {
const { canceled, filePath } = await dialog.showSaveDialog({
filters: [
{ name: 'PNG', extensions: ['png'] },
{ name: 'JPEG', extensions: ['jpg', 'jpeg'] }
]
});
if (!canceled && filePath) {
const buffer = Buffer.from(dataUrl.split(',')[1], 'base64');
fs.writeFileSync(filePath, buffer);
return filePath;
}
});
2. preload.js(安全暴露 API)
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('api', {
saveImage: (data) => ipcRenderer.invoke('save-image', data)
});
3. index.html(核心功能)
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>图片尺寸调节工具</title><style>body {font-family: -apple-system, BlinkMacSystemFont, sans-serif;margin: 0;padding: 20px;background: #f9fafb;}.container {max-width: 750px;margin: 0 auto;background: white;border-radius: 12px;box-shadow: 0 4px 12px rgba(0,0,0,0.08);padding: 25px;}h1 {text-align: center;color: #2d3748;margin-bottom: 25px;}.controls {display: flex;flex-wrap: wrap;gap: 15px;align-items: center;margin-bottom: 20px;}.input-group {display: flex;align-items: center;gap: 8px;}input[type="number"] {width: 90px;padding: 6px 8px;border: 1px solid #cbd5e0;border-radius: 6px;font-size: 14px;}label {display: flex;align-items: center;gap: 6px;font-size: 14px;color: #4a5568;}button {padding: 8px 18px;background: #3182ce;color: white;border: none;border-radius: 6px;cursor: pointer;font-size: 14px;}button:hover { background: #2c5aa0; }button:disabled {background: #cbd5e0;cursor: not-allowed;}canvas {width: 100%;height: auto;border: 1px solid #e2e8f0;border-radius: 8px;background: #f8fafc;margin-top: 10px;}.info {text-align: center;color: #718096;font-size: 13px;margin-top: 12px;}</style></head><body><div class="container"><h1> 图片尺寸调节工具</h1><div class="controls"><input type="file" id="imageInput" accept="image/*"><div class="input-group"><label>宽:</label><input type="number" id="widthInput" min="1" value="800"><span>×</span><input type="number" id="heightInput" min="1" value="600"><label><input type="checkbox" id="aspectLock" checked> 锁定比例</label></div><button id="saveBtn" disabled> 保存图片</button></div><canvas id="outputCanvas"></canvas><p class="info">上传图片后,可自由调整尺寸。勾选“锁定比例”避免图像变形。</p></div><script>const imageInput = document.getElementById('imageInput');const widthInput = document.getElementById('widthInput');const heightInput = document.getElementById('heightInput');const aspectLock = document.getElementById('aspectLock');const saveBtn = document.getElementById('saveBtn');const canvas = document.getElementById('outputCanvas');const ctx = canvas.getContext('2d');let originalImage = null;let originalRatio = 1;// 修改宽度时联动高度(如果锁定比例)widthInput.addEventListener('input', () => {if (aspectLock.checked && originalImage) {const w = parseInt(widthInput.value) || 1;heightInput.value = Math.round(w / originalRatio);}render();});// 修改高度时联动宽度(如果锁定比例)heightInput.addEventListener('change', () => {if (aspectLock.checked && originalImage) {const h = parseInt(heightInput.value) || 1;widthInput.value = Math.round(h * originalRatio);}render();});// 切换锁定比例状态aspectLock.addEventListener('change', render);// 上传图片imageInput.addEventListener('change', (e) => {const file = e.target.files[0];if (!file) return;const img = new Image();img.onload = () => {originalImage = img;originalRatio = img.width / img.height;// 默认设为目标尺寸(不超过原图)const maxWidth = Math.min(img.width, 1920);const maxHeight = Math.min(img.height, 1080);widthInput.value = maxWidth;heightInput.value = Math.round(maxWidth / originalRatio);render();saveBtn.disabled = false;};img.src = URL.createObjectURL(file);});// 渲染缩放后的图片function render() {if (!originalImage) return;const w = parseInt(widthInput.value) || 1;const h = parseInt(heightInput.value) || 1;canvas.width = w;canvas.height = h;// 关键:使用高质量缩放(关闭 imageSmoothing 可实现像素风,但这里要清晰)ctx.imageSmoothingEnabled = true;ctx.imageSmoothingQuality = 'high';ctx.clearRect(0, 0, w, h);ctx.drawImage(originalImage, 0, 0, w, h);}// 保存图片saveBtn.addEventListener('click', async () => {const mimeType = 'image/png'; // 也可根据扩展名动态切换const dataUrl = canvas.toDataURL(mimeType);const path = await window.api.saveImage({ dataUrl });if (path) alert(`✅ 已保存至:\n${path}`);});</script></body></html>
4. package.json
{
"name": "image-resize-app",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^latest"
}
}
▶️ 如何运行?
npm install --save-dev electron
npm start
建议使用
cnpm或设置淘宝镜像加速安装。
npm config set registry https://registry.npmmirror.com
npm install -g cnpm --registry=https://registry.npmmirror.com
cnpm install --save-dev electron
npm start
技术亮点
- 高质量缩放:通过
ctx.imageSmoothingQuality = 'high'保证缩放清晰 - 安全架构:使用
contextBridge隔离主/渲染进程 - 用户体验:默认尺寸不超过 1920×1080,避免内存溢出
- 格式兼容:支持透明 PNG、JPG 等主流格式
鸿蒙部分
如何让原本用于 Electron 的前端 + 主进程架构,在鸿蒙系统中运行并兼容?
我们的最终目的是打包在真机上面,所以要去将代码迁移到dev上面,通过观察不难看出,结构都是类似的,所以理论上来说直接copy上去即可,理论成立就开始实战

✅ 答案总结
鸿蒙的“Electron 兼容”本质是:Web Engine 模拟 Chromium + Node.js 环境
华为在 HarmonyOS 的 Web Engine(Web 引擎) 中,通过以下方式实现了对 Electron 应用的部分兼容:
项目 说明
Web 页面渲染 使用 Chromium 内核,支持 HTML/CSS/JS,与 Electron 一致
Node.js API 模拟 通过 libadapter 层模拟部分 Node.js 接口(如文件、IPC)
主进程 → 渲染进程通信 使用 contextBridge + ipcRenderer 模式,与 Electron 保持一致
资源打包机制 将 main.js, preload.js, index.html 打包进 HAP(HarmonyOS Ability Package)
测试
图片之前的尺寸
开始进行修改

修改后的尺寸

✅ 总结
我们通过一个简单的 图片尺寸调节工具,展示了如何:
✅ 用 Electron 快速构建桌面应用
✅ 利用 Canvas 实现高质量图像缩放
✅ 通过鸿蒙 DevEco 的 Web Engine + libadapter 机制,无缝迁移到 HarmonyOS
✅ 实现“一套代码,双端运行”(PC + 鸿蒙设备)