Skip to content

Repository files navigation

ForeastDraw

桌面图片标记查看器 —— 双屏工作流的理想伴侣

项目简介

ForeastDraw 是一个轻量级桌面应用,专为双显示器场景设计。在副屏展示参考图片的同时,可以直接在图片上绘制标记、添加文字、测量标注,而标记数据独立存储,永不修改原图

核心场景:

  • 游戏攻略参考(副屏放地图/技能树,主屏游戏)
  • 设计稿对照(副屏放设计图并标注问题点)
  • 教程学习(副屏放教程图并做笔记)
  • 任何需要"一边看图一边工作"的场景

功能特性

绘制工具

  • 🖌️ 画笔:自由绘制折线
  • 圆形:拖动绘制椭圆/圆形
  • 📏 直线:绘制直线段
  • 📐 标尺:带端点标记的测量线,可添加标注文字
  • ✏️ 文字:点击添加文本标注

核心功能

  • 🎨 颜色自定义:5个预设色 + 颜色选择器
  • 📐 4档粗细:适应不同标注需求
  • ↩️ 撤销/恢复:每张图独立的操作历史
  • 💾 自动保存:标记数据实时保存到 JSON 文件
  • 📤 导出图片:将标记合并到图片,弹出「另存为」自选路径导出为 PNG(默认下载文件夹,记住上次目录)
  • 🗂️ 多文件夹管理:左侧树形结构,展开/收起
  • 👁️ 标记开关:快速隐藏/显示所有标记
  • 🔍 缩放平移:滚轮缩放,左键 / 中键 / 空格+左键拖动平移
  • 移动标记Ctrl(macOS 为 )+ 拖动标记调整位置(悬停显示抓取点)
  • 🪟 窗口置顶:一键让窗口浮在最前,双屏参考更方便
  • 🔄 自动更新:基于 GitHub Releases 检查并提示新版本

数据安全

  • ✅ 标记存储在 .foreastdraw.json绝不写入图片文件
  • ✅ 使用归一化坐标,缩放平移时标记严格跟随
  • ✅ 文件夹监听,外部修改图片自动同步
  • ✅ 应用内重命名图片,标记数据自动迁移

技术栈

层级 技术
框架 Tauri 2
后端 Rust (notify 文件监听)
前端 TypeScript + Vite
渲染 Canvas 2D

无 UI 框架:整个前端约 1500 行纯 TypeScript,启动快、占用低。

开发环境要求

  • Node.js >= 18
  • Rust >= 1.70
  • pnpm / npm / yarn

macOS 开发需要 Xcode Command Line Tools:

xcode-select --install

快速开始

安装依赖

npm install

开发模式

npm run tauri dev

热重载启动,修改前端代码自动刷新。

构建应用

npm run tauri build

本地构建的输出位置(x.x.x 为版本号):

