慣性聚合 高效追蹤和閱讀你感興趣的部落格、新聞、科技資訊
閱讀原文 在慣性聚合中打開

推薦訂閱源

小众软件
小众软件
博客园 - 叶小钗
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
Hugging Face - Blog
Hugging Face - Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
aimingoo的专栏
aimingoo的专栏
Blog — PlanetScale
Blog — PlanetScale
爱范儿
爱范儿
T
Tailwind CSS Blog
Jina AI
Jina AI
量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
V
Visual Studio Blog
月光博客
月光博客

博客园 - 梦想CAD控件

在线CAD视图控制与图层管理二开实战 开源网页实时协同设计平台-在线编辑CAD图纸 在线CAD SDK开发包图纸转换功能使用教程(在线CAD API) 统信麒麟鸿蒙系统软件集成CAD功能(国产系统CAD控件) 网页CAD开发包结构与功能说明(网页CAD实时协同编辑) 网页CAD结合AI实现自然语言设计CAD图纸 (JS实现预览)在线CAD中的“组”功能开发 (在线CAD)html在线预览cad图纸SDK集成方法 (JS编辑DWG文件)在线CAD二开实现图纸表格提取到excel 网页版CAD与gis结合实现在线地图和CAD编辑 (html在线预览cad图纸插件)在线CAD实现形位公差标注 (WEB CAD API )网页CAD插件如何开发焊接符号 (HTML VUE在线编辑DWG)网页CAD利用AI实现多行文本功能的开发 (web cad sdk)在线CAD中配置属性的使用教程 (WEB CAD二次开发)在线CAD SDK调用内部弹框的方法 在线CAD插件通过上下文对象MxPluginContext修改UI界面的方法 国产操作系统中好用的CAD软件(统信,麒麟,信创环境安装CAD) (pdm集成CAD SDK)在线CAD绘制条形码、二维码的教程 在线CAD绘制门和窗(WEB CAD二次开发家装设计软件) 在线CAD绘制墙体(WEB端开发室内设计软件) (在线三维参数化建模)网页三维CAD中加载和保存STEP模型 (H5在线CAD SDK)在线CAD中线型表的使用方法 (web查看三维CAD图纸)在三维网页CAD中绘制一个窗户模型
Web CAD圖形引擎實現DWG圖紙網頁批註和查看
梦想CAD控件 · 2026-05-27 · via 博客园 - 梦想CAD控件

前言

在之前的文檔中,我們已對 MxCAD 產品進行了宏觀介紹,並完成了開發環境的初步搭建與 Demo 運行。然而,從運行官方示例構建自有業務系統之間,仍存在概念理解與工程落地的鴻溝。本篇文檔的核心目標在於填補這一空白,重點解決以下兩個關鍵問題:

概念理清:深入解析 MxCAD  MxDraw 的技術定位與職能邊界。明確 MxCAD 作為編輯內核負責原圖數據的深度操作,而 MxDraw 作為渲染引擎專注於圖紙瀏覽與非侵入式批註。

工程落地:指導開發者在自己的項目中,從零構建一個具備圖紙加載、視圖瀏覽、獨立批註功能的最小可行性產品(MVP),下面以vue項目為講解示例。

通過本文的學習,您將掌握如何根據業務需求(是僅需審閱批註,還是需要修改原圖)選擇合適的技術組件,並能夠獨立搭建起一個可運行的 Web CAD 基礎框架,為後續開發複雜的在線設計平臺奠定堅實基礎。

1

. 核心架構解析: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 並非孤立存在,而是呈現出緊密的層級協作與演進關係:

2

基礎與升級的關係

MxDraw 是夢想雲圖技術體系的基礎層。它提供了核心的 HTML5 Canvas 渲染能力、基礎的圖形交互邏輯以及輕量級的批註功能。其設計初衷是解決在網頁上快速、高效地展示和標註 CAD 圖紙這一核心痛點。

MxCAD 則是基於 MxDraw 的全功能升級版本。它在保留並複用 MxDraw 所有渲染與交互優勢的基礎上,通過引入 C++ 內核(編譯為 WebAssembly)和 TypeScript 業務框架,擴展了完整的 CAD 數據解析、實體編輯、幾何計算及複雜命令處理能力。

簡而言之MxCAD = MxDraw (渲染與交互) + CAD 專業內核 (數據與邏輯)

協作模式

