本帖最后由 MxDraw 于 2024-3-4 16:22 编辑
前言在线CAD的二次开发中对于交互绘制的使用频率非常高,MxCAD的思路是通过调取命令功能和取点对象来实现动态绘制,下面文章我们会详细讲解一下这三个步骤,如果对WEB CAD的二次开发还不熟悉可以参考入门教程。
一、什么是命令功能mxdraw.js库提供了一种可以通过输入一些特定的命令调用绘制方法,并在动态绘制过程中实现参数化绘图的功能,即为命令功能。例如想用命令功能绘制一个圆,可在命令行内调用绘圆方法,并根据用户输入圆的半径参数来确定圆的大小,下面是实现步骤。
1、监听输入- <input id="mxCmdText"/>
- let event = document.getElementById('mxCmdText')
- // 设置命令行消息数据 (在监听input输入框的onKeydown事件的回调函数中调用)
- event.onkeydown = function (e) {
- Mx.MxFun.setCommandLineInputData(event.value, e.keyCode)
- }
复制代码
2、编写绘制函数在使用命令功能时,编写绘制函数的过程中可以通过取点对象调用setMessage方法给用户提示必要的操作信息,以及获取到使用者的输入信息或关键词,下面以绘制线段函数为例: - // 线段函数async function BR_Line() {
- const getPoint = new Mx.MrxDbgUiPrPoint();
- // 交互提示
- getPoint.setMessage("\n指定直线起点:");
- getPoint.go(async (status:number)=>{
- if(status != Mx.MrxDbgUiPrBaseReturn.kOk) return
- let pt1 = getPoint.value();
- let line = new Mx.MxDbLine();
- line.pt1 = pt1;
- getPoint.setMessage("\n指定直线终点:");
- getPoint.setUserDraw((pt:any,pw:any)=>{
- line.pt2 = pt;
- pw.drawCustomEntity(line)
- });
- line.pt2 = await getPoint.go(); Mx.MxFun.getCurrentDraw().addMxEntity(line);})}
复制代码
3、注册命令- // 注册命令名 BR_Line:命令名
- Mx.MxFun.addCommand("BR_Line", ()=> {
- // 是否正在运行某个命令
- if(Mx.MxFun.isRunningCommand()) {
- return
- }
- // 目标绘制函数
- BR_Line()})
复制代码
4、执行命令、输出消息- // 手动执行命令
- Mx.MxFun.sendStringToExecute("目标命令");
- // 监听正在绘制中的命令提示
- Mx.MxFun.listenForCommandLineInput(({ msCmdTip, msCmdDisplay, msCmdText }) => {
- console.log(msCmdTip, msCmdDisplay, msCmdText)})
复制代码命令功能效果完整示例代码如下: - <!DOCTYPE html><html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>MxDbLine 示例</title>
- <script src="https://unpkg.com/mxdraw/dist/mxdraw.umd.js"></script></head>
- <body>
- <div style="height: 80vh; overflow: hidden;">
- <canvas id="mxdraw"></canvas>
- </div>
- <div>
- <textarea id="mxCmdArea" rows="5" style="width:100%;overflow: scroll;"
- placeholder="命令:" readonly></textarea>
- <input type="text" id="mxCmdText" />
- </div></body><script type="module">
- Mx.loadCoreCode().then(async () => {
- // 创建控件对象
- Mx.MxFun.createMxObject({
- canvasId: "mxdraw", // canvas元素的id
- });
- })
- let event = document.getElementById('mxCmdText')
- // 设置命令行消息数据 (在监听input输入框的onKeydown事件的回调函数中调用)
- event.onkeydown = function (e) {
- Mx.MxFun.setCommandLineInputData(event.value, e.keyCode)
- }
- // 直线函数
- async function BR_Line() {
- const getPoint = new Mx.MrxDbgUiPrPoint();
- // 交互提示
- getPoint.setMessage("\n指定直线起点:");
- let pt1 = await getPoint.go();
- if (!pt1) return
- let line = new Mx.MxDbLine();
- line.pt1 = pt1;
- getPoint.setMessage("\n指定直线终点:");
- getPoint.setUserDraw((pt, pw) => {
- line.pt2 = pt;
- pw.drawCustomEntity(line)
- });
- const pt2 = await getPoint.go()
- if (!pt2) return
- line.pt2 = pt2;
- Mx.MxFun.getCurrentDraw().addMxEntity(line);
- }
- // 注册命名
- Mx.MxFun.addCommand("BR_Line", () => {
- // 是否正在运行某个命令
- if (Mx.MxFun.isRunningCommand()) {
- return
- }
- BR_Line()
- })
- // 监听正在绘制中的命令提示
- Mx.MxFun.listenForCommandLineInput(({ msCmdTip, msCmdDisplay, msCmdText }) => {
- console.log(msCmdTip, msCmdDisplay, msCmdText)
- document.getElementById('mxCmdArea').innerHTML = msCmdTip
- document.getElementById("mxCmdArea").scrollTop = document.getElementById("mxCmdArea").scrollHeight;
- })
- </script>
- </html>
复制代码
二、取点对象
在画布中绘制基本图形前,先要学会点对象的绘制(复杂图形都由点、线、面组成),mxdraw.js中提供了API ,MrxDbgUiPrPoint用于构建一个取点对象并提供一系列方法属性辅助用户绘图,点击MrxDbgUiPrPoint API 查看详细属性和方法说明。
1、基础取点调用MrxDbgUiPrPoint中的方法go()记录鼠标开始拖动的点位置,用户可利用该方法记录画布中的目标点位,执行go()方法,若取点成功则返回点的位置,默认点值为THREE.Vector3();若取点失败则返回null,示例代码如下: - Mx.loadCoreCode().then(async () => {
- // 创建控件对象
- Mx.MxFun.createMxObject({
- canvasId: "mxdraw", // canvas元素的id
- callback: (mxDrawObject, dom ) => {
- //图纸展示控件创建完成后的回调函数 回调参数mxDraw和dom
- console.log(mxDrawObject, dom)
- },
- });
- const getPoint = new Mx.MxFun.MrxDbgUiPrPoint()
- const pt = await getPoint.go()
- if(!pt) return
- console.log('目标点位' , pt)})
复制代码此外,若用户需要连续取点,则可以结合while函数调用go()方法,代码如下: - const getPoint = new Mx.MxFun.MrxDbgUiPrPoint()while(true){
- const pt = await getPoint.go()
- if(!pt) break}
复制代码
2、辅助命令功能结合命令功能和mxdraw.js中取点对象提供的一系列方法对绘图操作时所进行的操作,提供相应提示和操作选项,以下面两种常用方法为例。 2.1设置提示字符串:setMessage()方法对绘图操作时所进行的操作进行提示,代码如下: - const getPoint = new Mx.MxFun.MrxDbgUiPrPoint()
- getPoint.setMessage('设置提示字符串')
- const pt = await getPoint.go()
复制代码2.2关键字:setKeyWords()方法可为当前命令设置关键字选项,keyWordPicked()方法可返回用户选择的关键字,代码如下: - const getPoint = new Mx.MxFun.MrxDbgUiPrPoint()
- // 设置关键字列表
- getPoint.setKeyWords('[闭合(C)/ 放弃(U)]')
- // 获取用户选择关键字
- getPoint.isKeyWordPicked('关键字')
复制代码
3.取点对象动态绘制取点对象中还提供了setUserDraw()方法设置交互过程的动态绘制调用对象,在该过程中所绘制的图像都是临时绘制,不会保存在画布中。该方法提供了两个回调参数:currentPoint、pWorldDraw。 currentPoint为当前光标所在点的点位,pWorldDraw为一个动态绘制回调对象,可根据用户设置动态绘制目标图形,点击动态绘制回调对象查看详细属性和方法说明,示例代码如下: - async function draw_line(){
- const line = new Mx.MxDbLine()
- const getPoint = new Mx.MxFun.MrxDbgUiPrPoint()
- const pt1 = await getPoint.go()
- if(!pt1) return
- line.pt1 = pt1
- // 动态绘制
- getPoint.setUserDraw((currentPoint, pWorldDraw)=>{
- line.pt2 = currentPoint
- pWorldDraw.drawCustomEntity(line)
- })
- const pt2 = await getPoint.go()
- if(!pt2) return
- line.pt2 = pt2
- // 获取控件对象并将线段对象line添加到画布中
- Mx.MxFun.getCurrentDraw().addMxEntity(line);}
复制代码
三、动态绘制
1.基础绘制
mxdraw.js提供了两种实现动态绘制的方式,它们可以在不改变图形类的情况下,改变图形的大小、方向等,帮助用户更快捷地绘制目标图形。这两种动态绘制的方式都是结合取点对象来实现动态绘制图形的功能。
方式一利用API McEdGetPointWorldDrawObject构建一个动态绘制回调对象,再通过取点对象中的setUserDraw()方法调用该对象。 - // 实例化取点对象
- const getPoint = new Mx.MrxDbgUiPrPoint();
- // 实例化线段对象line
- let line = new Mx.MxDbLine()
- const pt1 = await getPoint.go()
- line.setPoint1(pt1)
- // 实例化动态绘制对象
- const worldDrawComment = new Mx.McEdGetPointWorldDrawObject();
- // 设置动态绘制回调函数
- worldDrawComment.setDraw((currentPoint) => {
- line.setPoint2(currentPoint);
- worldDrawComment.drawCustomEntity(line)
- });
- // 使用动态绘制对象
- getPoint.setUserDraw(worldDrawComment)
复制代码
方式二 直接运用取点对象提供的setUserDraw()方法设置交互过程的动态绘制调用对象。详细描述可参考取点对象动态绘制,示例代码如下: - const getPoint = new Mx.MrxDbgUiPrPoint()
- // 实例化线段对象line
- let line = new Mx.MxDbLine();
- const pt1 = await getPoint.go()
- if(!pt1) return
- line.pt1 = pt1
- // 实例化动态绘制对象
- getPoint.setUserDraw((currentPoint, worldDrawComment)=>{
- line.pt2 = currentPoint
- worldDrawComment.drawCustomEntity(line)
- });
- const pt2 = await getPoint.go()
- if(!pt2) return
- line.pt2 = pt2;
复制代码在动态绘制中的绘制的图形都是临时的,意味着这些图形最终是不会保持在画布上的,如果需要将动态绘制的图形保存在画布上请调用取点对象的 drawReserve方法。
2.图形对象的动态绘制- // 实例化取点对象
- const getPoint = new Mx.MrxDbgUiPrPoint();
- // 实例化动态绘制对象
- const worldDrawComment = new Mx.McEdGetPointWorldDrawObject();
- const pt1 = await getPoint.go()
- if(!pt1) return
- // 设置动态绘制回调函数
- worldDrawComment.setDraw((currentPoint) => {
- // 绘制线段对象
- worldDrawComment.drawLine(pt1, currentPoint);
- // 在绘制过程中还可以一起绘制其他图形 绘制过程结束时,不会保留这些图形,如:
- // 绘制以下图形使用红色
- worldDrawComment.setColor('#ff0000')
- // 绘制半径为6的圆
- worldDrawComment.drawCircle(currentPoint, 6)
- // 绘制字体大小为36的 “文字” 角度为0
- worldDrawComment.drawText("文字" ,36 , 0, currentPoint)
- // 绘制矩形 pt1, currentPoint为矩形两对角
- worldDrawComment.drawRect(pt1, currentPoint)
- });
- // 使用动态绘制对象
- getPoint.setUserDraw(worldDrawComment)
复制代码
|