Electron 入门项目(一)

547 阅读1分钟

ImageShrink

简介:一个简单的图片大小缩放工具。 先看效果:

ImageShrink
原图:
大小缩小后:
图片前后质量对比:

前:

后:
可以看到图片的大小变小了,但是图片的质量并没有下降多少。

项目技术概述

采用Electron开发,利用node 生态中的 imagemin包来实现对图片大小的缩放;利用electron-log包实现对源文件与目标文件转换的日志记录;渲染进程通过ipcRenderer将用户上传的图片的地址、将要缩小的倍数发送到主进程,主进程通过ipcMain接收到对应的opthions利用imagemin将文件缩小,将缩小后的文件存在用户的目录下,并自动打开该文件夹。

核心细节

区分环境

process.env.NODE_ENV = 'production'
const isDev = process.env.NODE_ENV !== 'production' ? true : false //区分生产开发环境
const isMac = process.platform === 'darwin' ? true : false // 区分平台

我这里是采用手动的方式区分开发或者是生产环境,虽然有相应的包可以直接判断,但是我觉得这样比较简单点。

创建窗口

function createMainWindow() {
    mainWindow = new BrowserWindow({
        title: 'ImageShrink',
        width: isDev ? 800 : 500,
        height: 600,
        icon: './assets/icons/Icon_256x256.png',
        resizable: isDev ? true : false,
        webPreferences: {
            nodeIntegration: true // 设置渲染进程是否可用node
        }
    })
    // mainWindow.loadURL(`file://${__dirname}/app/index.html`) // 可以采用loadURL的方式,但是会有一个安全的限制 需要在html中加上这一段 meta: <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'">

    if (isDev) {
      // 如果是开发环境,就打开开发者菜单
        mainWindow.webContents.openDevTools() 
    }
    mainWindow.loadFile(`./app/index.html`)
}

// 关于页面的窗口
function createAboutWindow() {
    aboutWindow = new BrowserWindow({
        title: 'About ImageShrink',
        width: 300,
        height: 300,
        icon: './assets/icons/Icon_256x256.png',
        resizable: false
    })
    aboutWindow.loadFile(`./app/about.html`)
}

设置菜单项

const menu = [
    ...(isMac ? [{
        label: app.name,
        submenu: [{
            label: 'About',
            click: createAboutWindow
        }]
    }] : []),
    {
        role: 'fileMenu'
    },
    ...(!isMac ? [{
        label: 'Help',
        submenu: [{
            label: 'About',
            click: createAboutWindow
        }]
    }] : []),
    ...(isDev ? [{
        label: 'Developer', // 开发者菜单,用内置的menu
        submenu: [{
                role: 'reload'
            },
            {
                role: 'forcereload'
            },
            {
                type: 'separator'
            },
            {
                role: 'toggledevtools'
            },
        ]
    }] : [])
]

app.on('ready', () => {
    createMainWindow()

    const mainMenu = Menu.buildFromTemplate(menu)
    Menu.setApplicationMenu(mainMenu)

    // 全局快捷键  如果不用开发者菜单 可用自己设置全局快捷键帮助开发
    // globalShortcut.register('CmdOrCtrl+R', () => mainWindow.reload()) 刷新页面
    // globalShortcut.register(isMac ? 'Command+Alt+I' : 'Ctrl+Shift+I', () => mainWindow.toggleDevTools()) 打开 DevTools

    mainWindow.on('ready', () => mainWindow = null)
})

图片缩小逻辑

// 利用 ipcMain ipcRenderer 实现主进程与渲染进程的通信
// options 有两个参数: url 和 quality,分别为图片的路径和缩小倍数
// 这里的dest是指转换后图片存放的地址
ipcMain.on('image:minimize', (e, options) => {
    options.dest = path.join(os.homedir(), 'imageshrink')
    shrinkImage(options)
})

// 图片缩小的方法
async function shrinkImage({
    imgPath,
    quality,
    dest
}) {
    try {
        const pngQuality = quality / 100
        // 调用方法 实现缩小图片,具体细节可在npm上搜索该包的详细信息
        const files = await imagemin([slash(imgPath)], {
            destination: dest,
            plugins: [
                imageminMozjpeg({
                    quality
                }),
                imageminPngquant({
                    quality: [pngQuality, pngQuality]
                })
            ]
        })
        log.info(files) // 将这个文件写入日志文件中
        shell.openPath(dest) // 打开转换后图片的存放的文件夹
        mainWindow.webContents.send('image:done') // 主进程 利用webContents 主动向渲染进程发送 渲染已完成的事件
    } catch (error) {
        // 如果转换出错,将错误信息存入日志文件中
        log.error(error)
    }
}

// 渲染进程
document.getElementById('output-path').innerText = path.join(os.homedir(),'imageshrink')

form.addEventListener('submit', e => {
    e.preventDefault()

    const imgPath = img.files[0].path
    const quality = slider.value
				
    // 向主进程提交缩小图片的事件,并将图片路径和缩小倍数传过去
    ipcRenderer.send('image:minimize', {
        imgPath,
        quality
    })
})

// on done
		// 图片上传完成 页面提示转换完成
ipcRenderer.on('image:done', () => {
    M.toast({
        html: `Image resized to ${slider.value}% quality`
    })
})

欢迎交流,目前大三,求职中。