默認集成:在大多數應用場景下,開發者引入 MxCAD 開發包時,實際上已經包含了 MxDraw 的功能模塊。MxCAD 內部會自動調用 MxDraw 進行圖形繪製和用戶交互監聽。

按需調用: 

  • 若業務場景僅需查看與批註(如圖紙審閱、移動端巡查),可直接利用 MxCAD 中集成的 MxDraw 接口模式。此時系統表現為輕量級引擎,不加載重型編輯內核(或僅使用其渲染部分),確保啟動速度與運行性能。
  • 若業務場景涉及原圖修改、參數化設計或數據提取,則激活 MxCAD 的完整內核功能,對底層數據庫進行讀寫操作。

無縫切換:由於二者同源,開發者可以在同一個項目中根據權限或功能模塊,動態切換只讀/批註模式編輯模式,無需更換底層引擎,保證了用戶體驗的一致性與技術架構的統一性。

這種架構設計既保證了輕量級應用的極致性能,又為專業級應用提供了無限擴展的可能。

. 構建基礎 CAD 項目:圖紙預覽與批註實戰

2.1 環境準備與項目初始化

環境要求

Node.js: ≥ v16

包管理器: npm / pnpm

構建工具:

Vite (推薦,配置簡單,開發速度快)

Webpack (支持,需配置 worker-loader 或相關 WASM 處理規則)

其他:Rollup, Parcel 等支持自定義 Loader/Plugin 的構建工具均可。

後端服務: 需運行雲圖開發包提供的圖紙轉換服務,用於處理 DWG/DXF MXWEB

可直接開啟雲圖開發包 3000 端口下的服務。

也可自行根據圖紙轉換文檔規則設置新的轉換接口。

創建或集成項目

您可新建項目或在現有項目中添加 CAD 模塊:

# 新建 Vue3 + TypeScript 項目
npm create vite@latest cad-viewer -- --template vue-ts
cd cad-viewer
npm install

安裝核心依賴

# 安裝 mxcad 核心包
npm install mxcad
# 若使用 pnpm,請額外安裝 mxdraw (通常 mxcad 已包含,視具體版本策略而定)
# pnpm add mxdraw

配置構建工具支持多線程

MxCAD 的高性能渲染依賴 SharedArrayBuffer,這要求服務器響應頭必須包含 Cross-Origin-Opener-Policy: same-origin  Cross-Origin-Embedder-Policy: require-corp無論使用何種打包工具(WebpackRollup 等),都必須進行此配置,否則引擎將無法啟動或自動降級。

下面以 Vite 為例演示配置方法,修改 vite.config.ts,在 server.headers 中添加響應頭:

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  server: {
    // 開發環境:直接在此處配置響應頭
    headers: {
      "Cross-Origin-Opener-Policy": "same-origin",
      "Cross-Origin-Embedder-Policy": "require-corp",
    }
  },
  build: {
    target: 'esnext' // 確保編譯目標支持最新特性
  }
})

2.2 創建 Canvas 容器與初始化 MxCAD 引擎

模板結構:Canvas 與文件上傳控件

在組件模板中定義渲染容器和文件選擇器,並添加控制按鈕。

<template>
  <!-- CAD 渲染區域 -->
  <div style="width: 100vw; height: 95vh; overflow: hidden;">
    <canvas id="myCanvas"></canvas>
  </div>

  <!-- 控制欄 -->
  <div style="margin-top: 10px; padding: 10px; background: #f5f5f5;">
    <!-- 隱藏的文件輸入框 -->
    <input
      type="file"
      ref="fileInput"
      accept=".dwg,.dxf,.mxweb"
      @change="openDwgFile"
      style="display:none"
    />
    
    <!-- 功能按鈕 -->
    <button @click="$refs.fileInput.click()" :disabled="!mxcadReady">打開圖紙</button>
    <button @click="startCloudMark" :disabled="!mxcadReady">繪製雲線批註</button>
    <button @click="saveMarkup" :disabled="!mxcadReady">保存批註</button>
    <button @click="loadMarkup" :disabled="!mxcadReady">加載批註</button>
  </div>
</template>

初始化 MxCAD 實例

Vue 組件的 onMounted 生命週期中調用 createMxCad,完成 Canvas 綁定、WASM 核心文件路徑定位、字體庫路徑設置以及初始化完成的回調處理。

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { createMxCad, MxCpp } from 'mxcad';

const mxcadReady = ref(false);
const fileInput = ref<HTMLInputElement | 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 將報錯或無法顯示任何內容。

3

文件選擇與處理流程

