# Visioxure
**Repository Path**: masonwu21/Visioxure
## Basic Information
- **Project Name**: Visioxure
- **Description**: No description available
- **Primary Language**: C++
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2026-10-28
- **Last Updated**: 2026-11-10
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Visioxure
Visio + Axure 结合体的桌面原型设计工具:**画得出 Visio 的图,也能像 Axure 一样跑交互**。
- 桌面端:C++17 / Win32 / WebView2(TauriCPP 框架)+ Canvas 2D 前端,单 exe 分发
- 当前版本:**1.2.0**(exe 文件属性同步带版本信息,状态栏右下角也显示版本号)
- 文档模型:前端 JSON 为唯一事实源,后端只做文件 IO 与 VSDX 编解码
- 文件格式:`.vsdx`(OPC 包 + VisioML),保存后可用 Microsoft Visio 直接打开
## 当前进度
| 阶段 | 内容 | 状态 |
|---|---|---|
| P0 | 窗口骨架 + Bridge 双向通信 | ✅ |
| P1 | 画布/选择/变换/文本/撤销重做/多页面/参考线/标尺 | ✅ |
| P2 | 路径与布尔运算、组合/解组、连接线与布线、形状库、图层、对齐分布 | ✅ |
| P3 | VSDX 读写(miniz)、文件对话框、脏标记、最近文件、Ctrl+S | ✅ |
| P4 | 交互面板(事件→动作)、动态面板多状态、三级变量、F5 浏览器预览 | ✅ |
| P5 | 注释 / 链接 / 脚本面板、meta 读写 | ✅ |
| P5.5 | 形状属性面板(几何 + 文本样式)、前端 Playwright 验收 | ✅ |
| P6 | 导出 PNG / SVG / HTML / PDF(S1) | ✅(多页 zip 待 A1) |
| P7 | 主题、性能、图标、测试补齐、文档 | ⏳(应用图标已完成) |
详细设计见 [CODEPLAN.md](CODEPLAN.md)。
## 1.2.0(2026-11)
- **版本号 1.2.0**:仍由 `CMakeLists.txt` 的 `project(VERSION)` 单一来源派生到 exe 文件属性、状态栏与 VSDX `AppVersion`
- **动态面板完善**:状态编辑页签(标题 = 面板名 + 状态名,可切换/关闭)、状态复制/排序/删除与形状 id 重映射;移动面板带动全部状态内容,视口裁剪可开关(旧文档默认不裁剪)、一键适应内容尺寸;状态编辑中点插的形状自动落在面板视口内
- **状态切换**:`setState` 支持指定 / 下一个 / 上一个 / 循环,淡入淡出与四向滑动动效、时长;新增 `statechange` 事件与 `{{panelStateName}}` 等局部变量;页面载入 / 按键事件只派发给当前可见状态
- **旧文档兼容**:载入时把旧交互面板丢失的 `setState` 空状态物化为明确状态 id;交互面板给出「目标 = 当前默认态 / 只有 1 个状态 / 状态为空」等诊断;导出 HTML 带 `visioxure-runtime` 指纹以识别旧运行时
- **F5 浏览器预览**:菜单栏最右侧新增「预览」按钮,直接把工程导出为自包含 HTML 写到系统临时目录,并用默认浏览器新页签打开;不弹保存对话框,无 Bridge 时退化为 Blob URL 新页签
- **剪贴板复制粘贴**:`Ctrl+C` / `Ctrl+V` 复制粘贴图形,支持多选、跨页 / 跨动态面板状态、连续粘贴阶梯错开与 `Ctrl+Z` 撤销;`Ctrl+D` 再制保留,文本输入框和就地文字编辑仍是原生复制粘贴
- **画布右键菜单**:多选时「组合」、选中组合或处于组编辑态时「取消组合」,不可用的项灰显;组合 / 解组统一作用于当前编辑容器,不再把动态面板状态内的形状组合到页面顶层
- **缩放显示修复**:工具栏中间的百分比不再固定 `100%`,与底部状态栏同源,缩放按钮 / `Ctrl`+滚轮 / 适应窗口都会同步刷新
- **交互组件缩放修复**:组合缩放改为以拖拽开始时的深拷贝快照逐帧重算,消除逐帧连乘导致的子形状漂移;形状库组合内的 `path` 图标 / 箭头插入时固化 `path.design`,缩放时几何随包围盒变化;子形状文字字号与圆角按等比系数跟随,全程可 `Ctrl+Z` 恢复
- **动态面板虚线框可选中**:命中判定不再只认状态内子形状,空面板、框内空白与 1px 虚线框(含状态编辑态蓝色框)都能选中面板本身;框线留 6 屏幕像素容差,开启裁剪时视口外仍不命中、关闭裁剪时溢出子形状照旧可点
- **动态面板状态编辑修复**:画布渲染改用 `panelEdit.stateId`,切换状态页签后新加的组件立刻可见;点插与拖拽的落点统一钳制在面板视口内,连点级联按「页面 / 面板状态」隔离并在可用空间内回绕,不再出现「插入了、退出编辑却看不见」
- **状态编辑遮罩**:进入动态面板状态编辑时,画布上面板视口以外的区域压暗(视口与「状态编辑」标签留亮),Esc / 关闭页签退出后自动恢复
- **验收**:Playwright e2e 226 项断言(含真实样本导出点击)、CTest VSDX 往返与临时预览文件落盘测试;上述剪贴板、右键菜单、缩放同步、组件缩放、状态编辑插入与遮罩另有针对性 Playwright 验证(含像素级断言)
## 近期更新(2026-10)
- **版本号升至 1.1.0**:状态栏右下角改为「版本号 + GitHub/Gitee 图标链接」,两个仓库链接从菜单栏左侧移到这里,点击仍由系统默认浏览器打开
- **形状库支持拖拽插入**:条目可直接拖到画布上,形状中心落在鼠标释放处(拖拽中缩略图跟随光标、画布虚线提示落点,拖回面板即取消);点击插入仍然落在视口中心,同一位置连点时自动阶梯错位 20px(最多 8 步后回到原位),不再与上一个形状完全重叠
- **版本号 1.0.1**:状态栏右下角常显版本号(`v1.0.1`,桌面端由后端 `app.get_info` 从 CMake 的 `project(VERSION)` 回填);同时去掉此前占据右下角的 Bridge 连接状态提示
- **页面网格样式**:右侧「页面」面板新增「网格」四档——小网格(10px 细线)/ 大网格(10px 细线 + 每 50px 主线)/ 网点 / 无;逐页保存、随 .vsdx 往返(PageSheet 的 `User.VXGrid`),选「无」同时关闭网格吸附;状态栏点「网格」也能在四档间循环
- **表格组件**:形状库新增「表格」(组 + 等分网格),右侧「属性」可选行数 / 列数(1–30)与首行表头;拖缩放手柄时按网格重排而不是拉伸单元格,行高 / 列宽有可读下限(24 / 48px),压到下限即停,缩放与改行列均可 Ctrl+Z
- **占位组件改版**:图片占位 / 照片占位按 `prototype/` 样图重绘(140×100 卡片 + 山形图标、76×76 头像剪影)
- **状态栏常显当前页**:底部状态栏新增「页面 xxx」,左侧面板切到形状库时也知道自己在改哪一页;点一下切回「页面树」
- **页面树改造**:行首页图标改为拖拽把手(上下拖动排序,可撤销)、顶部新增「新增页面」按钮、去掉底部提示行
- **导出 HTML**:页面树移到左侧可折叠侧栏(200px ⇄ 34px),点页面名切页;修复导出页面底色未铺导致整页发灰(新增空白像素回归断言)
- 页面纸张默认背景色统一为白色(新建页面 / 新建文档 / 旧文件与未声明底色的 VSDX 都回退白纸)
- 「适应窗口」改为页面贴工作区左上角,多余空间留在右侧与下方
- 应用图标:`TauriCPP/tools/make_icon.py` 从 `logo.svg` / `logo.png` 生成 `src/app.ico`,编译期嵌入 exe 并设为窗口类图标
- **导出(P6-S1)**:一级菜单「导出」(位于「文件」右侧)提供四种产物——**PNG**(当前页,1x/2x/3x 与透明底)、**SVG**(当前页矢量)、**HTML**(整个工程,单文件自包含可交互)、**PDF**(整个工程多页);位图 / 矢量 / 栅格 PDF / 交互页全部复用与编辑器同一份 `drawScene`/`interact.js`,导出与画布逐像素一致;后端 `export.write` 负责 base64 解码落盘,无原生 Bridge 时退化为浏览器下载;验收 `test/e2e/check_export.js`(65 项)
- 新增右侧「属性」面板:X / Y / 宽 / 高 / 旋转 / 圆角 / 不透明度,以及字体 / 字号 / 加粗 / 字色 / 水平·垂直对齐;多选时不一致的值显示「多个值」,回车或失焦生效,全部可 Ctrl+Z 撤销
- 修复在面板输入框里改完数值后 Ctrl+Z 失效(面板抢占了全局快捷键)
- 修复撤销 / 重做后丢失当前页与选中(快照现在同时记录页面与选中上下文)
- 修复形状库的三角形 / 梯形 / 菱形 / 箭头插入后缺一条闭合边:子路径开合不再按「有没有填充」推断,改由 `path.closed[]` 显式声明(缺省闭合),`.vsdx` 读写同步保留该语义
- 修复菱形 / 三角形 / 梯形「选框变低但图形不变」:拖缩放手柄、面板改宽高、组缩放与布尔运算输入现在都按包围盒相对设计尺寸(`path.design`)缩放图形,`.vsdx` 导出同步(旧文件与导入的 Visio 文件行为不变)
- 新增 `test/e2e/` Playwright 验收脚本(属性面板 + 主干交互 + 子路径闭合 + 路径缩放,共 88 项断言,复用本机 Edge,无需下载浏览器内核)
- 形状库改版:基本形状 6 项(矩形 / 圆角矩形 / 圆形 / 三角形 / 梯形 / 菱形,带连接点)、流程图 3 项(连接线 / 箭头 / 双向箭头)、交互原型 25 项(按 `prototype/` 样图重做,白底卡片 + 极细描边 + 深墨蓝主色 + 骨架占位),固定三列
- 菜单栏左侧改为 GitHub / Gitee 图标链接(内容取自 `logo.txt`),点击由系统默认浏览器打开
- 新增右侧「样式」面板与 Office 风格调色板:填充 / 边框 / 线宽,主题色 + 标准色 + 取色器 + 最近自定义色
- 连接线支持直线 / 折线 / 曲线、线宽、两端 7 种箭头,端点可拖拽并接近吸附
- 修复拖动连接线端点后整条连接线消失(布线空值异常导致整帧渲染中断)
- 修复无填充形状双击输入文字后不可见
## 功能一览
**绘图(Visio 向)**
- 矩形 / 圆角矩形 / 椭圆 / 文本 / 图片 / 自由路径(含孔洞,even-odd)
- 组合(Ctrl+G)/ 解组(Ctrl+Shift+G)、布尔运算(联合 / 相交 / 剪除,基于 Clipper);画布右键菜单也提供「组合 / 取消组合」,多选或进入组编辑态时按条件启用,组合结果落在当前编辑容器(页面 / 动态面板状态)
- 剪贴板:`Ctrl+C` / `Ctrl+V` 复制粘贴图形(多选、跨页 / 跨面板状态、连续粘贴阶梯错开、可 `Ctrl+Z` 撤销),`Ctrl+D` 再制保留;文本输入框与就地文字编辑仍是原生复制粘贴
- 连接线:四边连接点吸附、直线 / 直角折线 / 曲线、线宽、两端 7 种箭头(无 / 实心 / 开口 / 空心三角 / 圆点 / 菱形 / 竖线)、移动形状自动跟随
- 连接线端点可直接拖拽换连接点(14px 接近吸附),**选中后可拖拽任意线段手动调整折线**
- 形状库:基本形状(矩形 / 圆角矩形 / 圆形 / 三角形 / 梯形 / 菱形)、流程图(连接线 / 箭头 / 双向箭头)、交互原型(26 个 Axure 风格构件:手机画板 / 按钮 / 表单控件 / **表格** / 占位图 / 卡片 / 对话框 / 动态面板等);固定三列,缩略图与插入结果一致(基本形状统一黑描边无填充,交互原型按样图配色);点击插入到视口中心(连点自动错位),也可拖拽到画布任意位置插入
- 交互原型组件可整体拖拽缩放:子形状按拖拽起始快照线性映射,组合内 `path` 图标、文字字号与圆角同步跟随,多帧拖拽不再累积漂移或变形
- 右侧「属性」面板:位置尺寸 / 旋转 / 圆角 / 不透明度 + 字体 / 字号 / 加粗 / 字色 / 水平·垂直对齐(多选混合值显示「多个值」)
- 右侧「样式」面板:填充 / 边框颜色(Office 主题色 + 标准色 + 取色器 + 最近 10 个自定义色)、线宽、连接线线型与箭头
- 双击形状就地输入文字(无填充形状自动改用深色字)
- 图层显隐与锁定、网格与参考线吸附、多页面页面树(拖动把手排序 / 一键新增页面)
- 右侧「页面」面板:页面尺寸、背景色与网格样式(小 / 大 / 网点 / 无);底部状态栏始终显示当前编辑的页面
**VSDX 读写(P3/P4)**
- 保存:可以生成结构合法的 VSDX,Visio 打开后形状 / 文字 / 颜色 / 连线正确
- 打开:支持真实 Visio 文件(样式表继承、母版几何、原生组合、相对坐标、1-D 连接线、背景页跳过)
- 自定义数据通过 User 段保存:组合链、连接线粘附、手动折线、交互、面板状态、变量
**交互原型(Axure 向,P4)**
- 右侧「交互」Tab:事件 → 动作编辑器;全局变量 / 页面变量编辑
- 事件:点击 / 双击 / 鼠标移入 / 移出 / 页面载入 / 按键 / 状态改变(动态面板)
- 动作:打开链接(跳页或 URL)/ 显示 / 隐藏(含淡入淡出)/ 切换面板状态 / 设置文本 / 移动(可带动画)/ 设置变量 / 运行脚本
- 动态面板:双击(或属性/交互面板按钮)在画布上方打开**状态编辑页签**,页签标题为面板名 + 状态名,可重命名面板、切回页面页签、关闭页签;状态栏同步显示「页面 › 面板 › 状态」面包屑
- 动态面板:多状态编辑(新增 / 复制 / 排序 / 删除)与切换(指定 / 上一下一个 / 循环,淡入淡出或四向滑动);新建形状归入当前状态,点插时自动落在面板视口内;面板移动带动全部状态内容,视口裁剪可开关(旧文档默认不裁剪)、可一键适应内容尺寸;状态切换触发 OnStateChange,可用 `{{panelStateName}}` 等变量
- 动态面板状态编辑:虚线框(含空面板与框内空白)可直接点击选中,编辑时渲染的就是正在编辑的状态;点插 / 拖拽添加的组件统一钳制在视口内并立刻可见,画布上面板视口以外的区域压暗,退出编辑恢复
- 交互只在 **F5 预览 / 导出的 HTML** 中执行;编辑器里点击形状只会选中它。设计态(画布与导出显示的默认状态)在「交互」面板的状态单选里切换
- 变量插值 `{{name}}`:local → page → global,全局变量跨页持久、页面变量进入页面时重置
- **预览(菜单栏最右侧按钮 / F5)**:把整个工程导出为自包含 HTML 写到系统临时目录,并用系统默认浏览器新页签打开,不弹保存对话框;浏览器直开(无 Bridge)时退化为 Blob URL 新页签
- 应用内全屏预览运行时仍保留(`VX.Preview`),与 HTML 导出共用同一交互运行时,Esc 退出
**导出(P6-S1)**
- PNG(当前页):1x / 2x / 3x、透明底;离屏复用 `drawScene`,与画布逐像素一致(不吃编辑态最小线宽、不带页影/页框)
- SVG(当前页):矢量,与渲染器同口径的圆角 / 虚线 / 箭头 / 多行文本;隐藏层不参与导出
- HTML(整个工程):单文件自包含,内联运行时脚本 + 文档 JSON + 样式,双击即可跑交互、切页、`{{变量}}` 插值;页面树在左侧可折叠侧栏
- HTML 产物带 `` 指纹。改过前端后必须重新构建 exe(`./build.ps1`)或用 `-DevMode` 运行,否则已编译 exe 仍内嵌旧运行时,导出的 HTML 不会带上新逻辑;旧版导出的 HTML 需要重新导出
- 打开旧文档时会把 `setState` 动作里丢失的空状态(旧交互面板只显示不写回)物化为明确的状态 id,避免「按钮点了没反应」
- PDF(整个工程):多页单文件,每页一张 JPEG 以 `DCTDecode` 内嵌,屏幕 96dpi → PDF 72pt(1px=0.75pt)
## 构建与运行
### 环境
- Windows 10/11
- Visual Studio 2022(C++ 桌面工作负载)
- CMake 3.15+
- Python 3(前端资源打包进 `.rc`)
- vcpkg 静态库:`webview2:x64-windows-static`
### 命令
```powershell
# 构建 Release(内部调用 CMake + MSBuild)
powershell -ExecutionPolicy Bypass -File .\build.ps1
# 产物
build\Release\Visioxure.exe
```
首次构建会自动把 `frontend/` 下的 HTML/CSS/JS 打包进资源;修改前端后需重新构建。
只调 UI 时可用开发模式(前端从 `frontend/` 目录直接加载,无需重新编译):
```powershell
powershell -ExecutionPolicy Bypass -File .\build.ps1 -DevMode
```
### 测试
```powershell
cd build
ctest -C Release --output-on-failure
```
- `vsdx_test`:JSON → VSDX → JSON 往返一致性、包结构断言、坐标 Y 翻转、组合/连接线粘附/二次往返
- 样例文件在 `test/sample/`(Visio 生成的原生 VSDX 与对应 SVG,可用于读取回归与渲染对照)
### 升级版本号
当前版本 **1.2.0**。`CMakeLists.txt` 的 `project(Visioxure VERSION x.y.z)` 是唯一来源,exe「文件属性 → 详细信息」、`app.get_info`(状态栏显示)与 VSDX `AppVersion` 都由它自动派生。升级时改这一处,并同步两处静态兜底值:
- `src/version.hpp`:`VISIOXURE_VERSION` 回退值(不经 CMake 手工编译时使用)
- `frontend/index.html`:`#app-version`(浏览器直开、无 Bridge 时显示)
改完重新执行 `build.ps1`;README 顶部的「当前版本」与 `CODEPLAN.md` 的版本表也要同步。
## 目录结构
```
src/ 应用入口 + VSDX 编解码
main.cpp Bridge 命令:文件对话框 / vsdx.save / vsdx.load / 最近文件
vsdx/ xml(极简 DOM) / package(OPC) / writer / reader
frontend/ 前端(编译期嵌入 exe)
index.html 菜单 / 工具栏 / 三栏布局
js/model.js 文档模型(页面 / 形状 / 面板 / 图层 / 变量)
js/canvas/ viewport / hit / renderer / overlay
js/tools.js 选择 / 创建 / 连接线 / 线段与端点拖拽
js/stencils.js 形状库(分类 / 缩略图 / 插入)
js/table.js 表格组件(行列数 / 等分网格 / 最小行高列宽)
js/style.js 右侧「样式」面板(填充 / 边框 / 连接线属性)
js/colorpicker.js Office 风格调色板(主题色 / 标准色 / 自定义 / 最近颜色)
js/editor.js 快捷键 / 菜单 / 页面树 / 状态栏
js/interact.js 交互运行时(事件 → 动作、变量、动效)
js/preview.js F5 预览
js/inspect.js 右侧「交互」面板
js/fileio.js 打开 / 保存 / 脏标记 / 最近文件
TauriCPP/ 窗口 + WebView2 + Bridge 框架(随仓库提供)
third_party/miniz/ 单文件 zip 库(OPC 打包)
test/ vsdx_test 与 Visio 原生样例
```
## 技术要点
- **坐标**:内部 96 DPI、左上原点、Y 向下;Visio 为英寸、左下原点、Y 向上,写入/读取时做 Pin 与角度翻转
- **布线**:端口法向 + LEAD 出线段 + 折线算法(曲线则为三次贝塞尔采样),折线统一做去重与「去折返」整理,避免线段自我重叠;编辑器与 VSDX 输出一致
- **渲染健壮性**:单个形状绘制异常不会中断整帧(逐形状 try/catch);老版本 WebView2 缺少 `ctx.roundRect` 时退化为手写圆角路径,细线在小比例下保持至少 1 屏幕像素
- **母版**:按母版自身宽高解析 Geometry,再缩放到页面形状;页面行覆盖按 IX 合并
- **持久化**:交互 / 面板 / 变量以 User 单元格 JSON 保存,Visio 侧仅作为不可见数据,不影响打开
## 已知限制
- 圆弧 / 贝塞尔按折线近似:胶囊形会显示为圆角矩形,虚线边框绘制为实线
- 连接线走自研直角折线算法,个别长连线与 Visio 内置走向不同(可手动分段调整)
- 曲线连接线导出 VSDX 时按折线写入;箭头种类导出目前只区分有 / 无,统一写成实心三角
- 只导入非背景页;背景页内容不合并
- 组合级交互不随保存写入
- 富文本多段落只保留首段样式
## 仓库
- Gitee:https://gitee.com/masonwu21/Visioxure
- GitHub:https://github.com/Emsoro/Visioxure
`TauriCPP` 框架自带其 LICENSE,见 [TauriCPP/LICENSE](TauriCPP/LICENSE)。
## 打赏
如果 Visioxure 对你有帮助,欢迎请作者喝杯咖啡。
