@qs-coder/react-screenshots

中文文档
1.0.1发布于 2026/11/02MITTypeScriptESM + CJS零依赖

react提供的截图裁剪工具

中文使用文档
文档目录8 节
  1. Install
  2. Usage
  3. Props
  4. 窗口识别与锁边
  5. 元素识别与自动框选
  6. example
  7. Screenshot
  8. Icons

react-screenshots

a screenshot cropper tool by react

Install

NPM

Usage

  1. web 中使用
import React, { ReactElement, useCallback } from "react";
import Screenshots, { Bounds } from "react-screenshots";
import url from "./image.jpg";

interface Bounds {
  x: number;
  y: number;
  width: number;
  height: number;
}

export default function App(): ReactElement {
  const onSave = useCallback((blob: Blob, bounds: Bounds) => {
    console.log("save", blob, bounds);
    console.log(URL.createObjectURL(blob));
  }, []);
  const onCancel = useCallback(() => {
    console.log("cancel");
  }, []);
  const onOk = useCallback((blob: Blob, bounds: Bounds) => {
    console.log("ok", blob, bounds);
    console.log(URL.createObjectURL(blob));
  }, []);

  return (
    <Screenshots
      url={url}
      width={window.innerWidth}
      height={window.innerHeight}
      lang={{
        operation_undo_title: "Undo",
        operation_mosaic_title: "Mosaic",
        operation_text_title: "Text",
        operation_brush_title: "Brush",
        operation_arrow_title: "Arrow",
        operation_ellipse_title: "Ellipse",
        operation_rectangle_title: "Rectangle",
      }}
      onSave={onSave}
      onCancel={onCancel}
      onOk={onOk}
    />
  );
}
  1. electron 中使用
  • electron 中使用可直接加载渲染进程的页面,页面路径为require.resolve('react-screenshots/electron/electron.html'),不推荐自己手动开发主进程,推荐直接使用electron-screenshots模块
interface ScreenshotsData {
  bounds: Bounds
  display: Display
}

interface GlobalScreenshots {
  ready: () => void
  reset: () => void
  save: (arrayBuffer: ArrayBuffer, data: ScreenshotsData) => void
  cancel: () => void
  ok: (arrayBuffer: ArrayBuffer, data: ScreenshotsData) => void
  on: (channel: string, fn: ScreenshotsListener) => void
  off: (channel: string, fn: ScreenshotsListener) => void
}

// 需要在electron的preload中提前初始化这个对象,用于渲染进程与主进程通信
window.screenshots: GlobalScreenshots

Props

interface Bounds {
  x: number;
  y: number;
  width: number;
  height: number;
}

interface Lang {
  magnifier_position_label: string;
  operation_ok_title: string;
  operation_cancel_title: string;
  operation_save_title: string;
  operation_redo_title: string;
  operation_undo_title: string;
  operation_mosaic_title: string;
  operation_text_title: string;
  operation_brush_title: string;
  operation_arrow_title: string;
  operation_ellipse_title: string;
  operation_rectangle_title: string;
}
名称说明类型是否必选
url要编辑的图像资源地址string是
imageElement与 url 成对传入的已解码底图元素;传了就直接用它,不再走"置空等 onload"HTMLImageElement | null否
width画布宽度number是
height画布宽度number是
lang多语言支持,默认中文Partial<Lang>否
onSave保存按钮回调(blob: Blob, bounds: Bounds) => void否
onCancel取消按钮回调() => void否
onOk取消按钮回调(blob: Blob, bounds: Bounds) => void否
windows窗口识别与锁边数据Bounds[]否
edges元素识别数据(拾取时窗口优先,只在 windows 为空时参与吸附)Bounds[]否

窗口识别与锁边

传入 windows(当前屏幕上其他应用的窗口矩形,坐标系为画布内相对坐标,且必须按 z 轴从上到下排序)后会启用两套微信/Snipaste 式交互:

  • 未框选时,鼠标悬停会标记光标所在的窗口,单击即整窗选中;按下并拖动仍然是自由框选。被标记的窗口内部透出与遮罩下同尺寸的画面(看起来就是"已经框选好"的样子),只有 #39f 的 2px 边框,没有着色填充。
  • 框选与拖拽 8 个手柄调整大小时,边会在 6px 内吸附到窗口边和画布边;整体移动选区时按"选区的边对齐窗口的边"平移,而不是按鼠标抓取点对齐。
  • 按住 Alt/⌥ 期间禁用吸附,作为需要精确到像素时的逃生口。
  • 不传或传空数组时,上述两项都不生效(只剩画布边),交互与之前完全一致。

元素识别与自动框选

edges 是元素级矩形:@qs-coder/electron-screenshots 在 detectEdges: true 时用截图像素识别出的界面元素(按钮、卡片、输入框等),坐标系与 windows 一致,两个 prop 同时传。两者都是截图画面锁住之后才陆续到达的(窗口枚举走 on('windows'),元素识别走 on('edges'))。内置的 electron 渲染层已经接好这套协议,并且会按 display.id 缓存每块屏解码好的底图:on('capture') 的 PNG 字节可能为 undefined,含义是"这块屏你已经有缓存了";换屏时只换已解码的图片元素,等这一帧真的画完再回 painted(),主进程才搬窗口。自带渲染层的宿主若不复现这套回执,每次显示和换屏都会等满 2.5s 的绘制超时,详见 @qs-coder/electron-screenshots 的 IPC 说明。

  • hover 与单击的拾取规则是窗口优先:光标只要落在某个窗口矩形里,就直接选那个窗口(取 z 序最靠上的),完全不会再和元素矩形比面积——像素法只能看到窗口"露出来的那部分",被别的窗口压住下边界时它检出的是半截矩形,让半截赢整窗是不对的。光标不在任何窗口里时(桌面控件、Wayland 这类拿不到窗口几何的场合),才在包含光标的元素矩形里取面积最小的那个。边界口径分两套:窗口的四条边算窗口自己(那 1px 视觉上就是这个窗口的;若不算,光标压在窗口边框上时窗口不命中、元素矩形趁虚而入,表现就是窗口边缘冒碎框;右/下不取等,避免和相邻窗口抢同一列像素),元素的两层(邻域精修 / 整屏候选)共用另一条:四条边本身不算内部,两层之间必须一致,否则同一像素上口径不一,hover 会抖。
  • 元素矩形的贴边精修是按需二次请求的:整屏那一遍为压耗时降过采样,边会系统性偏 1~3 DIP。hover 到窗口之外的元素矩形时,渲染端通过 window.screenshots.edgeRegion(rect) 把粗矩形发给主进程,主进程按原生分辨率重检后回 edges-precise,渲染端把高亮和单击结果换成那份贴准的矩形(同一个粗矩形只问一次,结果回来时校验请求标识和光标位置,走远了就丢掉)。宿主用内置的 <Screenshots> 即可,不需要自己接这两个通道;edgeRegion 是可选方法,老版本主进程没有它时行为退化成只用粗矩形。
  • 拖框与 resize 的吸附只认 windows 的边:元素边太碎,靠过去会把选区带偏。windows 为空(平台或权限拿不到窗口几何)时才由 edges 顶上,阈值不变。
  • 识别结果是异步的:截图窗口先显示,识别完成后才补齐,所以刚进入截图的那一瞬间可能只有窗口边可吸附。
  • edges 只有在 windows 为空时才进吸附候选;拾取则始终窗口优先,光标不在任何窗口里时才落到元素。不传或传空数组时,行为与不启用元素识别(0.7.0)完全一致。

example

import React from "react";

function App() {
  return (
    <Screenshot
      url="./example.png"
      width={window.innerWidth}
      height={window.innerHeight}
      onSave={() => {}}
      onCancel={() => {}}
      onOk={() => {}}
    />
  );
}

Screenshot

screenshot

Icons

Iconfont

版本与发布记录

@qs-coder/react-screenshots 共发布 12 个版本,首次发布于 2025/06/12;过去 12 个月发布了 9 个版本。

版本发布日期距今
1.0.1latest2026/11/021 天前
1.0.02026/11/021 天前
0.9.02026/10/304 天前
0.8.22026/10/295 天前
0.8.12026/10/277 天前
0.8.02026/10/268 天前

关于 @qs-coder/react-screenshots 的常见问题

@qs-coder/react-screenshots 是什么?

react提供的截图裁剪工具

如何安装 @qs-coder/react-screenshots?

在项目目录运行 npm install @qs-coder/react-screenshots,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=16.9.0)、react-dom(>=16.9.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@qs-coder/react-screenshots 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@qs-coder/react-screenshots 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@qs-coder/react-screenshots 可以商用吗?

@qs-coder/react-screenshots 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@qs-coder/react-screenshots 还在维护吗?

最新版本 1.0.1 发布于 2026/11/02(1 天前);至今共发布 12 个版本,其中过去 12 个月发布了 9 个;首次发布于 2025/06/12。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。