翼度科技»论坛 编程开发 JavaScript 查看内容

500行JavaScript代码在前端根据数据生成CAD工程剖面图

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
前言

用数据生成CAD图,一般采用的ObjectArx对CAD二次开发完成。ObjectARX是AutoDesk公司针对AutoCAD平台上的二次开发而推出的一个开发软件包,它提供了以C++为基础的面向对象的开发环境及应用程序接口,能访问和创建AutoCAD图形数据库。而由于现在懂C++的人少,很多人对C++有点望而生畏。则JavaScript 是互联网上最流行的脚本语言,用户群体很大。那有没有可能利用JavaScript来进行数据成图?
今天和大家聊聊,怎么用500行JavaScript代码,根据数据在前端创建一个Dwg格式的工程剖面图。
效果

先上效果图


它支持哪些功能?


  • 支持CAD的27种实体类型的创建,如线、文字、填充等
  • 支持对DWG图中实体进行修改、克隆、删除等操作
  • 支持创建CAD图层、线型、块定义、文字样式
  • 支持从外部图形中拷贝实体到当前创建的CAD图中
  • 支持块属性文字的创建和设置
  • 对创建好的CAD图形数据能以GeoJson的格式在前端直接展示,同时能选中移动等操作
  • 对创建好的CAD图形能在前端展示,同时能点击弹出实体类型等属性
  • 能导出成DWG图形
实现原理


(1) 对剖面图中不变的元素如图例做成模板。创建图时直接拷贝这些实体即可。对于图签可以外部图形插入,同时图签中需要修改的文字内容如制图人或日期等字段,可以块属性文字的方式在创建时以属性赋值的方式来进行创建。如上面生成的剖面图的模板来源于下面这两个模板图形。 剖面图模板:

图签模板:(其中单位和日期是块属性文字,支持插入的时候输入属性值进行修改)

(2) 获取要创建的绘图数据,示例中对数据进行了模拟生成。
(3) 根据唯杰地图https://vjmap.com/ SDK中提供创建CAD实体类型的方法创建相关实体。  唯杰地图SDK支持的实体类型有DbLine直线、DbCurve曲线、Db2dPolyline二维折线、Db3dPolyline三维多段线、DbPolyline多段线、BlockReference块参照、DbArc圆弧、DbCircle圆、DbEllipse椭圆、DbHatch填充、Text单行文本、DbMText多行文本、RasterImage栅格图片、DbShape型实体、Spline样条曲线、Wipeout遮罩实体、Dimension标注、Db2LineAngularDimension角度标注[两条线]、Db3PointAngularDimension角度标注[三点]、DbAlignedDimension对齐标注、DbArcDimension圆弧标注、DbDiametricDimension直径标注、DbOrdinateDimension坐标标注、DbRadialDimension半径标注、DbRadialDimensionLarge半径折线标注、DbRotatedDimension转角标注、AcDbAttributeDefinition属性注记、AcDbAttribute块属性、DbLayer图层、DbTextStyle文字样式、DbDimStyle标注样式、DbLinetypeStyle线型样式、DbBlock块定义、DbDocument数据库文档。
如何减少代码量可以用如下方法:

  • 技巧一:可以直接拷贝模板中的实体,对实体的属性进行修改。这样能少赋值参数,减少代码量。
  • 技巧二:对于重复的对象,可以创建块,变化的文字,以块属性文字定义。再重复创建块参照,修改属性文字。
(4) 把创建的数据生成一个JSON对象,调用唯杰地图服务,后台创建DWG图形。
(5) 把后台创建的DWG图形数据以GeoJson数据或GIS瓦片的格式返回给前端进行展示。对于图不大的情况,可用GeoJson数据进行展示。如果图大时,GeoJson数据量大,数据返回慢,渲染也会受影响,这时建议用GIS栅格瓦片或矢量瓦片的时候进行绘制。
在线体验地址

https://vjmap.com/demo/#/demo/map/comprehensive/03datatodwgmap
应用场景

能在前端通过JavaScript创建CAD格式的DWG图形,极大的降低了数据生成CAD图的门槛,具有很广泛的应用场景。例如,在建筑和工程领域,DWG文件是广泛使用的标准文件格式,如工程中常用的一些等值线图、剖面图、水位图等;建筑、交通等不同行业中的相关图纸都可以用这个来生成DWG图形。偷个懒,让目前很火的ChatGPT来总结下吧:

全部实现代码
  1. // --数据自动生成CAD工程剖面图--根据数据在前端创建生成CAD格式的工程剖面图形
  2. // 剖面图模板来源地图id和版本
  3. let templateSectId = "template_sect";
  4. let templateSecVersion = "v1";
  5. // 图框模板来源id和版本
  6. const templateTkMapId = "template_tk";
  7. const templateTkVersion = "v1";
  8. // 注:以下所的有objectid来源方法为:
  9. // 在唯杰云端管理平台 https://vjmap.com/app/cloud 里面以内存方式打开模板图,然后点击相应实体,在属性面板中获取object值
  10. // 或者以几何渲染方式打开模板图,点击相应实体,在属性面板中获取object值,如果是块实体(objectid中有多个_),取第一个_前面的字符串
  11. let svc = new vjmap.Service(env.serviceUrl, env.accessToken);
  12. // 获取模板信息
  13. let tplInfo;
  14. // 获取模板中的信息
  15. const getTemplateInfo = async (templateSectId, version) => {
  16.     let features = await getTemplateData(templateSectId, version);
  17.     // 获取所有填充符号。先获取 填充符号 图层中的所有文字,文字上面的hatch就是填充符号
  18.     let hatchInfos = features.filter(f => f.layername == "填充符号" && f.name == "AcDbMText").map(t => {
  19.         let hatch = features.filter(f => f.layername == "填充符号" && f.name == "AcDbHatch").find(h =>
  20.             // 填充垂直方向位于文字上方,并且距离不能超过文字高度两倍,水平方向包含文字中心点水平方向
  21.             h.envelop.min.y > t.envelop.max.y &&
  22.             h.envelop.min.y - t.envelop.max.y < t.envelop.height() * 2 &&
  23.             h.envelop.min.x <= t.envelop.center().x &&
  24.             h.envelop.max.x >= t.envelop.center().x
  25.         )
  26.         if (!hatch) return;
  27.         return {
  28.             name: t.text,
  29.             hatchObjectId: hatch.objectid
  30.         }
  31.     })
  32.     // 获取绘制开始的位置线
  33.     let lineInfo = features.filter(f => f.layername == "线" && f.name == "AcDbLine");
  34.     let startLine;
  35.     if (lineInfo.length > 0) {
  36.         startLine = {
  37.             objectId: lineInfo[0].objectid,
  38.             positon: [lineInfo[0].envelop.min.x, lineInfo[0].envelop.min.y]
  39.         }
  40.     }
  41.     return {
  42.         startLine,
  43.         hatchInfos
  44.     }
  45. }<br>​
  46. // 模拟数据
  47. const mockData = (hatchNames, minCount) => {
  48.     // 对填充符号次序先随机排序下,这样每次生成次序就不一样了
  49.     hatchNames.sort(() => Math.random() - 0.5);
  50.     let data = [];
  51.     // 孔口个数
  52.     let kongCount = vjmap.randInt(minCount, minCount * 2);
  53.     for(let i = 0; i < kongCount; i++) {
  54.         let item = {
  55.             name: '孔' + (i + 1),
  56.             x: 15 * (i + 1) + vjmap.randInt(0, 10) + 1000, // 孔口坐标x 生成随机数x
  57.             y: vjmap.randInt(100, 105), // 孔口坐标y 生成随机数y
  58.             stratums: [] // 分层数据
  59.         }
  60.         // 生成每层的信息
  61.         let stratumCount = vjmap.randInt(5, hatchNames.length - 1);
  62.         let stratumAllThickness = 0;
  63.         for(let k = 0; k < stratumCount; k++) {
  64.             const thickness = vjmap.randInt(2, 6) // 随机生成一个厚度
  65.             item.stratums.push({
  66.                 hatch: hatchNames[k],
  67.                 thickness: thickness
  68.             })
  69.             stratumAllThickness += thickness;
  70.         }
  71.         item.stratumsThickness = stratumAllThickness; // 所有的厚度
  72.         data.push(item);
  73.     }
  74.     return data;
  75. }
  76. // 创建剖面图
  77. const createSectDoc = async (sectData) => {
  78.     // 获取要绘制的数据
  79.     let drawData = sectData;
  80.     // 获取最大和最小值
  81.     let minX = Math.min(...drawData.map(d => d.x));
  82.     let maxX = Math.max(...drawData.map(d => d.x));
  83.     let minY = Math.min(...drawData.map(d => d.y));
  84.     let maxY = Math.max(...drawData.map(d => d.y + d.stratumsThickness));
  85.     minY = Math.floor(minY / 10) * 10; // 往10取整,刻度以10为单位
  86.     maxY = Math.ceil(maxY / 10) * 10 + 10; // 往10取整,刻度以10为单位,稍长点
  87.     let posMaxX = maxX - minX + 20; //x绘制位置,相对距离从标尺偏移十个像素
  88.     let posMinX = 10;//x绘制位置,相对距离从标尺偏移十个像素<br>​
  89.     const startPoint = tplInfo.startLine.positon;<br>​
  90.     let doc = new vjmap.DbDocument();
  91.     // 数据来源
  92.     doc.from = `${templateSectId}/${templateSecVersion}`;<br>​
  93.     // 把来源图的数据最后都清空,(这里的模板不需要清空,直接用了)
  94.     // doc.isClearFromDb = true;
  95.     let entitys = [];<br>​
  96.     // 左边刻度
  97.     entitys.push(new vjmap.DbLine({
  98.         objectid: "169A2",
  99.         start: startPoint,
  100.         end: [startPoint[0], startPoint[1] + (maxY - minY)]
  101.     }))
  102.     for(let y = minY; y < maxY; y += 10) {
  103.         let pt = [startPoint[0], startPoint[1] + maxY - y];
  104.         entitys.push(new vjmap.DbLine({
  105.             start: pt,
  106.             end: [pt[0] - 2, pt[1]]
  107.         }))
  108.         // 刻度值<br>​
  109.         entitys.push(new vjmap.DbText({
  110.             cloneObjectId: '168C8',
  111.             position: [pt[0] - 1, pt[1] + 0.2],
  112.             text: y + ''
  113.         }))
  114.     }
  115.     // 右边刻度
  116.     entitys.push(new vjmap.DbLine({
  117.         cloneObjectId: "169A2", // 不是修改了,是克隆左边的刻度线
  118.         start: [startPoint[0] + posMaxX, startPoint[1]],
  119.         end: [startPoint[0] + posMaxX, startPoint[1] + (maxY - minY)]
  120.     }))
  121.     for(let y = minY; y < maxY; y += 10) {
  122.         let pt = [startPoint[0], startPoint[1] + maxY - y];
  123.         entitys.push(new vjmap.DbLine({
  124.             start: [pt[0] + posMaxX , pt[1]],
  125.             end: [pt[0]  + posMaxX + 2, pt[1]]
  126.         }))
  127.         // 刻度值
  128.         entitys.push(new vjmap.DbText({
  129.             cloneObjectId: '168C8',
  130.             position: [pt[0] + posMaxX + 1, pt[1] + 0.2],
  131.             text: y + ''
  132.         }))
  133.     }<br>​
  134.     // 修改线坐标
  135.     entitys.push(new vjmap.DbLine({
  136.         cloneObjectId:  tplInfo.startLine.objectId,
  137.         start: [startPoint[0], startPoint[1]],
  138.         end: [startPoint[0] + posMaxX, startPoint[1]]
  139.     }))<br>​<br>​
  140.     // 演示下块及属性字段的使用,这里用块创建一个孔口名称和x坐标,中间用横线隔开
  141.     const blockName = "nameAndx";
  142.     let block = new vjmap.DbBlock();
  143.     block.name = blockName;
  144.     block.origin = [0, 0]
  145.     block.entitys = [
  146.         new vjmap.DbAttributeDefinition({
  147.             position: [0, 0.2],
  148.             contents: "名称",
  149.             tag: "NAME",
  150.             colorIndex: 7, // 自动反色
  151.             horizontalMode: vjmap.DbTextHorzMode.kTextCenter,
  152.             verticalMode: vjmap.DbTextVertMode.kTextBottom, // kTextBottom,
  153.             height: 0.5,
  154.         }),
  155.         new vjmap.DbLine({
  156.             start: [-2, 0],
  157.             end: [2, 0]
  158.         }),
  159.         new vjmap.DbAttributeDefinition({
  160.             position: [0, -0.2],
  161.             contents: "X坐标",
  162.             tag: "POSX",
  163.             colorIndex: 7, // 自动反色
  164.             horizontalMode: vjmap.DbTextHorzMode.kTextCenter,
  165.             verticalMode: vjmap.DbTextVertMode.kTextTop, // kTextBottom,
  166.             height: 0.5,
  167.         })
  168.     ];
  169.     doc.appendBlock(block);
  170.     // 绘制每一个孔
  171.     for(let i = 0; i < drawData.length; i++) {
  172.         // 开始绘制的位置点
  173.         let x = posMinX + drawData[i].x - minX;
  174.         let y = startPoint[1] + maxY - drawData[i].y;
  175.         // 名称和x,用上面的块创建块参照
  176.         let blockRef = new vjmap.DbBlockReference();
  177.         blockRef.blockname = blockName;
  178.         blockRef.position =  [x + 1.5,  y + 3];
  179.         // 修改属性定义值
  180.         blockRef.attribute = {
  181.             NAME: drawData[i].name,
  182.             POSX: drawData[i].x
  183.         }
  184.         entitys.push(blockRef);<br>​
  185.         // 一层一层绘制
  186.         for(let k = 0; k < drawData[i].stratums.length; k++) {
  187.             let y2 = y - drawData[i].stratums[k].thickness;
  188.             let bounds = vjmap.GeoBounds.fromArray([x, y, x + 3, y2]);
  189.             let points = bounds.toPointArray(); // 转成点坐标格式
  190.             // 闭合
  191.             points.push(points[0]);
  192.             // 填充
  193.             entitys.push(new vjmap.DbHatch({
  194.                 cloneObjectId: drawData[i].stratums[k].hatch.hatchObjectId,
  195.                 points: points,
  196.                 patternScale: 1.5
  197.             }))
  198.             // 边框
  199.             entitys.push(new vjmap.Db2dPolyline({
  200.                 points: points
  201.             }))<br>​
  202.             // 绘制连接下一个孔的线
  203.             if (i != drawData.length - 1) {
  204.                 const nextKongStratums = drawData[i + 1].stratums;
  205.                 let nextX = posMinX + drawData[i + 1].x - minX;
  206.                 let nextY = startPoint[1] + maxY - drawData[i + 1].y;
  207.                 if (k < nextKongStratums.length) {
  208.                     for(let n = 0; n <= k; n++) {
  209.                         nextY = nextY - drawData[i + 1].stratums[n].thickness;
  210.                     }
  211.                     entitys.push(new vjmap.DbLine({
  212.                         start: [x + 3, y2],
  213.                         end: [nextX, nextY]
  214.                     }))
  215.                 }
  216.                 // 水平间距
  217.                 entitys.push(new vjmap.DbLine({
  218.                     start: [x, startPoint[1]],
  219.                     end: [x, startPoint[1] - 2]
  220.                 }))
  221.                 entitys.push(new vjmap.DbLine({
  222.                     start: [nextX, startPoint[1]],
  223.                     end: [nextX, startPoint[1] - 2]
  224.                 }))
  225.                 entitys.push(new vjmap.DbLine({
  226.                     start: [x, startPoint[1] - 2],
  227.                     end: [nextX, startPoint[1] - 2]
  228.                 }))
  229.                 // 间距值
  230.                 entitys.push(new vjmap.DbText({
  231.                     cloneObjectId: '168C8',
  232.                     position: [(x + nextX) / 2, startPoint[1] - 1],
  233.                     text: nextX - x,
  234.                     horizontalMode: vjmap.DbTextHorzMode.kTextCenter, // kTextCenter
  235.                     verticalMode: vjmap.DbTextVertMode.kTextVertMid // kTextVertMid,
  236.                 }))
  237.             }
  238.             y = y2;
  239.         }
  240.         // 最下面写上累计厚度值
  241.         entitys.push(new vjmap.DbText({
  242.             cloneObjectId: '168C8',
  243.             position: [x + 1.5, y - 0.2],
  244.             text: drawData[i].stratumsThickness,
  245.             horizontalMode: vjmap.DbTextHorzMode.kTextCenter, // kTextCenter
  246.             verticalMode: vjmap.DbTextVertMode.kTextTop // kTextTop,
  247.         }))<br>​<br>​
  248.     }<br>​
  249.     entitys.push(new vjmap.DbText({
  250.         objectid: '1687C',
  251.         position: [(posMinX + posMaxX) / 2.0, startPoint[1] + maxY - minY + 10],
  252.         /* 如果是相对位置,可以利用矩阵
  253.         matrix: [
  254.             {
  255.                 op: "translation",
  256.                 vector: [相对偏移x, 相对偏移y]
  257.             }
  258.         ],*/
  259.         text: `剖面图${Date.now()}`
  260.     }))<br>​
  261.     // 绘制图框
  262.     let bounds = vjmap.GeoBounds.fromArray([posMinX - 20, startPoint[1] + maxY - minY + 15, posMaxX + 10, startPoint[1] - 20]);
  263.     let labelPos = [bounds.max.x, bounds.min.y];
  264.     let points = bounds.toPointArray(); // 转成点坐标格式
  265.     // 闭合
  266.     points.push(points[0]);
  267.     // 边框
  268.     entitys.push(new vjmap.Db2dPolyline({
  269.         points: points
  270.     }))
  271.     bounds = bounds.scale(1.02);
  272.     points = bounds.toPointArray(); // 转成点坐标格式
  273.     // 闭合
  274.     points.push(points[0]);
  275.     // 边框
  276.     entitys.push(new vjmap.Db2dPolyline({
  277.         points: points,
  278.         lineWidth: 30 // mm
  279.     }))<br>​
  280.     let date = new Date();
  281.     // 图框从其他模板插入,并修改块属性文字
  282.     entitys.push(new vjmap.DbBlockReference({
  283.         cloneObjectId: '6A1',
  284.         cloneFromDb: `${templateTkMapId}/${templateTkVersion}`,
  285.         position: labelPos,
  286.         attribute: {
  287.             // 修改块中的属性字段
  288.             DATETIME: `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`,
  289.             COMPANY: {
  290.                 text: "唯杰地图VJMAP",
  291.                 color: 0x00FFFF
  292.             }
  293.         }
  294.     }))<br>​
  295.     entitys.push(new vjmap.DbLine({
  296.         objectid: "168C8", // 这个模板文字不用了,直接删除了
  297.         delete: true
  298.     }))
  299.     doc.entitys = entitys;
  300.     return doc;
  301. }<br>​<br>​
  302. // 先得设置一个要图形的所有范围,这个范围是随便都没有有关系的。最后导出dwg时,会根据实体的所有坐标去自动计算真实的范围。
  303. let mapBounds = '[-10000,-10000,10000,10000]'
  304. let mapExtent = vjmap.GeoBounds.fromString(mapBounds);
  305. mapExtent = mapExtent.square(); // 要转成正方形<br>​
  306. svc.setCurrentMapParam({
  307.     darkMode: true, // 由于没有打开过图,所以主动设置黑色模式
  308.     bounds: mapExtent.toString()
  309. })
  310. // 建立坐标系
  311. let prj = new vjmap.GeoProjection(mapExtent);<br>​
  312. // 新建地图对象
  313. let map = new vjmap.Map({
  314.     container: 'map', // container ID
  315.     style: {
  316.         version: svc.styleVersion(),
  317.         glyphs: svc.glyphsUrl(),
  318.         sources: {},
  319.         layers: []
  320.     },// 矢量瓦片样式
  321.     center: [0,0], // 中心点
  322.     zoom: 2,
  323.     renderWorldCopies: false
  324. });
  325. // 地图关联服务对象和坐标系
  326. map.attach(svc, prj);<br>​
  327. // 使地图全部可见
  328. map.fitMapBounds();
  329. await map.onLoad();<br>​<br>​
  330. // 创建一个几何对象
  331. const createGeomData = async (map, doc) => {
  332.     let svc = map.getService();
  333.     let res = await svc.cmdCreateEntitiesGeomData({
  334.         filedoc: doc.toDoc()
  335.     });
  336.     if (res.error) {
  337.         message.error(res.error);
  338.         return {
  339.             type: "FeatureCollection",
  340.             features: []
  341.         };
  342.     }
  343.     if (res.metadata && res.metadata.mapBounds) {
  344.         // 如果返回的元数据里面有当前地图的范围,则更新当前地图的坐标范围
  345.         map.updateMapExtent(res.metadata.mapBounds);
  346.     }<br>​
  347.     const features = [];
  348.     if (res && res.result && res.result.length > 0) {
  349.         for (let ent of res.result) {
  350.             if (ent.geom && ent.geom.geometries) {
  351.                 let clr = map.entColorToHtmlColor(ent.color); // 实体颜色转html颜色
  352.                 let featureAttr = {};
  353.                 // 因为要组合成一个组合实体,所以线和多边形的颜色得区分
  354.                 if (ent.isPolygon) {
  355.                     featureAttr.color = clr; // 填充色,只对多边形有效
  356.                     featureAttr.noneOutline = true; // 不显示多边形边框,只对多边形有效
  357.                 } else {
  358.                     featureAttr.color = clr; // 颜色
  359.                     featureAttr.line_width = ent.lineWidth; // 线宽
  360.                 }
  361.                 let ft = {
  362.                     id: vjmap.RandomID(10),
  363.                     type: "Feature",
  364.                     properties: {
  365.                         objectid: ent.objectid,
  366.                         opacity: ent.alpha / 255,
  367.                         ...featureAttr,
  368.                     }
  369.                 }
  370.                 if (ent.geom.geometries.length == 1) {
  371.                     features.push({
  372.                         ...ft,
  373.                         geometry: ent.geom.geometries[0],
  374.                     });
  375.                 } else {
  376.                     features.push({
  377.                         ...ft,
  378.                         geometry: {
  379.                             geometries: ent.geom.geometries,
  380.                             type: "GeometryCollection"
  381.                         },
  382.                     });
  383.                 }<br>​
  384.             }
  385.         }
  386.     }
  387.     return {
  388.         type: "FeatureCollection",
  389.         features: features,
  390.     };
  391. };<br>​
  392. // 清空之前的地图数据
  393. const clearMapData = () => {
  394.     svc.setCurrentMapParam({
  395.         darkMode: true, // 由于没有打开过图,所以主动设置黑色模式
  396.         bounds: mapExtent.toString()
  397.     })
  398.     map.disableLayerClickHighlight();
  399.     map.removeDrawLayer();
  400.     let sources = map.getStyle().sources;
  401.     for(let source in sources) {
  402.         map.removeSourceEx(source);
  403.     }
  404. }<br>​
  405. // 创建一个有数据的地图
  406. const createDataMap = async (doc) => {
  407.     clearMapData();
  408.     let geojson = await createGeomData(map, doc);
  409.     const opts = vjmap.Draw.defaultOptions();
  410.     // 修改默认样式,把点的半径改成1,没有边框,默认为5
  411.     let pointIdx = opts.styles.findIndex(s => s.id === "gl-draw-point-point-stroke-inactive");
  412.     if (pointIdx >= 0) {
  413.         opts.styles[pointIdx]['paint']['circle-radius'][3][3] = 0
  414.     }
  415.     pointIdx = opts.styles.findIndex(s => s.id === "gl-draw-point-inactive");
  416.     if (pointIdx >= 0) {
  417.         opts.styles[pointIdx]['paint']['circle-radius'][3][3] = 1
  418.     }
  419.     map.getDrawLayer(opts).set(geojson);
  420. }<br>​
  421. // 创建一个dwg的地图
  422. const createDwgMap = async (doc) => {
  423.     // 先清空之前绘制的
  424.     clearMapData();
  425.     // js代码
  426.     let res = await svc.updateMap({
  427.         // 获取一个临时的图id(临时图形只会用临时查看,过期会自动删除)
  428.         mapid: vjmap.getTempMapId(1), // 临时图形不浏览情况下过期自动删除时间,单位分钟。默认30
  429.         filedoc: doc.toDoc(),
  430.         mapopenway: vjmap.MapOpenWay.Memory,
  431.         style: {
  432.             backcolor: 0 // 如果div背景色是浅色,则设置为oxFFFFFF
  433.         }
  434.     })
  435.     if (res.error) {
  436.         message.error(res.error)
  437.     }
  438.     await map.switchMap(res);
  439. }<br>​<br>​
  440. let curDoc;
  441. const exportDwgOpen = async () => {
  442.     if (!curDoc) return;
  443.     const mapid = 'exportdwgmap';
  444.     let res = await svc.updateMap({
  445.         mapid: mapid,
  446.         filedoc: curDoc.toDoc(),
  447.         mapopenway: vjmap.MapOpenWay.Memory,
  448.         style: {
  449.             backcolor: 0 // 如果div背景色是浅色,则设置为oxFFFFFF
  450.         }
  451.     })
  452.     if (res.error) {
  453.         message.error(res.error)
  454.     } else{
  455.         window.open(`https://vjmap.com/app/cloud/#/map/${res.mapid}?version=${res.version}&mapopenway=Memory&vector=false`)
  456.     }
  457. }<br>​
  458. // 获取模板的所有数据
  459. const getTemplateData = async (mapid, version) => {
  460.     let res = await svc.rectQueryFeature({
  461.         mapid,
  462.         version,
  463.         fields: "",
  464.         geom: false, // 以内存方式打开,获取真正的objectid
  465.         maxGeomBytesSize: 0, // 不需要几何坐标
  466.         useCache: true, // 因为是以内存方式打开,后台先把查询的数据保存进缓存,下次直接去缓存查找,提高效率
  467.         // x1,y1,x2,y2同时不输的话,表示是查询整个图的范围  这范围不输入,表示是全图范围
  468.     })
  469.     // 把实体的范围字符串转成对象
  470.     res.result.map(f => f.envelop = vjmap.GeoBounds.fromString(f.bounds));
  471.     console.log(res.result)
  472.     return res.result;
  473. }<br>​<br>​
  474. const creatSectDataMap = async () => {
  475.     let sectData = mockData(tplInfo.hatchInfos, 5);
  476.     const doc = await createSectDoc(sectData);
  477.     await createDataMap(doc);
  478.     map.fitMapBounds();
  479.     curDoc = doc;
  480. }
  481. const creatSectDwgMap = async () => {
  482.     let sectData = mockData(tplInfo.hatchInfos, 15);
  483.     const doc = await createSectDoc(sectData);
  484.     await createDwgMap(doc);
  485.     map.fitMapBounds();
  486.     // 点击有高亮状态(鼠标点击地图元素上时,会高亮)
  487.     map.enableLayerClickHighlight(svc, e => {
  488.         if (!e) return;
  489.         let msg = {
  490.             content: `type: ${e.name}, id: ${e.objectid}, layer: ${e.layerindex}`,
  491.             key: "layerclick",
  492.             duration: 5
  493.         }
  494.         e && message.info(msg);
  495.     })
  496.     curDoc = doc;
  497. }
  498. // 先获取模板信息
  499. tplInfo = await getTemplateInfo(templateSectId, templateSecVersion);
  500. // 随机生成一个剖面图
  501. creatSectDataMap();
  502. // UI界面
  503. const App = () => {
  504.     return (
  505.         
  506.             
  507.                
  508.                     <button className="btn btn-full mr0" onClick={creatSectDataMap}>随机生成一个剖面图[前端直接绘制,适合于生成图不大的情况]</button>
  509.                     <button className="btn btn-full mr0" onClick={creatSectDwgMap}>随机生成剖面图[后台生成DWG前端展示,适合于生成图大的情况]</button>
  510.                     <button className="btn btn-full mr0" onClick={exportDwgOpen}>导出成DWG图并打开</button>
  511.                
  512.             
  513.         
  514.     );
  515. }
  516. ReactDOM.render(<App />, document.getElementById('ui'));<br>​<br>​
  517. const mousePositionControl = new vjmap.MousePositionControl();
  518. map.addControl(mousePositionControl, "bottom-left");
复制代码
  
  1. <br>​
复制代码
 
来源:https://www.cnblogs.com/vjmap/p/17179837.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具