平台 产物 路径
Windows 免安装 exe src-tauri/target/release/ForeastDraw.exe
Windows NSIS 安装包 src-tauri/target/release/bundle/nsis/ForeastDraw_x.x.x_x64-setup.exe
macOS 应用本体 src-tauri/target/release/bundle/macos/ForeastDraw.app
macOS 磁盘镜像 src-tauri/target/release/bundle/dmg/ForeastDraw_x.x.x_*.dmg
Linux AppImage src-tauri/target/release/bundle/appimage/*.AppImage
Linux deb 包 src-tauri/target/release/bundle/deb/*.deb
Linux rpm 包 src-tauri/target/release/bundle/rpm/*.rpm

默认只构建当前系统对应的产物。指定特定格式用 npx tauri build --bundles <targets>,例如 --bundles nsis--bundles appimage,deb,rpm

全平台自动构建与发布(GitHub Actions)

仓库配置了三条独立的 workflow,均可在 GitHub 的 Actions 页手动触发(workflow_dispatch,可选填 Release 标签,留空则用 package.json 版本号,如 0.2.0)。三者用同一个 tag,产物会合并进同一个 Release

Workflow Runner 产物(发布名统一为 ForeastDraw-<tag>-<平台>-<架构>.*
build-windows.yml windows-latest 免安装 -portable.exe、NSIS -setup.exe
build-macos.yml macos-latest 通用二进制 .dmg.app.tar.gz(已签名 + 公证 + 装订)
build-linux.yml ubuntu-22.04 .AppImage.deb.rpm

应用启动后可通过菜单栏「检查更新」比对 GitHub 最新 Release 版本(走 GitHub API,无需自建服务器)。

macOS 代码签名与公证

build-macos.yml 会自动导入证书、签名、公证(notarization)并装订(staple)。需要在仓库 Settings → Secrets and variables → Actions 配置以下 secrets:

Secret 说明
APPLE_CERTIFICATE Developer ID Application 证书(.p12 的 base64)
APPLE_CERTIFICATE_PASSWORD 导出 .p12 时设置的密码
APPLE_SIGNING_IDENTITY 形如 Developer ID Application: Name (TEAMID)
KEYCHAIN_PASSWORD 任意强随机串(用于创建临时 keychain)
APPLE_API_ISSUER App Store Connect API 的 Issuer ID
APPLE_API_KEY API Key ID(10 位)
APPLE_API_KEY_P8 API Key .p8 文件的完整文本内容

GITHUB_TOKEN 由 Actions 自动注入,无需手动配置。Windows / Linux 构建不需要任何 secret。

Linux 兼容性说明

Tauri 2 依赖 webkit2gtk-4.1,构建基线为 Ubuntu 22.04(glibc 2.35),因此运行环境要求:

  • 支持:Ubuntu 22.04+、Debian 12+、Fedora 36+、以及基于较新内核/glibc 的银河麒麟 V10 SP3 等
  • ⚠️ 受限:CentOS Stream 9(glibc 2.34)可能因 glibc 略低而无法运行
  • 不支持:CentOS 7(glibc 2.17)及基于其构建的旧版麒麟 —— glibc 过低,Tauri 2 官方不支持

三种 Linux 产物中,AppImage 通用性最好(自带大部分依赖,免安装双击运行);.deb / .rpm 依赖系统已安装 webkit2gtk,分别面向 Debian 系(Ubuntu / 银河麒麟)与 RHEL 系(CentOS / 中标麒麟)。

仅前端构建

npm run build

输出到 dist/ 目录。

类型检查

npx tsc --noEmit

项目结构

ForeastDraw/
├── src/                    # 前端源码
│   ├── main.ts            # 主入口 + 事件编排
│   ├── render.ts          # Canvas 渲染逻辑
│   ├── store.ts           # 标记数据管理(按文件夹分组)
│   ├── viewport.ts        # 视图变换(fit/zoom/center)
│   ├── imagecache.ts      # ImageBitmap LRU 缓存
│   ├── tree.ts            # 左侧文件夹树
│   ├── menu.ts            # 右键菜单 + 浮层
│   ├── ui.ts              # DOM 工具函数
│   ├── api.ts             # Tauri IPC 封装
│   ├── types.ts           # 共享类型定义
│   └── style.css          # 全局样式
├── src-tauri/             # Rust 后端
│   ├── src/
│   │   ├── lib.rs         # 8 个 Tauri 命令 + 文件监听
│   │   └── main.rs        # 入口(调用 lib.rs)
│   ├── Cargo.toml         # Rust 依赖
│   ├── tauri.conf.json    # Tauri 配置
│   └── capabilities/      # 权限配置
├── index.html             # HTML 模板
├── vite.config.ts         # Vite 配置
└── package.json           # npm 依赖

快捷键

ForeastDraw 采用平移优先交互:左键默认平移,按住空格切换到绘制。可在设置(S 键)中反转。

移动标记的修饰键按平台区分:macOS 用 (Command),Windows / Linux 用 Ctrl。下表以 Ctrl 为例,Mac 上请替换为

默认模式(平移优先):

按键 功能
主操作
左键拖动 平移画布
空格 + 左键 绘制当前工具
Ctrl / ⌘ + 左键拖动 移动已有标记
中键拖动 平移(台式机便利)
右键 打开菜单
工具切换
P 画笔工具
O 圆形工具
L 直线工具
T 文字工具
R 标尺工具
颜色/粗细
Q / W 切换到预设颜色 1 / 2
[ / ] 减细 / 加粗
导航
← / → 上一张 / 下一张
PgUp / PgDn 上一张 / 下一张
Home / End 第一张 / 最后一张
视图
0 适应窗口
9 实际大小(100%)
+ / - 放大 / 缩放
滚轮 鼠标位置缩放
标记操作
H 显示 / 隐藏标记
Ctrl / ⌘ + Z 撤销
Ctrl / ⌘ + Shift + Z 恢复
Del / Backspace 清理当前图片全部标记
文件操作
F2 重命名图片
E 导出图片(含标记,弹出「另存为」选择路径)
其他
S 打开设置(可反转平移/绘制)
F 全屏
Esc 关闭菜单/对话框

反转模式(勾选「反转平移 / 绘制」后):

  • 左键拖动 → 绘制当前工具
  • 空格 + 左键 → 平移画布
  • 其他快捷键不变

应用菜单栏还提供「检查更新」「帮助」「关于」以及「文件 → 打开文件夹 / 关闭当前文件夹」。

数据格式

每个文件夹的标记存储在 .foreastdraw.json

{
  "version": 1,
  "images": {
    "example.jpg": {
      "mtime": 1234567890,
      "strokes": [
        {
          "tool": "ellipse",
          "color": "#ff3b30",
          "width": 0.004,
          "points": [[0.3, 0.4], [0.6, 0.7]]
        },
        {
          "tool": "text",
          "color": "#76b900",
          "width": 0.002,
          "points": [[0.5, 0.5]],
          "text": "重要标记"
        }
      ]
    }
  }
}

关键设计

  • width 是图片宽度的比例(如 0.004 = 0.4%),不是像素值
  • points 是归一化坐标(0..1),与分辨率无关
  • mtime 用于检测图片是否被外部修改过

开发说明

核心约束

  1. 标记坐标归一化 — 存储 0..1 的相对坐标,渲染时乘以图片尺寸。这样换分辨率、换缩放都不会错位。

  2. 单 transform 管理 — 图片和标记共用一个 canvas transform,所以标记"跟随"不是计算出来的,而是结构上不可能不跟随。别把它们拆成两次 transform。

  3. 文件夹分组存储store.tsMap<dir, FolderMarks>,撤销栈、脏标记都是按文件夹分组的。

  4. 改名竞态处理fs::rename 会触发文件监听,dropMissing 会把旧文件名当删除。所以 store.rename 必须在 400ms 防抖窗口内完成(doRename 有注释标了顺序)。

  5. 右键菜单平台差异 — macOS 在 pointerdown 触发 contextmenu,Windows 在 pointerup,所以全局禁掉 contextmenu 事件,由指针状态机自己开菜单。

添加新工具

  1. types.tsStroke["tool"] 联合类型中添加
  2. render.tspath() 函数中添加渲染分支
  3. main.tspointermove / pointerup 中处理交互
  4. index.html 添加工具按钮
  5. handleLetterKeys 添加快捷键

调试技巧

# 只做类型检查
npx tsc --noEmit

# 只构建前端
npx vite build

# 只检查 Rust
cargo check --manifest-path src-tauri/Cargo.toml

# 查看 Tauri 日志
npm run tauri dev  # 控制台会输出 Rust 端日志

常见问题

Q: 标记位置偏移了?
A: 可能是图片被外部软件修改了尺寸。应用会 toast 提示"图片尺寸已变化"。

Q: 外部改名的图片标记丢失?
A: 这是设计行为。标记按文件名追踪,外部改名视为删除。请在应用内改名(F2)。

Q: 能导入 Photoshop/Figma 的标注吗?
A: 目前不支持。标记格式是应用专用的。

开源协议

MIT License

致谢

ForeastDraw, for Foreast Yao.
Copyright © 2026 iwpz. All rights reserved.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages