• CAD图在线Web测量工具代码实现(测量距离、面积、角度等)


    CAD如今在各个领域均得到了普遍的应用并大大提高了工程技术人员的工作效率。在桌面端,AutoCAD测量工具已经非常强大;然后在Web端,如何准确、快速的对CAD图在Web进行测量呢?

    功能

    • 能Web在线打开AutoCAD图形

    • 测量距离

    • 测量面积

    • 测量角度

    • 坐标标注

    • 测量时能捕捉Web端CAD图形上面的坐标,提高准确度

    • 测量时能对捕捉进行开关启用

    • 测量时能启用正交模式

    • 测量时能自定义右键菜单功能

    • 能进行连续测量

    • 测量结束后,能删除已测量的结果

    效果

    能Web在线打开AutoCAD图形

    如果在Web网页端展示CAD图形(唯杰地图云端图纸管理平台 https://vjmap.com/app/cloud),这个在前面的博文中已讲过,这里不再重复,有需要的朋友可下载工程源代码研究下。

    测量距离

    image-20220623192548087

    测量面积

    image-20220623192725011

    测量角度

    image-20220623193100555

    坐标标注

    image-20220623193145638

    其他功能

    在测量过程中,按Alt键可开启关闭捕捉;按Ctrl键可启用正交模式;按退格键可删除上一个点;按ESC键取消测量;按Enter键结束测量; 按右键弹出上下文菜单

    image-20220623194559185

    代码实现

     
    有需要的朋友可以在线体验下。上面的案例代码已开源。访问 (唯杰地图云端图纸管理平台 https://vjmap.com/app/cloud) ,点击下载此案例源码即可。

    复制代码
      1 import vjmap, { Map } from 'vjmap'
      2 import { sleep } from '~/utils/ui';
      3 import { getMapSnapPoints } from './snap';
      4 let snapObj: any; // 设置的捕捉的实体
      5 let curMeasureCmd: string; // 当前测量命令
      6 export async function runMeasureCmd(map: Map, cmd: string) {
      7   curMeasureCmd = cmd;
      8   if (cmd != "measureCancel") {
      9     // 先结束当前测量
     10     await measureCancel(map);
     11     if (!snapObj) {
     12         // 获取地图上的捕捉点
     13         snapObj = {};
     14         getMapSnapPoints(map, snapObj);
     15     }
     16   }
     17   switch (cmd) {
     18     case "measureDist":
     19       measureDistLoop(map, snapObj);
     20       break;
     21     case "measureArea":
     22       measureAreaLoop(map, snapObj);
     23       break;
     24     case "measureAngle":
     25       measureAngleLoop(map, snapObj);
     26       break;
     27     case "measureCoordinate":
     28       measureCoordinateLoop(map, snapObj);
     29       break;
     30     case "measureCancel":
     31       await measureCancel(map);
     32       break;
     33   }
     34 }
     35  36 // 结束绘制
     37 const measureCancel = async (map: Map)=> {
     38     // 连续发送取消键,第一次取消当前绘制,第二次退出测量
     39     map.fire("keyup", {keyCode:27});
     40     await sleep(100);
     41     map.fire("keyup", {keyCode:27});
     42     await sleep(100);
     43     map.setIsInteracting(false); // 没有进行交互操作了
     44 }
     45  46 let popup: vjmap.Popup | null;
     47 const setPopupText = (text: string, map: Map) => {
     48     if (text) {
     49         if (!popup) {
     50             popup = new vjmap.Popup({
     51                 className: "my-custom-popup",
     52                 closeOnClick: false,
     53                 closeButton: false
     54             })
     55                 .setHTML(text)
     56                 .setMaxWidth("500px")
     57                 .trackPointer()
     58                 .addTo(map)
     59         }
     60         else {
     61             popup.setHTML(text);
     62         }
     63     } else {
     64         // 如果为空时,则删除popup
     65         if (popup) {
     66             popup.setLngLat([0,0]); // 取消trackPointer
     67             popup.remove();
     68             popup = null;
     69         }
     70     }
     71  72 }
     73 // 测量距离循环,直至按ESC键取消,否则测量完一条后,继续测量下一条
     74 const measureDistLoop = async (map: Map, snapObj: any)=> {
     75     while(true) {
     76         let res = await measureDist(map, snapObj);
     77         if (res.exit === true) break;
     78         if (curMeasureCmd != "measureDist") break;
     79     }
     80 }
     81  82 // 测量距离
     83 const measureDist = async (map: Map, snapObj: any)=> {
     84     let isDrawing = false;
     85     let line = await vjmap.Draw.actionDrawLineSting(map, {
     86         api: {
     87             getSnapFeatures: snapObj //要捕捉的数据项在后面,通过属性features赋值
     88         },
     89         updatecoordinate: (e: any) => {
     90             if (!e.lnglat) return;
     91             isDrawing = true;
     92             const co = map.fromLngLat(e.feature.coordinates[e.feature.coordinates.length - 1]);
     93             let html = `【测量距离】当前坐标:<span style="color: #ff0000"> ${co.x.toFixed(2)}, ${co.y.toFixed(2)}</span>`;
     94             if (e.feature.coordinates.length == 1) {
     95                 html += "<br/>请指定要测量的第一点的坐标位置"
     96             } else {
     97                 let len = e.feature.coordinates.length;
     98                 html += `<br/>按Alt键取捕捉; Ctrl键启用正交; 退格键删除上一个点`
     99                 html += `<br/>距上一点距离: <span style="color: #ff0000">${getDist(map, [e.feature.coordinates[len - 2], e.feature.coordinates[len -1]])}</span>`
    100                 html += `;  当前总的距离: <span style="color: #ff0000">${getDist(map, e.feature.coordinates)}</span>`
    101             }
    102             setPopupText(html, map)
    103         },
    104         contextMenu: (e: any) => {
    105             new vjmap.ContextMenu({
    106                 event: e.event.originalEvent,
    107                 theme: "dark", //light
    108                 width: "250px",
    109                 items: [
    110                     {
    111                         label: '确认',
    112                         onClick: () => {
    113                             // 给地图发送Enter键消息即可取消,模拟按Enter键
    114                             map.fire("keyup", {keyCode:13})
    115                             setPopupText("", map);
    116                         }
    117                     },
    118                     {
    119                         label: '取消',
    120                         onClick: () => {
    121                             // 给地图发送ESC键消息即可取消,模拟按ESC键
    122                             map.fire("keyup", {keyCode:27})
    123                             setPopupText("", map);
    124                         }
    125                     },{
    126                         label: '删除上一个点',
    127                         onClick: () => {
    128                             // 给地图发送退格键Backspace消息即可删除上一个点,模拟按Backspace键
    129                             map.fire("keyup", {keyCode:8})
    130                         }
    131                     },{
    132                         label: '结束测距',
    133                         onClick: () => {
    134                             // 给地图发送ESC键消息即可取消,模拟按ESC键
    135                             map.fire("keyup", {keyCode:27})
    136                             isDrawing = false;
    137                             setPopupText("", map);
    138                         }
    139                     }
    140                 ]
    141             });
    142 143         }
    144     });
    145     if (line.cancel) {
    146         setPopupText("", map);
    147         return {
    148             cancel: true,
    149             exit: isDrawing === false // 如果还没有绘制,就取消的话,就结束测距
    150         };// 取消操作
    151     }
    152 153     let color = vjmap.randomColor();
    154     let polyline = new vjmap.Polyline({
    155         data: line.features[0].geometry.coordinates,
    156         lineColor: color,
    157         lineWidth: 2
    158     });
    159     polyline.addTo(map);
    160     addMarkersToLine(map, line.features[0].geometry.coordinates, color, polyline.sourceId || "", snapObj);
    161     return {
    162         polyline
    163     };
    164 }
    165 166 167 // 给线的加个点加个测量的结果值
    168 const addMarkersToLine = (map: Map, coordinates: Array<[number, number]>, color: string, sourceId: string, snapObj: any) => {
    169     let markerTexts: any = [];
    170     for(let i = 1; i < coordinates.length; i++) {
    171         let text = new vjmap.Text({
    172             text: getDist(map, coordinates.slice(0, i + 1)),
    173             anchor: "left",
    174             offset: [3, 0], // x,y 方向像素偏移量
    175             style:{     // 自定义样式
    176                 'cursor': 'pointer',
    177                 'opacity': 0.8,
    178                 'padding': '6px',
    179                 'border-radius': '12px',
    180                 'background-color': color,
    181                 'border-width': 0,
    182                 'box-shadow': '0px 2px 6px 0px rgba(97,113,166,0.2)',
    183                 'text-align': 'center',
    184                 'font-size': '14px',
    185                 'color': `#${color.substring(1).split("").map(c => (15 - parseInt(c,16)).toString(16)).join("")}`,
    186             }
    187         });
    188         text.setLngLat(coordinates[i]).addTo(map);
    189         markerTexts.push(text);
    190     }
    191     // 给第一个点加一个marker用来删除
    192     const deletePng = "delete.png";
    193     let el = document.createElement('div');
    194     el.className = 'marker';
    195     el.style.backgroundImage =
    196         `url(${deletePng})`;
    197     el.style.width = '20px';
    198     el.style.height = '20px';
    199     el.style.backgroundSize = '100%';
    200     el.style.cursor = "pointer";
    201 202     el.addEventListener('click', function (e) {
    203         map.removeSourceEx(sourceId); // 删除绘制的线
    204         markerTexts.forEach((m: any) => m.remove());
    205         markerTexts = [];
    206 207         // 多点了下,给地图发送退格键Backspace消息即可删除上一个点,模拟按Backspace键
    208         map.fire("keyup", {keyCode:8})
    209     });
    210     // Add markers to the map.
    211     let deleteMarker = new vjmap.Marker({
    212         element: el,
    213         anchor: 'right'
    214     });
    215     deleteMarker.setLngLat(coordinates[0])
    216         .setOffset([-5, 0])
    217         .addTo(map);
    218     markerTexts.push(deleteMarker)
    219 220     // 把坐标加进捕捉数组中。
    221     addSnapCoordinates(snapObj, coordinates);
    222 }
    223 // 得到距离值
    224 const getDist = (map: Map, coordinates: Array<[number, number]>) => {
    225     let result = vjmap.Math2D.lineDist(map.fromLngLat(coordinates));
    226     let unit = "m";
    227     if (result >= 1000) {
    228         result /= 1000;
    229         unit = "km";
    230     } else if (result < 0.01) {
    231         result *= 100;
    232         unit = "cm";
    233     }
    234     return result.toFixed(2) + " " + unit;
    235 }
    236 // 增加捕捉点
    237 const addSnapCoordinates = (snapObj: any, coordinates: Array<[number, number]>) => {
    238     snapObj.features.push({
    239         type: "Feature",
    240         geometry: {
    241             type: "LineString",
    242             coordinates: [...coordinates]
    243         }
    244     })
    245 }
    246 247 248 249 // 测量面积
    250 const measureArea = async (map: Map, snapObj: any)=> {
    251     let isDrawing = false;
    252     let poly = await vjmap.Draw.actionDrawPolygon(map, {
    253         api: {
    254             getSnapFeatures: snapObj //要捕捉的数据项在后面,通过属性features赋值
    255         },
    256         updatecoordinate: (e: any) => {
    257             if (!e.lnglat) return;
    258             isDrawing = true;
    259             const co = map.fromLngLat(e.feature.coordinates[0][e.feature.coordinates.length - 1]);
    260             let html = `【测量面积】当前坐标:<span style="color: #ff0000"> ${co.x.toFixed(2)}, ${co.y.toFixed(2)}</span>`;
    261             if (e.feature.coordinates[0].length == 1) {
    262                 html += "<br/>请指定要测量的第一点的坐标位置"
    263             } else {
    264                 html += `<br/>按Alt键取捕捉; Ctrl键启用正交; 退格键删除上一个点`
    265                 html += `<br/>当前面积: <span style="color: #ff0000">${getArea(map, e.feature.coordinates[0])}</span>`
    266             }
    267             setPopupText(html, map)
    268         },
    269         contextMenu: (e: any) => {
    270             new vjmap.ContextMenu({
    271                 event: e.event.originalEvent,
    272                 theme: "dark", //light
    273                 width: "250px",
    274                 items: [
    275                     {
    276                         label: '确认',
    277                         onClick: () => {
    278                             // 给地图发送Enter键消息即可取消,模拟按Enter键
    279                             map.fire("keyup", {keyCode:13})
    280                             setPopupText("", map);
    281                         }
    282                     },
    283                     {
    284                         label: '取消',
    285                         onClick: () => {
    286                             // 给地图发送ESC键消息即可取消,模拟按ESC键
    287                             map.fire("keyup", {keyCode:27})
    288                             setPopupText("", map);
    289                         }
    290                     },{
    291                         label: '删除上一个点',
    292                         onClick: () => {
    293                             // 给地图发送退格键Backspace消息即可删除上一个点,模拟按Backspace键
    294                             map.fire("keyup", {keyCode:8})
    295                         }
    296                     },{
    297                         label: '结束测面积',
    298                         onClick: () => {
    299                             // 给地图发送ESC键消息即可取消,模拟按ESC键
    300                             map.fire("keyup", {keyCode:27})
    301                             isDrawing = false;
    302                             setPopupText("", map);
    303                         }
    304                     }
    305                 ]
    306             });
    307 308         }
    309     });
    310     if (poly.cancel) {
    311         debugger
    312         setPopupText("", map);
    313         return {
    314             cancel: true,
    315             exit: isDrawing === false // 如果还没有绘制,就取消的话,就结束测距
    316         };// 取消操作
    317     }
    318 319     let color = vjmap.randomColor();
    320     let polygon = new vjmap.Polygon({
    321         data: poly.features[0].geometry.coordinates[0],
    322         fillColor: color,
    323         fillOpacity: 0.4,
    324         fillOutlineColor: color,
    325     });
    326     polygon.addTo(map);
    327     addMarkersToPolygon(map, poly.features[0].geometry.coordinates[0], color, polygon.sourceId || "", snapObj);
    328     return {
    329         polygon
    330     };
    331 }
    332 333 // 测量面积循环,直至按ESC键取消,否则测量完一条后,继续测量下一条
    334 const measureAreaLoop = async (map: Map, snapObj: any)=> {
    335     while(true) {
    336         let res = await measureArea(map, snapObj);
    337         if (res.exit === true) break;
    338         if (curMeasureCmd != "measureArea") break;
    339     }
    340 }
    341 342 // 给加个测量的结果值
    343 const addMarkersToPolygon = (map: Map, coordinates: Array<[number, number]>, color: string, sourceId: string, snapObj: any) => {
    344     let markerTexts: any = [];
    345     const center = vjmap.polygonCentroid(map.fromLngLat(coordinates));
    346     let text = new vjmap.Text({
    347         text: getArea(map, coordinates),
    348         anchor: "center",
    349         offset: [0, 0], // x,y 方向像素偏移量
    350         style:{     // 自定义样式
    351             'cursor': 'pointer',
    352             'opacity': 0.8,
    353             'padding': '6px',
    354             'border-radius': '12px',
    355             'background-color': `#${color.substring(1).split("").map(c => (15 - parseInt(c,16)).toString(16)).join("")}`,
    356             'border-width': 0,
    357             'box-shadow': '0px 2px 6px 0px rgba(97,113,166,0.2)',
    358             'text-align': 'center',
    359             'font-size': '14px',
    360             'color': color,
    361         }
    362     });
    363     text.setLngLat(map.toLngLat(center)).addTo(map);
    364     markerTexts.push(text);
    365     // 给第一个点加一个marker用来删除
    366     const deletePng = = "delete.png";
    367     let el = document.createElement('div');
    368     el.className = 'marker';
    369     el.style.backgroundImage =
    370         `url(${deletePng})`;
    371     el.style.width = '20px';
    372     el.style.height = '20px';
    373     el.style.backgroundSize = '100%';
    374     el.style.cursor = "pointer";
    375 376     el.addEventListener('click', function (e) {
    377         map.removeSourceEx(sourceId); // 删除绘制的线
    378         markerTexts.forEach((m: any) => m.remove());
    379         markerTexts = [];
    380     });
    381     // Add markers to the map.
    382     let deleteMarker = new vjmap.Marker({
    383         element: el,
    384         anchor: 'right'
    385     });
    386     deleteMarker.setLngLat(coordinates[0])
    387         .setOffset([-5, 0])
    388         .addTo(map);
    389     markerTexts.push(deleteMarker)
    390 391     // 把坐标加进捕捉数组中。
    392     addSnapCoordinates(snapObj, coordinates);
    393 }
    394 // 得到面积值
    395 const getArea = (map: Map, coordinates: Array<[number, number]>) => {
    396     let result = vjmap.calcPolygonArea(map.fromLngLat(coordinates));
    397     let unit = "m²";
    398     if (result >= 1e6) {
    399         result /= 1e6;
    400         unit = "km²";
    401     } else if (result < 1.0/1e4) {
    402         result *= 1e4;
    403         unit = "cm²";
    404     }
    405     return result.toFixed(2) + " " + unit;
    406 }
    407 408 409 410 // 测量角度
    411 const measureAngle = async (map: Map, snapObj: any)=> {
    412     let isDrawing = false;
    413     let line = await vjmap.Draw.actionDrawLineSting(map, {
    414         pointCount: 3,// 只需三个点,绘制完三个点后,自动结束
    415         api: {
    416             getSnapFeatures: snapObj //要捕捉的数据项在后面,通过属性features赋值
    417         },
    418         updatecoordinate: (e: any) => {
    419             if (!e.lnglat) return;
    420             isDrawing = true;
    421             const co = map.fromLngLat(e.feature.coordinates[e.feature.coordinates.length - 1]);
    422             let html = `【测量角度】当前坐标:<span style="color: #ff0000"> ${co.x.toFixed(2)}, ${co.y.toFixed(2)}</span>`;
    423             if (e.feature.coordinates.length == 1) {
    424                 html += "<br/>请指定要测量的第一点的坐标位置"
    425             } else {
    426                 let len = e.feature.coordinates.length;
    427                 html += `<br/>按Alt键取捕捉; Ctrl键启用正交; 退格键删除上一个点`
    428                 html += `<br/>当前角度: <span style="color: #ff0000">${getAngle(map, e.feature.coordinates).angle}</span>`
    429             }
    430             setPopupText(html, map)
    431         },
    432         contextMenu: (e: any) => {
    433             new vjmap.ContextMenu({
    434                 event: e.event.originalEvent,
    435                 theme: "dark", //light
    436                 width: "250px",
    437                 items: [
    438                     {
    439                         label: '确认',
    440                         onClick: () => {
    441                             // 给地图发送Enter键消息即可取消,模拟按Enter键
    442                             map.fire("keyup", {keyCode:13})
    443                             setPopupText("", map);
    444                         }
    445                     },
    446                     {
    447                         label: '取消',
    448                         onClick: () => {
    449                             // 给地图发送ESC键消息即可取消,模拟按ESC键
    450                             map.fire("keyup", {keyCode:27})
    451                             setPopupText("", map);
    452                         }
    453                     },{
    454                         label: '删除上一个点',
    455                         onClick: () => {
    456                             // 给地图发送退格键Backspace消息即可删除上一个点,模拟按Backspace键
    457                             map.fire("keyup", {keyCode:8})
    458                         }
    459                     },{
    460                         label: '结束测角度',
    461                         onClick: () => {
    462                             // 给地图发送ESC键消息即可取消,模拟按ESC键
    463                             map.fire("keyup", {keyCode:27})
    464                             isDrawing = false;
    465                             setPopupText("", map);
    466                         }
    467                     }
    468                 ]
    469             });
    470 471         }
    472     });
    473     if (line.cancel) {
    474         setPopupText("", map);
    475         return {
    476             cancel: true,
    477             exit: isDrawing === false // 如果还没有绘制,就取消的话,就结束测距
    478         };// 取消操作
    479     }
    480 481     let color = vjmap.randomColor();
    482     let polyline = new vjmap.Polyline({
    483         data: line.features[0].geometry.coordinates,
    484         lineColor: color,
    485         lineWidth: 2
    486     });
    487     polyline.addTo(map);
    488     addMarkersToAngle(map, line.features[0].geometry.coordinates, color, polyline.sourceId || "", snapObj);
    489     return {
    490         polyline
    491     };
    492 }
    493 494 // 测量角度循环,直至按ESC键取消,否则测量完一条后,继续测量下一条
    495 const measureAngleLoop = async (map: Map, snapObj: any)=> {
    496     while(true) {
    497         let res = await measureAngle(map, snapObj);
    498         if (res.exit === true) break;
    499         if (curMeasureCmd != "measureAngle") break;
    500     }
    501 }
    502 503 504 505 // 给加个测量的结果值
    506 const addMarkersToAngle = (map: Map, coordinates: Array<[number, number]>, color: string, sourceId: string, snapObj: any) => {
    507     if (coordinates.length < 3) return;
    508     let markerTexts: any = [];
    509     let points = map.fromLngLat(coordinates);
    510     let textPoint = coordinates[1];
    511     let ang = getAngle(map, coordinates);
    512     // 绘制注记圆弧
    513     const cirleArcPath = vjmap.getCirclePolygonCoordinates(
    514         points[1],
    515         points[1].distanceTo(points[0]) / 4.0, 36,
    516         ang.startAngle,  ang.endAngle, false);
    517     let path = new vjmap.Polyline({
    518         data: map.toLngLat(cirleArcPath),
    519         lineColor: color,
    520         lineWidth: 2
    521     });
    522     path.addTo(map);
    523     markerTexts.push(path)
    524 525     // @ts-ignore
    526     let arcPoints = path.getData().features[0].geometry.coordinates;
    527     let arcMid = arcPoints[Math.ceil(arcPoints.length / 2)];// 取中点
    528     let textAngle = vjmap.radiansToDegrees(-map.fromLngLat(arcMid).angleTo(points[1])) + 90;
    529     if (textAngle > 90) textAngle += 180;
    530     else if (textAngle > 270) textAngle -= 180;
    531     let text = new vjmap.Text({
    532         text: ang.angle as string,
    533         anchor: "center",
    534         rotation: textAngle,
    535         offset: [0, 0], // x,y 方向像素偏移量
    536         style:{     // 自定义样式
    537             'cursor': 'pointer',
    538             'opacity': 0.8,
    539             'padding': '6px',
    540             'border-radius': '12px',
    541             'background-color': color,
    542             'border-width': 0,
    543             'box-shadow': '0px 2px 6px 0px rgba(97,113,166,0.2)',
    544             'text-align': 'center',
    545             'font-size': '14px',
    546             'color': `#${color.substring(1).split("").map(c => (15 - parseInt(c,16)).toString(16)).join("")}`,
    547         }
    548     });
    549     text.setLngLat(arcMid).addTo(map);
    550     markerTexts.push(text);
    551     // 给第一个点加一个marker用来删除
    552     const deletePng = = "delete.png";
    553     let el = document.createElement('div');
    554     el.className = 'marker';
    555     el.style.backgroundImage =
    556         `url(${deletePng})`;
    557     el.style.width = '20px';
    558     el.style.height = '20px';
    559     el.style.backgroundSize = '100%';
    560     el.style.cursor = "pointer";
    561 562     el.addEventListener('click', function (e) {
    563         map.removeSourceEx(sourceId); // 删除绘制的线
    564         markerTexts.forEach((m: any) => m.remove());
    565         markerTexts = [];
    566     });
    567     // Add markers to the map.
    568     let deleteMarker = new vjmap.Marker({
    569         element: el,
    570         anchor: 'right'
    571     });
    572     deleteMarker.setLngLat(coordinates[1])
    573         .setOffset([-5, 0])
    574         .addTo(map);
    575     markerTexts.push(deleteMarker)
    576 577     // 把坐标加进捕捉数组中。
    578     addSnapCoordinates(snapObj, coordinates);
    579 }
    580 // 得到角度值
    581 const getAngle = (map: Map, coordinates: Array<[number, number]>) => {
    582     let points = map.fromLngLat(coordinates);
    583     if (points.length < 3) return {  angle: 0.0 }
    584     let angle1 = points[0].angleTo(points[1]);
    585     let angle2 = points[2].angleTo(points[1]);
    586     let angle = angle1 - angle2;
    587     let deg = vjmap.radiansToDegrees(angle);//弧度转角度
    588     let dir = true;
    589     if (deg < 0) {
    590         deg = -deg;
    591         dir = !dir;
    592     }
    593     if (deg > 180) {
    594         deg = 360 - deg;
    595         dir = !dir;
    596     }
    597     let startAngle = !dir ? vjmap.radiansToDegrees(angle1) : vjmap.radiansToDegrees(angle2);
    598     let endAngle = dir ? vjmap.radiansToDegrees(angle1) : vjmap.radiansToDegrees(angle2);
    599     startAngle = startAngle < 0 ? 360 + startAngle : startAngle;
    600     endAngle = endAngle < 0 ? 360 + endAngle : endAngle;
    601     if (endAngle < startAngle) {
    602         endAngle += 360;
    603     }
    604     return {
    605         angle: deg.toFixed(2) + "°",
    606         dir,
    607         startAngle,
    608         endAngle
    609     }
    610 }
    611 612 613 // 测量坐标
    614 const measureCoordinate = async (map: Map, snapObj: any)=> {
    615     let isDrawing = false;
    616     let point = await vjmap.Draw.actionDrawPoint(map, {
    617         api: {
    618             getSnapFeatures: snapObj //要捕捉的数据项在后面,通过属性features赋值
    619         },
    620         updatecoordinate: (e: any) => {
    621             if (!e.lnglat) return;
    622             isDrawing = true;
    623             const co = map.fromLngLat(e.lnglat);
    624             let html = `【测量坐标】当前坐标:<span style="color: #ff0000"> ${co.x.toFixed(2)}, ${co.y.toFixed(2)}</span>`;
    625             setPopupText(html, map)
    626         },
    627         contextMenu: (e: any) => {
    628             new vjmap.ContextMenu({
    629                 event: e.event.originalEvent,
    630                 theme: "dark", //light
    631                 width: "250px",
    632                 items: [
    633                     {
    634                         label: '确认',
    635                         onClick: () => {
    636                             // 给地图发送Enter键消息即可取消,模拟按Enter键
    637                             map.fire("keyup", {keyCode:13})
    638                             setPopupText("", map);
    639                         }
    640                     },
    641                     {
    642                         label: '取消',
    643                         onClick: () => {
    644                             // 给地图发送ESC键消息即可取消,模拟按ESC键
    645                             map.fire("keyup", {keyCode:27})
    646                             setPopupText("", map);
    647                         }
    648                     },
    649                     {
    650                         label: '结束测坐标',
    651                         onClick: () => {
    652                             // 给地图发送ESC键消息即可取消,模拟按ESC键
    653                             map.fire("keyup", {keyCode:27})
    654                             isDrawing = false;
    655                             setPopupText("", map);
    656                         }
    657                     }
    658                 ]
    659             });
    660 661         }
    662     });
    663     if (point.cancel) {
    664         setPopupText("", map);
    665         return {
    666             cancel: true,
    667             exit: isDrawing === false
    668         };// 取消操作
    669     }
    670 671     addMarkersToCoord(map, point.features[0].geometry.coordinates);
    672     return {
    673         point
    674     };
    675 }
    676 677 // 测量坐标循环,直至按ESC键取消
    678 const measureCoordinateLoop = async (map: Map, snapObj: any)=> {
    679     while(true) {
    680         let res = await measureCoordinate(map, snapObj);
    681         if (res.exit === true) break;
    682         if (curMeasureCmd != "measureCoordinate") break;
    683     }
    684 }
    685 686 687 688 // 给加个点加个测量的结果值
    689 const addMarkersToCoord = (map: Map, coordinates: [number, number]) => {
    690     let markerTexts: any = [];
    691     let co = map.fromLngLat(coordinates);
    692     let content = `X: ${co.x.toFixed(2)}, Y: ${co.y.toFixed(2)}`
    693     let marker = createLeaderMarker(map, coordinates, content);
    694     markerTexts.push(marker);
    695 696     // 给第一个点加一个marker用来删除
    697     const deletePng = "delete.png";
    698     let el = document.createElement('div');
    699     el.className = 'marker';
    700     el.style.backgroundImage =
    701         `url(${deletePng})`;
    702     el.style.width = '20px';
    703     el.style.height = '20px';
    704     el.style.backgroundSize = '100%';
    705     el.style.cursor = "pointer";
    706 707     el.addEventListener('click', function (e) {
    708         markerTexts.forEach((m: any) => m.remove());
    709         markerTexts = [];
    710 711     });
    712     // Add markers to the map.
    713     let deleteMarker = new vjmap.Marker({
    714         element: el,
    715         anchor: 'right'
    716     });
    717     deleteMarker.setLngLat(coordinates)
    718         .setOffset([-5, 0])
    719         .addTo(map);
    720     markerTexts.push(deleteMarker)
    721 722 }
    723 724 // 引线标记
    725 const createLeaderMarker = (map: Map, lnglat: [number, number], content: string) => {
    726     let el = document.createElement('div');
    727     el.className = 'marker';
    728     el.style.position = 'absolute'
    729 730     let img = document.createElement("div");
    731     img.style.backgroundImage = 'bk.png';
    732     img.style.backgroundRepeat = "no-repeat"
    733     img.style.height = '37px';
    734     img.style.width = '100px';
    735     img.style.position = 'absolute';
    736     img.style.left = '-3px';
    737     img.style.bottom = '-3px';
    738     img.style.right = "0px"
    739     el.appendChild(img);
    740 741     let panel = document.createElement("div");
    742     panel.style.height = '50px';
    743     panel.style.width = '350px';
    744     panel.style.position = 'absolute';
    745     panel.style.left = '97px';
    746     panel.style.top = '-60px';
    747     panel.style.border = "solid 1px #8E0EFF";
    748     panel.style.background = 'linear-gradient(#00ffff, #00ffff) left top,  linear-gradient(#00ffff, #00ffff) left top,     linear-gradient(#00ffff, #00ffff) right bottom,    linear-gradient(#00ffff, #00ffff) right bottom';
    749     panel.style.backgroundRepeat = 'no-repeat';
    750     panel.style.backgroundColor ='rgba(87,255,255, 0.3)'
    751     panel.style.backgroundSize = '1px 6px, 6px 1px';
    752     panel.style.fontSize = '18px';
    753     panel.style.color = '#ffffff';
    754     panel.innerHTML =  `<div style='margin: 15px 5px 15px 5px'>${content}</div>`;
    755     el.appendChild(panel);
    756 757     // Add markers to the map.
    758     let marker = new vjmap.Marker({
    759         element: el,
    760         anchor: "bottom-left"
    761     })
    762     marker.setLngLat(lnglat)
    763         .addTo(map);
    764     return marker
    765 }
    766
    复制代码

     

     
  • 相关阅读:
    【C++】“最强查找“哈希表的底层实现
    Machine learning week 10(Andrew Ng)
    电力电子转战数字IC20220629day35——路科实验2b
    Single Image Haze Removal Using Dark Channel Prior(暗通道先验)
    GitLab忘记管理员密码处理和禁用注册功能
    JVM之运行时数据区、内存结构、内存模型
    SpringCloud在idea中一键启动项目
    电大搜题:开启智慧学习新时代
    科普:我就想写个爬虫,到底要学多少东西啊?
    3.0、C语言——猜数字游戏
  • 原文地址:https://www.cnblogs.com/vjmap/p/16406516.html