惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
博客园_首页
Google DeepMind News
Google DeepMind News
博客园 - Franky
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
有赞技术团队
有赞技术团队
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
Recent Announcements
Recent Announcements
A
About on SuperTechFans
博客园 - 【当耐特】
博客园 - 三生石上(FineUI控件)
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
罗磊的独立博客
IT之家
IT之家
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Jina AI
Jina AI
腾讯CDC
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

博客园 - 梦想CAD控件

网页CAD如何在web端实现AutoCAD的绘圆弧功能 网页CAD控件中对象捕捉的运用和二次开发方法(网页端编辑DWG) 网页端CAD的图形选择、编辑与夹点操作教程(CAD in WEB) 云原生CAD后台处理DWG(MxServiceCode) 网页CAD图纸保存与数据持久化(BS架构CAD插件) 网页CAD中命令行驱动与参数化绘图的使用教程 Web CAD图形引擎实现DWG图纸网页批注和查看 开源网页实时协同设计平台-在线编辑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中绘制一个窗户模型
在线CAD视图控制与图层管理二开实战
梦想CAD控件 · 2026-06-03 · via 博客园 - 梦想CAD控件

摘要

在构建企业级 Web CAD 应用时,视图导航与图层管理是衡量系统专业度的两大核心指标。用户不仅需要流畅地浏览大幅面图纸,更需要像使用桌面端 AutoCAD 一样,对复杂的图层体系进行精细化管控。

本文基于 MxCAD 引擎,深入解析如何从零构建一个功能完备的图层特性管理器。文章涵盖从底层的数据库事务操作到上层的交互逻辑实现,完整复现包括图层状态切换、属性编辑、批量操作、搜索过滤在内的专业功能。

本文严格遵循技术文档规范,重点阐述实现原理与关键代码逻辑,为开发者提供一套可落地的最佳实践方案。

一、核心架构与数据模型

1.1 CAD 数据库中的图层结构

在 MxCAD(以及兼容 AutoCAD 内核)的数据库架构中,图层并非孤立存在,而是作为符号表(Symbol Table)的一部分进行管理。理解这一结构是进行二次开发的前提。

image-20260330162225298

核心对象

  • McDbLayerTable (图层表):这是数据库中所有图层定义的容器。它是一个字典结构,通过图层名称(String)映射到唯一的对象 ID(ObjectId)。每个数据库文件有且仅有一个图层表。

  • McDbLayerTableRecord (图层记录):这是图层的具体定义对象。它存储了图层的所有元数据,包括:

    • 基本属性:名称(name)、颜色(color)、线型(lineType)、线宽(lineWeight)。

    • 状态标志:可见性(isOff)、冻结状态(isFrozen)、锁定状态(isLocked)。

实体关联机制

实体通过 layerId 引用图层记录,实现属性的动态继承。

  • 随层颜色的实现

    • 实体的颜色索引值需设置为 ColorIndexType.kBylayer(随层)。

    • 当图层颜色发生变化时,实体颜色会自动继承图层的新颜色。

    • 若实体颜色索引值非随层(如设置为固定颜色),则不会跟随图层颜色变化。

代码示例:设置颜色随层

import { McCmColor, ColorIndexType } from "mxcad";
const color = new McCmColor();
color.colorIndex = ColorIndexType.kBylayer; // 设置颜色随层
console.log(color.colorIndex);

代码示例:设置实体固定颜色

import { McDbEntity, McCmColor } from 'mxcad';
const ent = new McDbEntity();
ent.trueColor = new McCmColor(255, 0, 0); // 设置固定颜色为红色
console.log(ent.trueColor);

1.2 视图管理与显示机制

在 MxCAD 中,视图控制的核心是 MxCAD 实例对象(通过 MxCpp.getCurrentMxCAD() 获取)。该对象维护着当前视区的状态,负责处理图形的显示范围、缩放比例、旋转角度等。

二、视图控制模块实现

视图交互逻辑通过调用 MxCAD 核心实例的方法或执行特定的命令字符串来实现,主要包括缩放、平移、旋转及显示样式控制。

2.1 显示全部 (Zoom All)

  • 功能:自动调整视图,使当前 DWG 文档中的所有图形内容完整显示在视口内。

  • 实现逻辑:计算图形的边界框(Bounding Box),然后调整视图的中心点和缩放比例,以适配整个边界框。

import { MxCpp } from "mxcad";
const mxcad = MxCpp.getCurrentMxCAD();
mxcad.zoomAll();
mxcad.updateDisplay();

image-20260330163825877

2.2 窗口缩放 (Zoom Window)

  • 功能:允许用户通过鼠标拖拽一个矩形窗口,放大该窗口内的区域。

  • 实现逻辑:捕获用户拖拽的矩形区域的起点和终点,将视图中心调整至窗口中心,并缩放至覆盖该窗口区域。

import { MxCpp, MxCADUiPrPoint, MxCoordConvert } from "mxcad";
async function Mx_WindowZoom() {
  let mxcad = MxCpp.getCurrentMxCAD();
  let getPoint = new MxCADUiPrPoint();
  getPoint.setMessage("点取缩放区域");
  let pt1 = await getPoint.go();
  if (!pt1) return;
  getPoint.setUserDraw((p1, worldDraw) => {
    worldDraw.drawRect(
      MxCoordConvert.cad2doc1((pt1 as any)), 
      MxCoordConvert.cad2doc1((p1 as any))
    );
  });
  let pt2 = await getPoint.go();
  if (pt2 == null) return;  
  mxcad.zoomW(pt1, pt2);
}
Mx_WindowZoom();

image-20260330164841731

2.3 视区旋转 (Zoom Angle)

  • 功能:围绕视图中心旋转图纸显示。

  • 实现逻辑:调用 zoomAngle() 方法,传入旋转角度参数(通常以 PI 为单位)。

    import { MxCpp } from "mxcad";
    const mxcad = MxCpp.getCurrentMxCAD();
    const lAng = Math.PI * 0.5; // 视区旋转90度
    mxcad.zoomAngle(lAng);

    image-20260330165313177

2.4 视区平移 (Pan)

  • 功能:在不改变缩放比例的情况下,移动视图的显示区域。

  • 实现逻辑:通过发送命令字符串实现。

import { MxFun } from "mxdraw";
MxFun.sendStringToExecute("Mx_Pan");

2.5 视区黑白显示

  • 功能:将彩色图形强制渲染为黑白灰度。

  • 实现逻辑:修改渲染管线的着色器参数或设置图形的显示样式表(StyleSheet)为黑白模式。

import { MxCpp } from "mxcad";
const mxcad = MxCpp.getCurrentMxCAD();
mxcad.setAttribute({ BlackWhiteDisplay: true });
//mxcad.openWebFile('https://demo2.mxdraw3d.com:3000/mxcad/test3.mxweb');//重新打开图纸渲染

image-20260330165745168

2.6 视区背景颜色设置

  • 功能:更改绘图区域的背景颜色。

  • 实现逻辑:直接设置 MxCAD 实例的背景颜色属性。

import { MxCpp } from "mxcad";
const mxcad = MxCpp.getCurrentMxCAD();
mxcad.setViewBackgroundColor(255, 255, 255); // 设置为白色
mxcad.updateDisplay();

image-20260330165912702

三、图层管理器实现

图层管理器(Layer Manager)是 CAD 编辑器中核心的辅助工具。基于 MXCAD 的 McDbLayerTable 接口,我们可以构建一个完整的图层管理器。

image-20260330171631708

3.1 管理器交互入口与状态定义

首先,在 UI 界面(如工具栏)添加一个“图层管理器”按钮。点击该按钮将触发一个异步函数,用于初始化并显示管理器弹框。

3.2 管理器弹框 UI 实现

图层管理器通常以模态弹框形式展示,包含列表区域、操作面板和属性面板。

代码实现 (Vue3 + TypeScript)

<!-- 交互入口按钮 -->
<button class="layer-btn" @click="showLayerManager">图层管理器</button>

<!-- 图层管理弹框 (Modal) -->
<div v-if="isModalVisible" class="modal-overlay" @click.self="closeModal">
  <div class="modal-content">
    <div class="modal-header">
      <span class="modal-title">图层列表</span>
      <button class="close-btn" @click="closeModal">×</button>
    </div>    
    <!-- 图层数据表格 -->
    <table class="layer-table">
      <thead>
        <tr>
          <th>可见</th>
          <th>颜色</th>
          <th>名称</th>
          <th>锁定</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="layer in layerList" :key="layer.recordId" class="layer-row">
          <!-- 可见性控制 -->
          <td @click.stop="toggleVisibility(layer)">
            <span class="icon">{{ layer.isOff ? '👁️‍🗨️' : '👁️' }}</span>
          </td>
          <!-- 颜色块 -->
          <td>
            <div class="color-block" :style="{ backgroundColor: layer.colorRgb }"></div>
          </td>
          <!-- 图层名称 -->
          <td>{{ layer.name }}</td>
          <!-- 锁定控制 -->
          <td @click.stop="toggleLock(layer)">
            <span class="icon">{{ layer.isLocked ? '🔒' : '🔓' }}</span>
          </td>
        </tr>
      </tbody>
    </table>
    
    <div class="modal-footer">
      <button @click="submitLayerChanges">应用</button>
    </div>
  </div>
</div>

样式代码 (CSS)

