Electron屏幕捕获功能:基于gh_mirrors/el/electron-quick-start实现截图工具

Electron屏幕捕获功能:基于gh_mirrors/el/electron-quick-start实现截图工具

【免费下载链接】electron-quick-start Clone to try a simple Electron app 【免费下载链接】electron-quick-start 项目地址: https://gitcode.com/gh_mirrors/el/electron-quick-start

引言:截图工具的痛点与解决方案

你是否还在为寻找一款轻量、高效且可定制的截图工具而烦恼?传统截图工具要么功能单一,要么体积庞大,难以满足开发者的个性化需求。本文将带你基于Electron框架,从零开始打造一款功能完备的截图工具,解决截图、编辑、保存全流程的痛点。

读完本文,你将能够:

  • 掌握Electron桌面捕获API的核心用法
  • 实现区域选择、全屏截图等基础功能
  • 了解截图工具的架构设计与实现原理
  • 学会如何打包和分发Electron应用

项目准备与环境搭建

1. 项目克隆与依赖安装

首先,克隆项目仓库并安装依赖:

git clone https://gitcode.com/gh_mirrors/el/electron-quick-start
cd electron-quick-start
npm install

2. 安装截图相关依赖

为了实现截图功能,我们需要安装以下依赖:

npm install electron-screenshot-app --save

核心功能实现

1. 主进程代码修改(main.js)

首先,我们需要修改主进程代码,引入必要的模块并实现截图功能:

// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, desktopCapturer } = require('electron')
const path = require('node:path')
const fs = require('fs')
const { writeFile } = require('fs')

function createWindow () {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: true,
      contextIsolation: false
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()
}

// 实现截图功能
ipcMain.on('capture-screen', async (event, args) => {
  try {
    const { width, height, x, y } = args;
    
    // 获取所有可用的桌面源
    const sources = await desktopCapturer.getSources({ types: ['screen'] })
    
    // 创建截图窗口
    const captureWindow = new BrowserWindow({
      width: width,
      height: height,
      x: x,
      y: y,
      frame: false,
      transparent: true,
      alwaysOnTop: true,
      skipTaskbar: true,
      webPreferences: {
        nodeIntegration: true,
        contextIsolation: false
      }
    })
    
    // 加载截图页面
    captureWindow.loadFile('capture.html')
    
    // 发送截图区域信息
    captureWindow.webContents.on('did-finish-load', () => {
      captureWindow.webContents.send('capture-info', {
        sources: sources,
        bounds: { width, height, x, y }
      })
    })
  } catch (error) {
    console.error('截图失败:', error)
  }
})

// 保存截图
ipcMain.on('save-screenshot', (event, args) => {
  const { imageData, filePath } = args;
  const base64Data = imageData.replace(/^data:image\/png;base64,/, '');
  
  fs.writeFile(filePath, base64Data, 'base64', (err) => {
    if (err) {
      console.error('保存截图失败:', err);
      event.reply('save-status', { success: false, error: err.message });
    } else {
      event.reply('save-status', { success: true, path: filePath });
    }
  });
})

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

2. 预加载脚本修改(preload.js)

接下来,修改预加载脚本,添加与主进程通信的接口:

/**
 * The preload script runs before `index.html` is loaded
 * in the renderer. It has access to web APIs as well as
 * Electron's renderer process modules and some polyfilled
 * Node.js functions.
 *
 * https://www.electronjs.org/docs/latest/tutorial/sandbox
 */
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  captureScreen: (bounds) => ipcRenderer.send('capture-screen', bounds),
  saveScreenshot: (imageData, filePath) => ipcRenderer.invoke('save-screenshot', { imageData, filePath }),
  onSaveStatus: (callback) => ipcRenderer.on('save-status', callback)
});

window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const type of ['chrome', 'node', 'electron']) {
    replaceText(`${type}-version`, process.versions[type])
  }
})

3. 创建截图页面(capture.html)

创建一个新的HTML文件,用于显示截图区域和提供编辑功能:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>截图工具</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div id="screenshot-container"></div>
    <div id="toolbar">
        <button id="save-btn">保存</button>
        <button id="cancel-btn">取消</button>
    </div>
    <script src="renderer.js"></script>
</body>
</html>

4. 渲染进程代码修改(renderer.js)

修改渲染进程代码,实现截图区域选择和处理:

/**
 * This file is loaded via the <script> tag in the index.html file and will
 * be executed in the renderer process for that window. No Node.js APIs are
 * available in this process because `nodeIntegration` is turned off and
 * `contextIsolation` is turned on. Use the contextBridge API in `preload.js`
 * to expose Node.js functionality from the main process.
 */

const { ipcRenderer } = require('electron');

document.addEventListener('DOMContentLoaded', () => {
    // 添加截图按钮点击事件
    const screenshotBtn = document.createElement('button');
    screenshotBtn.textContent = '截图';
    screenshotBtn.id = 'screenshot-btn';
    document.body.appendChild(screenshotBtn);
    
    screenshotBtn.addEventListener('click', () => {
        // 获取屏幕尺寸
        const { screen } = require('electron');
        const primaryDisplay = screen.getPrimaryDisplay();
        const { width, height } = primaryDisplay.workAreaSize;
        
        // 发送截图请求到主进程
        window.electronAPI.captureScreen({
            width,
            height,
            x: 0,
            y: 0
        });
    });
    
    // 监听保存状态
    window.electronAPI.onSaveStatus((event, args) => {
        if (args.success) {
            alert(`截图已保存至: ${args.path}`);
        } else {
            alert(`保存失败: ${args.error}`);
        }
    });
});

功能扩展与优化

1. 快捷键支持

为了提升用户体验,我们可以添加快捷键支持:

// 在main.js中添加
const { globalShortcut } = require('electron');

app.whenReady().then(() => {
  // 注册快捷键 Ctrl+Shift+A 用于截图
  const ret = globalShortcut.register('Ctrl+Shift+A', () => {
    console.log('Ctrl+Shift+A is pressed');
    // 触发截图功能
    const mainWindow = BrowserWindow.getAllWindows()[0];
    if (mainWindow) {
      mainWindow.webContents.send('trigger-screenshot');
    }
  });

  if (!ret) {
    console.log('registration failed');
  }

  // 检查快捷键是否注册成功
  console.log(globalShortcut.isRegistered('Ctrl+Shift+A'));
});

app.on('will-quit', () => {
  // 注销快捷键
  globalShortcut.unregister('Ctrl+Shift+A');
  globalShortcut.unregisterAll();
});

2. 图片编辑功能

可以集成简单的图片编辑功能,如添加文字、箭头等:

// 在renderer.js中添加编辑功能
function initEditor() {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    // 设置canvas尺寸
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    document.getElementById('screenshot-container').appendChild(canvas);
    
    // 实现简单的绘图功能
    let isDrawing = false;
    let lastX = 0;
    let lastY = 0;
    
    canvas.addEventListener('mousedown', (e) => {
        isDrawing = true;
        [lastX, lastY] = [e.offsetX, e.offsetY];
    });
    
    canvas.addEventListener('mousemove', draw);
    canvas.addEventListener('mouseup', () => isDrawing = false);
    canvas.addEventListener('mouseout', () => isDrawing = false);
    
    function draw(e) {
        if (!isDrawing) return;
        ctx.strokeStyle = '#ff0000';
        ctx.lineWidth = 2;
        ctx.lineCap = 'round';
        ctx.beginPath();
        ctx.moveTo(lastX, lastY);
        ctx.lineTo(e.offsetX, e.offsetY);
        ctx.stroke();
        [lastX, lastY] = [e.offsetX, e.offsetY];
    }
}

应用打包与分发

1. 安装打包工具

npm install electron-packager --save-dev

2. 添加打包脚本

在package.json中添加打包脚本:

"scripts": {
  "start": "electron .",
  "package": "electron-packager . screenshot-tool --platform=win32 --arch=x64 --out=dist"
}

3. 执行打包命令

npm run package

总结与展望

通过本文的学习,我们基于Electron框架实现了一个基础的截图工具,包括区域选择、全屏截图、保存等核心功能。当然,这只是一个起点,你可以根据需求进一步扩展功能,如添加图片编辑、OCR文字识别、云同步等高级特性。

Electron框架为桌面应用开发提供了极大的便利,结合Web技术栈的优势,可以快速构建跨平台的桌面应用。希望本文能够帮助你更好地理解Electron的应用开发,为你的项目带来启发。

下期预告

下一篇文章,我们将深入探讨Electron应用的性能优化技巧,包括内存管理、启动速度优化等关键话题,敬请期待!

【免费下载链接】electron-quick-start Clone to try a simple Electron app 【免费下载链接】electron-quick-start 项目地址: https://gitcode.com/gh_mirrors/el/electron-quick-start

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值