seatmap-editor
seatmap-editor
基于 Vue 3 与 Konva 的场馆绘座与选座编辑器。
An open-source venue seating editor built with Vue 3 and Konva — region drawing, compound holes, DXF/SVG import, price levels and staged release plans.
这是什么
一个可以直接运行的场馆座位图编辑器,用来把 CAD 图纸或 SVG 平面图变成可交互的选座业务数据: 绘制区域与座位、划分票档、配置分阶段开放计划,并导出 JSON 草稿交给业务端渲染选座页。
仓库自带完整演示工作台,npm run dev 即可开始绘制;同时导出 SeatMapEditor 组件与几何工具函数,
方便嵌入已有的 Vue 应用。
功能概览
区域绘制
- 矩形、椭圆、多边形、直线、二次贝塞尔弧线和测距标注。
- 拖拽整体移动,逐顶点、端点与弧线控制点微调;矩形与多边形可点选边并拖动控制点设置正负弯曲量。
- 每个顶点可设为「棱角 / 圆滑」并调整切线影响范围;圆滑连接经过原顶点,不会截断两边。
- 快捷键:选中边后用
[/]微调弯曲量、0恢复直线;选中顶点后用1切换棱角、2切换圆滑。 - 按住
Space或H配合鼠标拖拽可临时平移,松开后自动回到选择工具。 - 区域支持
Ctrl+D复制、15° 步进旋转、锁定、尺寸显隐和对象层内前后顺序调整。
复合区域与孔洞
- 左上角「区域工具 / 孔洞工具」互斥切换:区域模式只编辑独立区域,孔洞不可直接命中。
- 选中闭合外区域后进入孔洞模式,可新增、平移、调整或删除该区域内部孔洞,并在左栏查看孔洞列表。
- 矩形与圆形孔沿用四角加四边中点的八点缩放,自由孔逐顶点调整,拖动过程始终限制在父区域范围内。
- 孔洞可拆回独立多边形或直接删除;主画布、座位画布、鹰眼与发布预览统一使用
evenodd填充。
CAD 与 SVG 导入
- 上传 ASCII DXF 自动识别毫米、厘米、米、英寸和英尺,按图层筛选,并把闭合
LWPOLYLINE/POLYLINE、 圆、椭圆、闭合样条、SOLID/3DFACE转为可编辑区域;开放线、圆弧、文字、标注可作为参考对象导入。 - 解析在 Web Worker 中执行,确认后整批只产生一条撤销记录。
- 上传 SVG 解析基础图形、文字、分组、
defs/use、viewBox、嵌套变换与文档内 CSS, 路径命令M/L/H/V/C/S/Q/T/A/Z会采样为可继续编辑的区域或参考线;同一<path>内的闭合子路径 按evenodd或nonzero自动识别为复合区域孔洞。 - 脚本、外部引用、图片、裁剪、遮罩和滤镜会被阻止或给出兼容性提示;DWG、二进制 DXF、
HATCH/ACIS/代理对象会明确计入跳过统计。
座位绘制
- 在画布拖出首排基准线再指定整体深度,自动生成规则座位矩阵;每个座位块用单个 Konva Shape 批量绘制, 座位数量不会等量增加场景节点。
- 座距、排距、错位、弧高、过道宽度和座位尺寸均以米保存,按文档级
pixelsPerMeter换算为画布坐标。 - 支持「后排每排增减」生成前窄后宽或前宽后窄的梯形座位块,开启「居中变化」时增减都围绕首排中心对齐。
- 编号支持数字、字母、方向、奇偶步长、蛇形、跨排连续和跳号;显式纵向/横向过道与座位缺口在重新生成时不会补回。
- 座位块始终单选,可整体平移或围绕块中心按指定角度旋转校正,两种操作都只提交一条可撤销历史。
- 排号竖条可通过
showRowLabels开启,支持左右位置、米制宽度、边框与字号配置。 - 单座可设置
0/90/180/270四向旋转,座椅旋转时座位号保持正向。
票档与选座预览
- 票档步骤支持价格与颜色管理、实时画笔预览、可见范围、清除、整排、框选、套索和平移;
B/E/R/X/L切换工具,1/3/5切换画笔范围,空格或H临时平移。 - 座位的
priceLevelId是事实来源,区域主票档图作为可检测过期的缓存保存。 - 选座预览支持场馆总览、区域视角和座位视角三级缩放;最大视角可配置为「直接座位」以锁定在座位层。
- 座位绘制、票档和选座预览共用右上角鹰眼,可点击或拖动快速定位,也可收起为图标。
- 发布步骤支持一期、二期及更多开放阶段,为每期选择区域与开放时段,导出的发布计划可按指定时间计算允许选座的区域。
舞台与幕布
- 首次拖拽确定幕布宽度,创建后用两端点调整宽度;弧顶锁定在跨度正中且只调整弧高。
- 渐变带从幕布向内弧前方过渡,两个前沿角点可独立拖动深度和横向收放形成梯形投影, 也可设置统一前景深度、双色渐变、透明度、文字与字号。
工程能力
- 撤销、重做、自动保存、本地恢复与 JSON 导出,两步工作流共用同一份历史。
- 新建场馆默认
20px = 1m,可在0.1–1000px/m范围内修改比例,换算保留小数以保证极端比例往返可逆。 - 网格显示、交叉点吸附与
0.1–1000m基础网格间距,缩小时按1/2/5 × 10^n自动合并。 - 草稿以
schemaVersion标识,加载时逐级迁移,兼容历史seatSize/seatRadius字段。
快速开始
需要 Node.js >= 20.19.0 与 npm。
git clone <仓库地址>
cd seatmap-editor
npm ci
npm run dev
仓库已提交
package-lock.json,推荐用npm ci安装以获得可复现的依赖树。 根目录的.npmrc关闭了 peer 依赖自动解析,这是为了绕开 npm 在重建依赖树时 解析vitestoptional peer 会触发的 arborist 报错,原因写在.npmrc注释里。
常用脚本
| 命令 | 说明 |
|---|---|
npm run dev |
启动演示工作台开发服务器 |
npm run build |
构建待发布的库产物,输出到 dist/(等同 build:lib) |
npm run build:lib |
类型检查 → 库构建 → 生成 .d.ts 类型声明 |
npm run build:demo |
构建静态演示站,输出到 dist-demo/ |
npm run preview |
预览演示站构建产物 |
npm test |
运行单元测试 |
npm run test:watch |
监听模式运行单元测试 |
npm run typecheck |
vue-tsc 类型检查 |
作为组件接入
直接安装已发布的包,产物是编译好的 ESM 与类型声明,Webpack、Rollup、Vite 均可消费:
npm install seatmap-editor konva
import { SeatMapEditor } from 'seatmap-editor';
import 'seatmap-editor/style.css';
也可以按需引用几何与数据层工具,例如 regionHoleContainsPoint:
import { regionHoleContainsPoint } from 'seatmap-editor';
vue是 peer 依赖,由宿主工程提供;konva、dxf-parser、@lucide/vue会随本包自动安装。 组件自带全部样式,不依赖任何第三方 UI 组件库或 Tailwind CSS。 DXF 导入依赖 Web Worker,请确保构建工具支持new Worker(new URL(...), { type: 'module' })。
在仓库内开发调试时,npm run build:lib 会重新生成 dist/;如需在消费端联调,可用
npm pack 产出 tarball 后安装,或让宿主工程通过 link: 指向本目录。
目录结构
src/
├── App.vue # 演示工作台:顶栏、画布、属性栏编排
├── index.ts # 包入口(类型入口),导出组件、几何工具与数据模型
├── lib-entry.ts # 库构建入口:聚合样式并转发 index 的公开 API
├── main.ts # 演示应用挂载入口
├── models.ts # 区域、座位块、票档、发布计划等数据模型
├── geometry.ts # 多边形与孔洞几何计算
├── seat-layout.ts # 座位矩阵生成、梯形排布、编号与过道
├── price-level.ts # 票档分配与校验
├── release-plan.ts # 分阶段开放计划
├── region-tools.ts # 区域工具状态机
├── projection-screen.ts # 舞台幕布几何
├── grid.ts / color.ts # 网格吸附与颜色换算
├── dxf-import.ts # DXF 解析
├── svg-import.ts # SVG 解析
├── preview.ts # 选座预览视角与命中判定
├── components/ # 画布、工具栏与属性面板
│ └── ui/ # 内置轻量 UI 原子组件(Button / Input / Slider 等)
├── composables/ # 编辑器状态、历史与草稿持久化
├── styles/ # 内置组件基础样式
└── workers/ # DXF 解析 Worker
tests/ # 单元测试(Vitest)
docs/ # 详细设计说明书
scripts/ # 构建辅助脚本
vite.config.ts # 演示站构建配置(输出 dist-demo/)
vite.lib.config.ts # npm 库构建配置(输出 dist/)
tsconfig.build.json # 类型声明生成配置
坐标与数据约定
- 长度一律以米存储,仅在渲染时按
pixelsPerMeter换算为画布坐标,因此比例尺调整不会改变业务数据。 - 座位块的座距、排距、过道宽度、缺口宽度和座位尺寸都是米制参数,不属于画布缩放语义。
- 座位颜色由
priceLevelId决定;区域主票档图只是可检测过期的缓存。 - 草稿的
schemaVersion一旦发布不应回改,新增字段需在use-region-editor中补迁移分支。 - 本地演示草稿保存在
localStorage的seatmap-region-editor-v1键下; 首次读取时会自动迁移早期的ikuzo-region-editor-v1草稿并清理旧键。
浏览器支持
面向支持 ES2020 与 Web Worker 模块加载的现代浏览器(Chrome / Edge / Firefox / Safari 最新两个大版本)。 移动端按编辑文档保存的视角规则展示选座预览。
设计文档
docs/ 下保留了实现过程中沉淀的设计说明书:
参与贡献
欢迎提交 Issue 与 PR,请先阅读 CONTRIBUTING.md。 变更记录见 CHANGELOG.md。
许可证
第三方资源
- 座椅图标
src/assets/default-seat.svg随仓库以 MIT 许可提供。 - 图标集来自 lucide(ISC 许可)。
- 画布渲染基于 Konva,DXF 解析基于 dxf-parser。
Related Packages
Extend Konva's functionality to export stages as SVG. Enhance the quality of exp...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.2.0 | ^3.5.0 | MIT |