<style scoped>
/* --- 样式还原图一 (深色主题) --- */
.app-container { 
  font-family: "Microsoft YaHei", sans-serif; 
  padding: 20px; 
}
.layer-btn { 
  padding: 8px 16px; 
  background: #007bff; 
  color: white; 
  border: none; 
  border-radius: 4px; 
  cursor: pointer; 
}
.layer-btn:hover { background: #0056b3; }
​
/* 模态框遮罩 */
.modal-overlay { 
  position: fixed; 
  top: 0; left: 0; right: 0; bottom: 0; 
  background: rgba(0, 0, 0, 0.7); 
  display: flex; 
  justify-content: center; 
  align-items: center; 
  z-index: 1000; 
}
​
/* 弹框内容 */
.modal-content { 
  background: #25282c; 
  width: 500px; 
  max-height: 70vh; 
  border-radius: 8px; 
  display: flex; 
  flex-direction: column; 
}
.modal-header { 
  display: flex; 
  justify-content: space-between; 
  align-items: center; 
  padding: 12px 16px; 
  border-bottom: 1px solid #383838; 
}
.modal-title { 
  color: #e0e0e0; 
  font-size: 16px; 
  font-weight: bold; 
}
.close-btn { 
  background: none; 
  border: none; 
  color: #e0e0e0; 
  font-size: 18px; 
  cursor: pointer; 
}
.close-btn:hover { color: #ff5555; }
​
/* 表格容器 */
.layer-list-container { flex: 1; overflow-y: auto; }
.layer-table { 
  width: 100%; 
  border-collapse: collapse; 
}
.layer-table th, .layer-table td { 
  padding: 8px 12px; 
  text-align: left; 
  border-bottom: 1px solid #383838; 
  color: #e0e0e0; 
}
​
/* 列宽控制 */
.col-visible { width: 60px; text-align: center; }
.col-color { width: 60px; text-align: center; }
.col-name { flex: 1; }
.col-status { width: 60px; text-align: center; }
​
/* 颜色块样式 */
.color-block { 
  width: 20px; 
  height: 20px; 
  margin: 0 auto; 
  border: 1px solid #444; 
}
​
/* 图标 */
.icon { font-size: 14px; }
​
/* 行样式 */
.layer-row { 
  cursor: pointer; 
  transition: background 0.2s; 
}
.layer-row:hover { background-color: #383838; }
​
/* 选中状态 (高亮) */
.layer-row-active { background-color: #3c4043; }
​
/* 表尾 */
.modal-footer { 
  padding: 12px 16px; 
  border-top: 1px solid #383838; 
  display: flex; 
  justify-content: flex-end; 
  gap: 10px; 
}
button { 
  padding: 6px 12px; 
  background: #3c4043; 
  color: #e0e0e0; 
  border: 1px solid #555; 
  border-radius: 4px; 
  cursor: pointer; 
}
button:hover { background: #555; }
</style>

3.3 图层数据遍历与加载

要显示所有图层,我们需要通过 MXCAD 实例获取数据库中的图层表(McDbLayerTable),并利用 getAllRecordId() 遍历所有图层记录。

实现逻辑:

  1. 获取核心实例与图层表对象。

  2. 调用 getAllRecordId() 获取所有图层 ID 数组。

  3. 遍历 ID 数组,通过 getMcDbLayerTableRecord() 获取具体的图层记录对象。

  4. 将图层属性映射到弹框的列表组件中。

代码示例:

const showLayerManager = async () => {
  // 1. 获取数据库与图层表
  const database = MxCpp.getCurrentMxCAD().getDatabase();
  const layerTable = database.getLayerTable();  
  // 2. 遍历所有图层 ID
  const allLayerIds = layerTable.getAllRecordId();
  const layers = [];  
  for (const id of allLayerIds) {
    const layerRecord = id.getMcDbLayerTableRecord();    
    // 3. 提取属性并转换格式 (如颜色转 HEX)
    layers.push({
      name: layerRecord.name,
      colorRgb: layerRecord.color.getStyle(), // 关键转换
      isLocked: layerRecord.isLocked,
      isOff: layerRecord.isOff,
      recordId: id, // 保留 ID 用于后续修改
      isChanged: false
    });
  }
  // 4. 绑定数据并显示弹框
  layerList.value = layers;
  isModalVisible.value = true;
};

3.4 图层核心操作与状态同步

这是管理器的核心逻辑。用户在 UI 上的操作会修改内存中的数据标记,点击“确定”后,系统遍历被标记修改的图层,通过 MXCAD API 将新状态写回图层记录,并强制刷新显示。

代码示例:

// 切换可见性逻辑
const toggleVisibility = (layer) => {
  layer.isOff = !layer.isOff;
  layer.isChanged = true; // 标记为脏数据
};
​
// 切换锁定逻辑
const toggleLock = (layer) => {
  layer.isLocked = !layer.isLocked;
  layer.isChanged = true; // 标记为脏数据
};
​
// 提交修改到 MXCAD 引擎
const submitLayerChanges = () => {
  layerList.value
    .filter(layer => layer.isChanged) // 筛选有修改的图层
    .forEach(layer => {
      const record = layer.recordId.getMcDbLayerTableRecord();
      record.isOff = layer.isOff;     // 写入可见性
      record.isLocked = layer.isLocked; // 写入锁定状态
    });
  
  // 关键:通知引擎更新显示状态
  const mxcad = MxCpp.getCurrentMxCAD();
  mxcad.updateLayerDisplayStatus(); // 更新图层状态
  mxcad.updateDisplay();            // 重绘视图
  isModalVisible.value = false;
};

四、图层扩展功能实现

为了实现完整的图层管理器功能,我们需要增加图层深度操作和搜索筛选逻辑。整体实现效果如下图所示:

image-20260331092752637

4.1 图层深度操作实现

A. 新增图层 (New Layer)

  • 功能:在图层表中创建一个新的图层记录。

  • 实现逻辑:调用 addLayer(name) 方法。

import { McCmColor, MxCpp, McDbLayerTableRecord, McDb } from "mxcad"
// 得到当前控件
const mxcad = MxCpp.getCurrentMxCAD();
// 实例化一个图层数据对象
const layer = new McDbLayerTableRecord();
layer.color = new McCmColor(0, 0, 0);
layer.isFrozen = true;
layer.isLocked = true;
layer.isOff = true;
layer.lineWeight = McDb.LineWeight.kLnWt018;
layer.name = "新图层";
// 拿到当前控件的数据库图层表并添加
const layerTable = mxcad.getDatabase().getLayerTable();
const objId = layerTable.add(layer);
// 更新显示
mxcad.updateLayerDisplayStatus();

B. 删除图层 (Delete Layer)

  • 功能:删除选中的图层。

  • 实现逻辑:获取选中行的图层 ID,调用 erase() 方法。注意:不能删除当前图层或包含实体的图层。

import { MxCpp } from "mxcad"
let layerTable = MxCpp.getCurrentMxCAD().getDatabase().getLayerTable();
let layerId = layerTable.get("图层名字");
let layerRec = layerId.getMcDbLayerTableRecord();
layerRec.erase(); // 删除图层
// 更新显示
mxcad.updateDisplay();

C. 置为当前 (Set Current)

  • 功能:将选中的图层设置为绘图的当前图层。

  • 实现逻辑:获取选中图层的名称,调用 setCurrentlyLayerId()

import { MxCpp } from "mxcad"
const mxcad = MxCpp.getCurrentMxCAD();
let layerTable = mxcad.getDatabase().getLayerTable();
let layerId = layerTable.get("图层名字");
mxcad.getDatabase().setCurrentlyLayerId(layerId);

D. 关闭所有图层 (Turn Off All)

  • 功能:批量操作,将除“0”层以外的所有图层设置为不可见。

  • 实现逻辑:遍历 layerList,对每个图层调用 layer.isOff = true

import { MxCpp } from "mxcad"
let layerTable = MxCpp.getCurrentMxCAD().getDatabase().getLayerTable();
let aryId = layerTable.getAllRecordId();
aryId.forEach((id) => {
  let layerRec = id.getMcDbLayerTableRecord();
  // 过滤掉 0 层或其他逻辑
  if (layerRec.name !== "0") {
    layerRec.isOff = true;
  }
});

4.2 搜索与筛选功能

  • 实现逻辑:监听搜索框的 input 事件,根据输入值过滤 layerList 数据源。

// 搜索框绑定的变量
const searchKeyword = ref('');
// 计算属性:根据搜索关键字过滤图层列表
const filteredLayers = computed(() => {
  if (!searchKeyword.value) return layerList;
  const keyword = searchKeyword.value.toLowerCase();
  return layerList.filter(layer => 
    layer.name.toLowerCase().includes(keyword) 
  );
});

五、总结

本文详细阐述了基于 MxCAD 实现专业级视图控制与图层管理系统的技术路径。通过深入利用 McDbLayerTable 数据结构与事务机制,我们成功实现了包括状态切换、属性编辑、批量操作在内的全套功能。

核心价值点回顾:

  1. 数据驱动:严格遵循 CAD 数据库的引用机制,确保数据一致性。

  2. 事务安全:所有写操作均在事务保护下进行,保障系统稳定性。

  3. 交互体验:通过坐标转换与事件映射,提供了接近原生桌面的流畅操作感。

  4. 扩展能力:模块化设计支持轻松扩展图层过滤器、状态保存等高级特性。

该方案不仅满足了基本的图纸查看需求,更为后续的深度二次开发(如自定义绘图命令、业务数据绑定)奠定了坚实的交互与数据基础。开发者可依据此框架,进一步定制符合特定行业规范的图层管理工具。