基於上述限制,我們的代碼邏輯分為兩條路徑:

  • 路徑 A (.mxweb):瀏覽器原生支持,直接生成臨時 URL 加載。
  • 路徑 B (.dwg/.dxf):調用本地轉換服務 localhost:3000/uploadfile 上傳 -> 服務端自動轉換 -> 返回/生成 .mxweb 路徑 -> 加載。

跨域處理配置

由於前端開發服務器(默認 localhost:5173)與圖紙轉換服務(localhost:3000)端口不同,直接請求會觸發瀏覽器的跨域限制 (CORS)

無論使用何種打包工具(WebpackRollup 等),在開發環境下都必須配置代理(Proxy)或將請求轉發至同源,以解決跨域問題。生產環境通常通過 Nginx 反向代理統一入口來解決。

以下以 Vite 為例演示開發環境的代理配置:

修改 vite.config.ts,添加 server.proxy 配置,將 /api 或特定路徑的請求轉發至轉換服務:

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  server: {
    // ....其他配置 
    // 開發環境跨域代理配置
    proxy: {
      // 匹配所有以 /api 開頭的請求(建議前端請求時加上 /api 前綴)
      '/api': {
        target: 'http://localhost:3000', // 圖紙轉換服務地址
        changeOrigin: true,              // 修改 Host 頭為 target
        rewrite: (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) 或直接 /uploadfile
const res = await fetch("/api/uploadfile", { // Vite 會自動攔截並轉發到 localhost:3000/uploadfile
  method: "POST",
  body: formData,
});

 代碼實現:打開網絡圖紙

圖紙的加載與渲染核心依賴於 MxCAD 提供的 openWebFile API。該接口支持從網絡 URL 直接加載 .mxweb 或轉換後的圖紙數據,並提供了豐富的參數控制(如是否使用多線程、加載策略等)。

<script setup lang="ts">
// ... 上述初始化代碼 ...

// 打開圖紙處理函數
const openDwgFile = async (event: Event) => {
  const target = event.target as HTMLInputElement;
  const file = target.files?.[0];
  if (!file) return; 
  const fileName = file.name;
  // 獲取文件後綴並轉為小寫
  const fileExt = fileName.slice(fileName.lastIndexOf(".")).toLowerCase();
  const mxcad = MxCpp.getCurrentMxCAD();

  if (fileExt === ".dwg" || fileExt === ".dxf") {
    // DWG/DXF 需要後端轉換
    const formData = new FormData();
    formData.append("file", file);
    
    try {
      // 調用代理後的上傳接口
      const res = await fetch("/upfile/mxcad", {
        method: "POST",
        body: formData,
      });
      
      if (!res.ok) throw new Error(`請求失敗:${res.status}`);
      
      // 約定:轉換後的文件位於 /demo/ 目錄下,文件名不變,後綴變為 .mxweb
      const mxwebFullUrl = `/demo/${fileName}.mxweb`;
      mxcad.openWebFile(mxwebFullUrl);
      
    } catch (err) {
      console.error(err);
      alert("上傳或轉換失敗,請檢查後端服務是否啟動");
    }
  } else if (fileExt === ".mxweb") {
    // MXWEB 直接讀取
    const tempUrl = URL.createObjectURL(file);
    mxcad.openWebFile(tempUrl);
  } else {
    alert("不支持該文件格式,請上傳 .dwg, .dxf 或 .mxweb");
  }
  // 重置 input value,允許重複選擇同一文件
  target.value = "";
};
</script>

 關鍵點說明:

  • 轉換接口: //localhost:3000/uploadfile 是雲圖開發包自帶的演示服務,實際生產環境請替換為您的後端地址。
  • 路徑約定: 代碼假設轉換服務會將結果固定在 /demo/ 目錄下,且文件名保持原名僅後綴變為 .mxweb
  • API 調用: 無論源文件是什麼,最終都統一調用 mxcad.openWebFile(url) 進行渲染。openWebFile 支持更多高級參數,例如控制是否使用工作線程 (isWorkThread)、指定數據加載到內存還是 IndexedDB (fetchAttributes) 等。如需瞭解完整的參數定義及詳細說明,請訪問官方文檔: McObject.openWebFile API 文檔

2.4 批註功能實現(創建、保存、回顯)

創建批註(以審圖雲線為例)

此功能通過 MxDraw 提供的交互接口,讓用戶在圖上繪製雲線並添加文字說明。

import {
  MxFun,
  MrxDbgUiPrPoint,
  McEdGetPointWorldDrawObject,
  MrxDbgUiPrBaseReturn,
  MxDbRectBoxLeadComment,
} from "mxdraw";
// 繪製雲線批註函數
function startCloudMark() {
  const point = new MrxDbgUiPrPoint(); // 獲取點交互對象
  const mxDraw = MxFun.getCurrentDraw(); // 獲取當前繪圖對象
  const worldDrawComment = new McEdGetPointWorldDrawObject(); // 動態繪製輔助對象
  const mxCheckDraw = new MxDbRectBoxLeadComment(); // 雲線批註實體對象
  // 設置雲線半徑(屏幕座標轉文檔座標)
  mxCheckDraw.radius = MxFun.screenCoordLong2Doc(5);
  mxCheckDraw.setLineWidth(3);
  mxCheckDraw.setLineWidthByPixels(true);
  // 第一步:獲取起始點
  point.setMessage("\n雲線框起始點: ");
  point.go((status) => {
    if (status != MrxDbgUiPrBaseReturn.kOk) return;    
    mxCheckDraw.point1 = point.value();    
    // 動態預覽:移動鼠標時繪製矩形
    worldDrawComment.setDraw((currentPoint) => {
      mxCheckDraw.point2 = currentPoint;
      worldDrawComment.drawCustomEntity(mxCheckDraw);
    });
    point.setUserDraw(worldDrawComment);
    point.setMessage("\n雲線框結束點: ");
    // 第二步:獲取結束點
    point.go((status) => {
      if (status != MrxDbgUiPrBaseReturn.kOk) return;     
      mxCheckDraw.point2 = point.value();      
      // 動態預覽:確定文本位置
      worldDrawComment.setDraw((currentPoint) => {
        mxCheckDraw.point3 = currentPoint;
        worldDrawComment.drawCustomEntity(mxCheckDraw);
      });
      // 設置批註文本屬性
      mxCheckDraw.text = "審圖批註";
      mxCheckDraw.textWidth = MxFun.screenCoordLong2Doc(100);
      mxCheckDraw.textHeight = MxFun.screenCoordLong2Doc(50);
      mxCheckDraw.fixedSize = true;
      if (mxCheckDraw.fixedSize) {
        mxCheckDraw.textHeight = 20;
        mxCheckDraw.textWidth = 130;
      }
      point.setMessage("\n審圖標註點: ");
      // 第三步:獲取文本引出點
      point.go((status) => {
        if (status != MrxDbgUiPrBaseReturn.kOk) return;
        mxCheckDraw.point3 = point.value();
        // 將實體添加到圖紙數據庫
        mxDraw.addMxEntity(mxCheckDraw);
      });
    });
  });
}

 繪製效果如下所示:

4

保存批註數據

使用官方推薦的 saveMxEntityToJson() 方法,將當前圖紙上的所有非原生實體(即批註)序列化為 JSON 字符串。本示例暫存至 localStorage 模擬數據庫存儲。

import { MxFun } from "mxdraw";
// 保存圖紙批註
const saveMarkup = () => {
  const draw = MxFun.getCurrentDraw();
  if (!draw) return;  
  // 序列化批註數據
  const jsonData = draw.saveMxEntityToJson();
  localStorage.setItem("mx-markup-data", jsonData);
  alert("批註已保存至本地存儲");
};

 回顯批註數據

當用戶再次打開圖紙時,從存儲中讀取 JSON 數據,並調用 loadMxEntityFromJson() 還原批註。

import { MxFun } from "mxdraw";

// 恢復圖紙批註
const loadMarkup = () => {
  const draw = MxFun.getCurrentDraw();
  if (!draw) return;

  const jsonData = localStorage.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-origin

Cross-Origin-Embedder-Policy: require-corp

字體缺失處理

若圖紙文字顯示為問號或亂碼,通常是因為缺少對應的 SHX 字體文件。請確保開發包中的 fonts 目錄已完整部署到項目中,或在後端轉換服務中配置字體映射。

大文件性能

對於超過 50MB 的超大圖紙,建議在加載前進行前端提示。可考慮啟用 SDK 中的按需加載功能或簡化顯示模式(如關閉抗鋸齒、隱藏填充圖案)以優化渲染幀率。

批註數據管理

批註數據是獨立於原圖存在的。務必在前端或後端建立圖紙 ID - 批註 JSON”的映射關係,避免不同圖紙間的批註混淆。