本帖最后由 MxDraw 于 2025-4-28 16:07 编辑
前言
在原本的富文本编辑器功能上,我们将文本与CAD功能相结合实现了多行文本的扩展,用户可以根据自己项目的需求将实体以文本内容的形式插入到我们的多行文本内,接下来我们将详细讲述如何在MxCAD项目的多行文本编辑功能中插入自定义文本实体,富文本编辑功能示例:
注册同心圆实体文本下面我们将以在多行文本编辑器中插入一个同心圆实体文本作为示例,介绍基础的扩展步骤。
1. 实现自定义文本类 MxCADMText类中注册的所有自定义文本实体都需要继承MxCADBaseCustomText这个自定义文本基类,否则多行文本实体内部将无法识别你的自定义文本。  - /**
- * 同心圆自定义文本类
- * 用于在MxCAD多行文本中插入同心圆
- */
- class MxCADConcentricCircles extends MxCADBaseCustomText {
- // 自定义文本的类型唯一标识
- type = "MxCADConcentricCircles";
- /**
- * 计算同心圆的尺寸
- * @param entity MxCAD多行文本实体
- * @param textNode 文本节点
- * @returns 计算数据,包含宽度和高度
- */
- calculate(entity: MxCADMText, textNode: MarksStyleText): MxCADCustomTextCalculateData {
- // 获取外圆半径
- const outerRadius = this.getOuterRadius(entity, textNode);
- // 计算同心圆占用的空间大小
- const width = outerRadius * 2;
- const height = outerRadius * 2;
- return {
- width,
- height
- };
- }
- /**
- * 创建同心圆实体
- * @param entity MxCAD多行文本实体
- * @param textNode 文本节点
- * @param calculateData 计算数据
- * @param renderData 渲染数据
- * @returns 创建的实体数组
- */
- create(
- entity: MxCADMText,
- textNode: MarksStyleText,
- calculateData: MxCADCustomTextCalculateData,
- renderData: CreateData
- ): (McDbEntity | McDbCustomEntity)[] {
- // 获取外圆半径
- const outerRadius = this.getOuterRadius(entity, textNode);
- // 计算中圆半径
- const middleRadius = outerRadius * 0.7;
- // 计算内圆半径
- const innerRadius = outerRadius * 0.4;
- // 创建同心圆实体
- const circles: McDbEntity[] = [];
- // 计算圆心位置
- // renderData.position是左上角的位置
- const leftTopPosition = renderData.position.clone();
- // 将圆心位置从左上角偏移一个半径的距离,使同心圆左上角与renderData.position对齐
- // 圆心坐标 = 左上角坐标 + 圆半径
- const centerX = leftTopPosition.x + outerRadius;
- const centerY = leftTopPosition.y - outerRadius;
- // 创建最终圆心坐标
- const centerPosition = new McGePoint3d(centerX, centerY, leftTopPosition.z);
- // 创建外圆
- const outerCircle = new McDbCircle();
- outerCircle.radius = outerRadius;
- outerCircle.center = centerPosition;
- circles.push(outerCircle);
- // 创建中圆
- const middleCircle = new McDbCircle();
- middleCircle.radius = middleRadius;
- middleCircle.center = centerPosition;
- circles.push(middleCircle);
- // 创建内圆
- const innerCircle = new McDbCircle();
- innerCircle.radius = innerRadius;
- innerCircle.center = centerPosition;
- circles.push(innerCircle);
- return circles;
- }
- /**
- * 获取外圆半径
- * @param entity MxCAD多行文本实体
- * @param textNode 文本节点
- * @returns 外圆半径
- */
- private getOuterRadius(entity: MxCADMText, textNode: MarksStyleText): number {
- // 根据文本字体大小动态计算圆的半径
- const fontSize = textNode?.fontSize || 1;
- // 调整半径计算,使圆的大小合适
- return fontSize * entity.textBaseHeight / 2.5;
- }
- constructor() {
- super();
- }
- }
注意: `create()`方法用于创建实际的图形实体。 `calculate()`方法用于计算自定义文本在多行文本中占用的空间。 `type`属性用于定义自定义文本的类型标识,该type将在MxCADMText类中作为唯一标识。
2. 注册自定义文本 在MxCAD项目内的MxPluginContext上下文对象中我们已经暴露出了`registerEditorCustomTextPlugin()`注册方法,将上述已经写好的类放入该方法中就可以在自定义文本中插入同心圆实体了。 - /**
- * 注册同心圆自定义文本插件
- */
- const insertConcentricCircles = MxPluginContext.registerEditorCustomTextPlugin(
- new MxCADConcentricCircles(),
- {
- // 双击图形时的回调函数
- onDbClick: (node) => {
- console.log("双击了同心圆:", node);
- },
- // UI数据
- uiData: {
- // 图标
- icon: "yuan",
- // 文本
- text: "同心圆",
- // 提示文本
- tip: "插入同心圆",
- // 点击事件
- onClick: () => {
- // 插入同心圆
- insertConcentricCircles({
- // 这里可以传入自定义参数
- });
- }
- }
- }
- );
复制代码`insertConcentricCircles(props: any, isUpdate?: boolean)`方法中的 props 为外部传入的参数对象,可以用于设置实体的参数绘制,设置后通过 `MxCADConcentricCircles ` 类内部 `calculate()`或`create()`方法内的 `textNode.props`中获取;isUpdate 参数是用于已经插入了实体对象并处于文本编辑状态时,单击或双击实体进行修改操作后通知多行文本修改节点内容。 - // 插入同心圆并传入自定义参数
- insertConcentricCircles({
- // 例如,可以传入不同的半径比例
- radiusRatio: {
- outer: 1,
- middle: 0.7,
- inner: 0.4
- }
- });
- /**
- *更新
- onDbClick: (node) => {
- // ... 处理node数据,更新params
- insertConcentricCircles(params, true);
- }
- */
复制代码- // 在create方法中使用这些参数:
- create(entity, textNode, calculateData, renderData) {
- // 获取自定义参数
- const radiusRatio = renderData.props?.radiusRatio || {
- outer: 1,
- middle: 0.7,
- inner: 0.4
- };
- const outerRadius = this.getOuterRadius(entity, textNode);
- const middleRadius = outerRadius * radiusRatio.middle;
- const innerRadius = outerRadius * radiusRatio.inner;
- // 其他代码...
- }
复制代码
onDbClick:双击文本时的回调函数,该回调函数内有一个node回调参数,该参数内部包含了文本节点的数据,即`MxCADConcentricCircles ` 类内部的`textNode`。利用该函数可实现交互式自定义文本,例如在双击时显示一个对话框来修改参数。 - MxPluginContext.registerEditorCustomTextPlugin(
- new MxCADConcentricCircles(),
- {
- onDbClick: (node) => {
- // 显示一个对话框来修改参数
- showDialog(node, (newParams) => {
- // 更新自定义文本
- updateCustomText(node, newParams);
- });
- },
- // 其他配置...
- }
- );
复制代码uiData:设置插入实体在编辑器中的ui配置,其中icon值可以设置为iconfont字体图标。
3. 在项目初始时执行注册事件 - function rxInitCircle() {
- /**
- ...params
- 设置初始参数
- */
- insertConcentricCircles(params)
- }
复制代码- // MxCAD创建成功,相当于mxcad init\_mxcad事件.
- MxFun.on("mxcadApplicationCreatedMxCADObject", (param) => {
- rxInitCircle()
- }
复制代码
4. 运行效果演示:
扩展实践(注册粗糙度实体文本)1. 构造粗糙度自定义实体文本注册类  - // 绘制最初始的文本实体
- const getEntity = (entity: MxCADMText, textNode: MarksStyleText) => {
- const roughness = new McDbTestRoughness();
- roughness.setPos(new McGePoint3d(0, 0, 0));
- roughness.rouDimHeight = (textNode?.fontSize ? textNode.fontSize : 1) * entity.textBaseHeight;
- const form = textNode.props;
- roughness.rougMarkType = form.selectSymbolNum;
- roughness.textLeftStr = form.textLeftStr;
- roughness.rougCornerType = form.rougCornerType === "无" ? "" : form.rougCornerType;
- roughness.isRoungSameRequire = form.isRoungSameRequire;
- roughness.isShowMostSymbols = form.isShowMostSymbols;
- const dataArr = form.textUpStr.filter((item) => item != "");
- roughness.textUpStr = JSON.parse(JSON.stringify(dataArr)).reverse();
- roughness.textDownStr = form.textDownStr.filter((item) => item != "");
- roughness.isAddRougLongLine = form.isAddLongLine;
- return roughness
- }
- // 构建文本注册类
- class MxCADTestRoughnessText extends MxCADBaseCustomText {
- // type为后续多行文本插入的唯一标识
- type = "MxCADTestRoughnessText"
- calculate(entity: MxCADMText, textNode: MarksStyleText): MxCADCustomTextCalculateData {
- const roughness = getEntity(entity, textNode);
- const box = roughness.getBoundingBox();
- const width = box.maxPt.x - box.minPt.x
- const height = box.maxPt.y - box.minPt.y;
- return {
- width,
- height
- }
- }
- create(entity: MxCADMText, textNode: MarksStyleText, calculateData: MxCADCustomTextCalculateData, renderData: CreateData): (McDbEntity | McDbCustomEntity)[] {
- const roughness = getEntity(entity, textNode);
- const pos = roughness.getPos();
- //设置粗糙度在文本中的位置
- const { minPt, maxPt } = roughness.getBoundingBox();
- const basePt = new McGePoint3d(minPt.x, maxPt.y);
- const v = pos.sub(basePt)
- const pt = renderData.position.clone().addvec(v)
- roughness.setPos(pt);
- if (entity.getMTextImp().entityType == 'mtext' && !entity.getMTextImp().isEditState) {
- return [roughness]
- } else {
- const entityArr = roughness.getAllEntity();
- return [...entityArr]
- }
- }
- constructor() {
- super()
- }
- }
2. 注册粗糙度文本 - // 注册粗糙度文本
- function rxInitRoughnessText() {
- // 使用插件上下文中的函数
- const insertCustomText = MxPluginContext.registerEditorCustomTextPlugin(
- new MxCADTestRoughnessText(),
- {
- // 双击文本时的回调函数
- onDbClick: (node) => {
- showRoughnessDialog(true, node as MarksStyleText)
- },
- uiData: {
- icon: 'icon-a-1',
- tip: '粗糙度',
- onClick: () => {
- // 插入自定义公式
- showRoughnessDialog(false)
- }
- }
- }
- )
- const showRoughnessDialog = (isUpdate: boolean = false, textNode?: MarksStyleText) => {
- if (isUpdate) {
- const roughness = new McDbTestRoughness();
- const form = textNode.props;
- roughness.rougMarkType = form.selectSymbolNum;
- roughness.textLeftStr = form.textLeftStr;
- roughness.rougCornerType = form.rougCornerType === "无" ? "" : form.rougCornerType;
- roughness.isRoungSameRequire = form.isRoungSameRequire;
- roughness.isShowMostSymbols = form.isShowMostSymbols;
- roughnessHandle.value = roughness;
- const dataArr = form.textUpStr.filter((item) => item != "");
- roughness.textUpStr = JSON.parse(JSON.stringify(dataArr)).reverse();
- roughness.textDownStr = form.textDownStr.filter((item) => item != "");
- roughness.isAddRougLongLine = form.isAddLongLine;
- }
- dialog.showDialog(true, { title: t("表面粗糙度") }).then(async ({ data, isCanceled }) => {
- // 需要等待cancel或者confirm调用才会触发
- if (!isCanceled) {
- insertCustomText(data.roughnessData, isUpdate)
- }
- });
- }
- }
复制代码
3. 初始化粗糙度自定义文本 - // MxCAD创建成功,相当于mxcad init\_mxcad事件.
- MxFun.on("mxcadApplicationCreatedMxCADObject", (param) => {
- rxInitRoughnessText()
- }
复制代码
4. 实践效果演示 初始插入,如下图: 双击修改,如下图: 修改后最终以多行文本形式绘制在图纸中,如下图:
|