)
前言在之前的文档中我们已对 MxCAD 产品进行了宏观介绍并完成了开发环境的初步搭建与 Demo 运行。然而从“运行官方示例”到“构建自有业务系统”之间仍存在概念理解与工程落地的鸿沟。本篇文档的核心目标在于填补这一空白重点解决以下两个关键问题概念理清深入解析MxCAD与MxDraw的技术定位与职能边界。明确MxCAD作为“编辑内核”负责原图数据的深度操作而MxDraw作为“渲染引擎”专注于图纸浏览与非侵入式批注。工程落地指导开发者在自己的项目中从零构建一个具备图纸加载、视图浏览、独立批注功能的最小可行性产品MVP下面以vue项目为讲解示例。通过本文的学习您将掌握如何根据业务需求是仅需审阅批注还是需要修改原图选择合适的技术组件并能够独立搭建起一个可运行的 Web CAD 基础框架为后续开发复杂的在线设计平台奠定坚实基础。一、核心架构解析MxCAD 与 MxDraw 的功能界定在梦想云图DreamCloud CAD的技术体系中MxCAD与MxDraw是两个核心组件。尽管二者在底层紧密耦合但在业务逻辑与应用场景上存在明确的职能划分。理解二者的区别是进行二次开发的前提。1.1 MxDraw轻量级前端渲染与批注引擎定义MxDraw是一个基于 HTML5 Canvas 及 WebGL 技术的前端图形渲染引擎。核心职能图纸浏览与非侵入式批注。渲染展示负责将 CAD 矢量数据高效地绘制于浏览器端支持平移、缩放、旋转等视图操作。批注处理提供独立的批注图层管理功能。用户可在图纸上层添加云线、文字注释、测量标记等信息。数据隔离MxDraw的批注操作不修改原始 DWG/DXF 文件的几何数据与数据库结构。批注信息通常以独立文件如 JSON 或专用批注格式存储或与原图分离保存确保原图的完整性与安全性。适用场景图纸在线审阅、协同设计标注、移动端轻量化查看、无需修改原图的设计评审。1.2 MxCAD全功能 CAD 业务内核定义MxCAD是基于 C 核心通过 WebAssembly (Wasm) 移植至 Web 端的专业 CAD 开发框架。核心职能图纸数据编辑与深度业务逻辑。数据解析完整解析 AutoCAD 原生格式DWG/DXF支持所有版本及复杂实体。实体编辑提供对图纸底层数据库的直接读写能力。支持实体的创建、修改、删除、属性变更等操作这些操作会直接改变原图纸的数据结构。适用场景Web 端在线绘图、图纸深化设计、自动化生成报表、基于图纸数据的业务系统集成。1.3 协作机制与版本演进在实际的技术架构中MxCAD与MxDraw并非孤立存在而是呈现出紧密的层级协作与演进关系基础与升级的关系MxDraw是梦想云图技术体系的基础层。它提供了核心的 HTML5 Canvas 渲染能力、基础的图形交互逻辑以及轻量级的批注功能。其设计初衷是解决“在网页上快速、高效地展示和标注 CAD 图纸”这一核心痛点。MxCAD则是基于MxDraw的全功能升级版本。它在保留并复用MxDraw所有渲染与交互优势的基础上通过引入 C 内核编译为 WebAssembly和 TypeScript 业务框架扩展了完整的 CAD 数据解析、实体编辑、几何计算及复杂命令处理能力。简而言之MxCAD MxDraw (渲染与交互) CAD 专业内核 (数据与逻辑)。协作模式默认集成在大多数应用场景下开发者引入MxCAD开发包时实际上已经包含了MxDraw的功能模块。MxCAD内部会自动调用MxDraw进行图形绘制和用户交互监听。按需调用若业务场景仅需查看与批注如图纸审阅、移动端巡查可直接利用MxCAD中集成的MxDraw接口模式。此时系统表现为轻量级引擎不加载重型编辑内核或仅使用其渲染部分确保启动速度与运行性能。若业务场景涉及原图修改、参数化设计或数据提取则激活MxCAD的完整内核功能对底层数据库进行读写操作。无缝切换由于二者同源开发者可以在同一个项目中根据权限或功能模块动态切换“只读/批注模式”与“编辑模式”无需更换底层引擎保证了用户体验的一致性与技术架构的统一性。这种架构设计既保证了轻量级应用的极致性能又为专业级应用提供了无限扩展的可能。二、构建基础 CAD 项目图纸预览与批注实战2.1 环境准备与项目初始化1. 环境要求Node.js: ≥ v16包管理器: npm / pnpm构建工具:Vite(推荐配置简单开发速度快)Webpack(支持需配置worker-loader或相关 WASM 处理规则)其他Rollup, Parcel 等支持自定义 Loader/Plugin 的构建工具均可。后端服务: 需运行云图开发包提供的图纸转换服务用于处理 DWG/DXF 转 MXWEB。可直接开启云图开发包 3000 端口下的服务。也可自行根据 图纸转换文档 规则设置新的转换接口。2. 创建或集成项目您可新建项目或在现有项目中添加 CAD 模块# 新建 Vue3 TypeScript 项目npmcreate vitelatest cad-viewer ----templatevue-tscdcad-viewernpminstall3. 安装核心依赖# 安装 mxcad 核心包npminstallmxcad# 若使用 pnpm请额外安装 mxdraw (通常 mxcad 已包含视具体版本策略而定)# pnpm add mxdraw4. 配置构建工具支持多线程MxCAD 的高性能渲染依赖SharedArrayBuffer这要求服务器响应头必须包含Cross-Origin-Opener-Policy: same-origin和Cross-Origin-Embedder-Policy: require-corp。无论使用何种打包工具Webpack、Rollup 等都必须进行此配置否则引擎将无法启动或自动降级。以下以Vite为例演示配置方法修改vite.config.ts在server.headers中添加响应头// vite.config.tsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueexportdefaultdefineConfig({plugins:[vue()],server:{// 开发环境直接在此处配置响应头headers:{Cross-Origin-Opener-Policy:same-origin,Cross-Origin-Embedder-Policy:require-corp,}},build:{target:esnext// 确保编译目标支持最新特性}})2.2 创建 Canvas 容器与初始化 MxCAD 引擎1. 模板结构Canvas 与文件上传控件在组件模板中定义渲染容器和文件选择器并添加控制按钮。template!-- CAD 渲染区域 --divstylewidth:100vw;height:95vh;overflow:hidden;canvasidmyCanvas/canvas/div!-- 控制栏 --divstylemargin-top:10px;padding:10px;background:#f5f5f5;!-- 隐藏的文件输入框 --inputtypefilereffileInputaccept.dwg,.dxf,.mxwebchangeopenDwgFilestyledisplay:none/!-- 功能按钮 --buttonclick$refs.fileInput.click():disabled!mxcadReady打开图纸/buttonbuttonclickstartCloudMark:disabled!mxcadReady绘制云线批注/buttonbuttonclicksaveMarkup:disabled!mxcadReady保存批注/buttonbuttonclickloadMarkup:disabled!mxcadReady加载批注/button/div/template2. 初始化 MxCAD 实例在 Vue 组件的onMounted生命周期中调用createMxCad完成 Canvas 绑定、WASM 核心文件路径定位、字体库路径设置以及初始化完成的回调处理。script setup langts import { onMounted, ref } from vue; import { createMxCad, MxCpp } from mxcad; const mxcadReady ref(false); const fileInput refHTMLInputElement | null(null); onMounted(() { // 自动检测浏览器环境支持 SharedArrayBuffer 则启用多线程 (2d)否则降级为单线程 (2d-st) const mode SharedArrayBuffer in window ? 2d : 2d-st; createMxCad({ canvas: #myCanvas, // 动态定位 WASM 文件路径兼容 Vite/Webpack 等构建工具 locateFile: (fileName: string) { return new URL( ../../node_modules/mxcad/dist/wasm/${mode}/${fileName}, import.meta.url ).href; }, fileUrl: , // 初始不加载文件等待用户通过 UI 选择 fontspath: new URL( ../../node_modules/mxcad/dist/fonts, import.meta.url ).href, // 初始化完成回调 onInit: () { console.log(MxCAD 引擎初始化完成); mxcadReady.value true; } }); }); /script更多配置项createMxCad支持丰富的自定义配置如背景色、多选配置、视区移动方式等。如需了解完整的配置参数列表及详细说明请访问官方文档[MxCadConfig 配置接口文档。2.3 打开图纸并预览关键格式说明重要说明MxCAD 文件格式限制MxCAD 引擎内核仅能直接解析和打开特定的.mxweb格式文件。它无法直接在浏览器端读取原生的 AutoCAD 格式如.dwg或.dxf。因此在实现“打开图纸”功能时必须遵循以下逻辑判断格式检查用户选择的文件后缀。格式转换如果文件是.dwg或.dxf必须先将其上传至后端转换服务由服务端将其转换为.mxweb格式。加载渲染只有获取到.mxweb格式的文件流或 URL 后才能调用mxcad.openWebFile()进行加载和渲染。若跳过转换步骤直接尝试加载 DWG 文件MxCAD 将报错或无法显示任何内容。1. 文件选择与处理流程基于上述限制我们的代码逻辑分为两条路径路径 A (.mxweb)浏览器原生支持直接生成临时 URL 加载。路径 B (.dwg/.dxf)调用本地转换服务localhost:3000/uploadfile上传 - 服务端自动转换 - 返回/生成.mxweb路径 - 加载。2. 跨域处理配置由于前端开发服务器默认localhost:5173与图纸转换服务localhost:3000端口不同直接请求会触发浏览器的跨域限制 (CORS)。无论使用何种打包工具Webpack、Rollup 等在开发环境下都必须配置代理Proxy或将请求转发至同源以解决跨域问题。生产环境通常通过 Nginx 反向代理统一入口来解决。以下以Vite为例演示开发环境的代理配置修改vite.config.ts添加server.proxy配置将/api或特定路径的请求转发至转换服务// vite.config.tsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueexportdefaultdefineConfig({plugins:[vue()],server:{// ....其他配置// 开发环境跨域代理配置proxy:{// 匹配所有以 /api 开头的请求建议前端请求时加上 /api 前缀/api:{target:http://localhost:3000,// 图纸转换服务地址changeOrigin:true,// 修改 Host 头为 targetrewrite:(path)path.replace(/^\/api/,),// 去掉 /api 前缀再转发},// 或者直接代理特定的转换接口路径///uploadfile: {// target: http://localhost:3000,// changeOrigin: true,// },// /demo: {// target: http://localhost:3000,// changeOrigin: true,// }}}})前端代码适配示例配置代理后前端请求地址需调整为相对路径或带前缀的路径// 原地址http://localhost:3000/uploadfile// 代理后地址/api/uploadfile (需在 proxy 中配置 rewrite) 或直接 /uploadfileconstresawaitfetch(/api/uploadfile,{// Vite 会自动拦截并转发到 localhost:3000/uploadfilemethod:POST,body:formData,});3. 代码实现打开网络图纸图纸的加载与渲染核心依赖于 MxCAD 提供的openWebFileAPI。该接口支持从网络 URL 直接加载.mxweb或转换后的图纸数据并提供了丰富的参数控制如是否使用多线程、加载策略等。script setup langts// ... 上述初始化代码 ...// 打开图纸处理函数constopenDwgFileasync(event:Event){consttargetevent.targetasHTMLInputElement;constfiletarget.files?.[0];if(!file)return;constfileNamefile.name;// 获取文件后缀并转为小写constfileExtfileName.slice(fileName.lastIndexOf(.)).toLowerCase();constmxcadMxCpp.getCurrentMxCAD();if(fileExt.dwg||fileExt.dxf){// DWG/DXF 需要后端转换constformDatanewFormData();formData.append(file,file);try{// 调用代理后的上传接口constresawaitfetch(/upfile/mxcad,{method:POST,body:formData,});if(!res.ok)thrownewError(请求失败${res.status});// 约定转换后的文件位于 /demo/ 目录下文件名不变后缀变为 .mxwebconstmxwebFullUrl/demo/${fileName}.mxweb;mxcad.openWebFile(mxwebFullUrl);}catch(err){console.error(err);alert(上传或转换失败请检查后端服务是否启动);}}elseif(fileExt.mxweb){// MXWEB 直接读取consttempUrlURL.createObjectURL(file);mxcad.openWebFile(tempUrl);}else{alert(不支持该文件格式请上传 .dwg, .dxf 或 .mxweb);}// 重置 input value允许重复选择同一文件target.value;};/script关键点说明转换接口:http://localhost:3000/uploadfile是云图开发包自带的演示服务实际生产环境请替换为您的后端地址。路径约定: 代码假设转换服务会将结果固定在/demo/目录下且文件名保持原名仅后缀变为.mxweb。API 调用: 无论源文件是什么最终都统一调用mxcad.openWebFile(url)进行渲染。openWebFile支持更多高级参数例如控制是否使用工作线程 (isWorkThread)、指定数据加载到内存还是 IndexedDB (fetchAttributes) 等。如需了解完整的参数定义及详细说明请访问官方文档 McObject.openWebFile API 文档。2.4 批注功能实现创建、保存、回显1. 创建批注以审图云线为例此功能通过MxDraw提供的交互接口让用户在图上绘制云线并添加文字说明。import{MxFun,MrxDbgUiPrPoint,McEdGetPointWorldDrawObject,MrxDbgUiPrBaseReturn,MxDbRectBoxLeadComment,}frommxdraw;// 绘制云线批注函数functionstartCloudMark(){constpointnewMrxDbgUiPrPoint();// 获取点交互对象constmxDrawMxFun.getCurrentDraw();// 获取当前绘图对象constworldDrawCommentnewMcEdGetPointWorldDrawObject();// 动态绘制辅助对象constmxCheckDrawnewMxDbRectBoxLeadComment();// 云线批注实体对象// 设置云线半径屏幕坐标转文档坐标mxCheckDraw.radiusMxFun.screenCoordLong2Doc(5);mxCheckDraw.setLineWidth(3);mxCheckDraw.setLineWidthByPixels(true);// 第一步获取起始点point.setMessage(\n云线框起始点: );point.go((status){if(status!MrxDbgUiPrBaseReturn.kOk)return;mxCheckDraw.point1point.value();// 动态预览移动鼠标时绘制矩形worldDrawComment.setDraw((currentPoint){mxCheckDraw.point2currentPoint;worldDrawComment.drawCustomEntity(mxCheckDraw);});point.setUserDraw(worldDrawComment);point.setMessage(\n云线框结束点: );// 第二步获取结束点point.go((status){if(status!MrxDbgUiPrBaseReturn.kOk)return;mxCheckDraw.point2point.value();// 动态预览确定文本位置worldDrawComment.setDraw((currentPoint){mxCheckDraw.point3currentPoint;worldDrawComment.drawCustomEntity(mxCheckDraw);});// 设置批注文本属性mxCheckDraw.text审图批注;mxCheckDraw.textWidthMxFun.screenCoordLong2Doc(100);mxCheckDraw.textHeightMxFun.screenCoordLong2Doc(50);mxCheckDraw.fixedSizetrue;if(mxCheckDraw.fixedSize){mxCheckDraw.textHeight20;mxCheckDraw.textWidth130;}point.setMessage(\n审图标注点: );// 第三步获取文本引出点point.go((status){if(status!MrxDbgUiPrBaseReturn.kOk)return;mxCheckDraw.point3point.value();// 将实体添加到图纸数据库mxDraw.addMxEntity(mxCheckDraw);});});});}绘制效果如下所示2. 保存批注数据使用官方推荐的saveMxEntityToJson()方法将当前图纸上的所有非原生实体即批注序列化为 JSON 字符串。本示例暂存至localStorage模拟数据库存储。import{MxFun}frommxdraw;// 保存图纸批注constsaveMarkup(){constdrawMxFun.getCurrentDraw();if(!draw)return;// 序列化批注数据constjsonDatadraw.saveMxEntityToJson();localStorage.setItem(mx-markup-data,jsonData);alert(批注已保存至本地存储);};3. 回显批注数据当用户再次打开图纸时从存储中读取 JSON 数据并调用loadMxEntityFromJson()还原批注。import{MxFun}frommxdraw;// 恢复图纸批注constloadMarkup(){constdrawMxFun.getCurrentDraw();if(!draw)return;constjsonDatalocalStorage.getItem(mx-markup-data);if(jsonData){draw.loadMxEntityFromJson(jsonData);alert(批注已加载);}else{alert(未找到保存的批注数据);}};最佳实践提示在实际业务中应将saveMarkup生成的 JSON 数据通过 AJAX/Fetch 发送给后端与图纸 ID 关联存储loadMarkup应在图纸加载完成后监听onOpenFileComplete回调自动从后端拉取数据并执行加载。2.5 运行验证启动服务确保云图转换服务已在localhost:3000运行。启动前端项目npm run dev。测试流程预览 MXWEB点击“打开图纸”选择.mxweb文件 → 图纸秒开。预览 DWG点击“打开图纸”选择.dwg文件 → 自动上传转换 → 加载转换后的图纸。绘制批注点击“绘制云线批注”在图上依次点击起始点、结束点、文字引出点 → 云线绘制成功。保存点击“保存批注” → 检查浏览器 LocalStorage 是否有mx-markup-data键值。回显刷新页面清空内存重新打开同一张图纸 → 点击“加载批注” → 确认云线准确还原。三、常见问题与注意事项路径配置敏感性Wasm 文件和字体文件的路径配置必须精确。若控制台出现 404 错误或 Wasm 编译失败请首先检查public目录结构及初始化参数中的locateFile和fontspath路径字符串是否正确。跨域隔离策略 (COOP/COEP)较新版本的 MxCAD 利用SharedArrayBuffer进行多线程优化以提升性能。若在 Chrome/Edge 中遇到SharedArrayBuffer is not defined相关报错必须在 Web 服务器或 Vite 配置的响应头中严格配置Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp字体缺失处理若图纸文字显示为问号或乱码通常是因为缺少对应的 SHX 字体文件。请确保开发包中的fonts目录已完整部署到项目中或在后端转换服务中配置字体映射。大文件性能对于超过 50MB 的超大图纸建议在加载前进行前端提示。可考虑启用 SDK 中的按需加载功能或简化显示模式如关闭抗锯齿、隐藏填充图案以优化渲染帧率。批注数据管理批注数据是独立于原图存在的。务必在前端或后端建立“图纸 ID - 批注 JSON”的映射关系避免不同图纸间的批注混淆。