CAD图在线Web测量工具代码实现(测量距离、面积、角度等)
功能
-
能Web在线打开AutoCAD图形
-
测量距离
-
测量面积
-
测量角度
-
坐标标注
-
测量时能捕捉Web端CAD图形上面的坐标,提高准确度
-
测量时能对捕捉进行开关启用
-
测量时能启用正交模式
-
测量时能自定义右键菜单功能
-
能进行连续测量
-
测量结束后,能删除已测量的结果
效果
能Web在线打开AutoCAD图形
如果在Web网页端展示CAD图形(
测量距离
测量面积
测量角度
坐标标注
其他功能
在测量过程中,按Alt
键可开启关闭捕捉;按Ctrl
键可启用正交模式;按退格键
可删除上一个点;按ESC
键取消测量;按Enter
键结束测量; 按右键
弹出上下文菜单
代码实现
有需要的朋友可以在线体验下。上面的案例代码已开源。访问 (
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