CAD Now it has been widely used in various fields and greatly improved the work efficiency of engineers and technicians . On the desktop side ,AutoCAD Measuring tools are already very powerful ; And then in Web End , How accurate 、 Fast pair CAD The picture is Web For measurement ?
function
can Web Open online AutoCAD graphics
Measuring distance
Measure the area
Measure the angle
Coordinate notation
It can capture Web End CAD The coordinates above the graph , Improve accuracy
The snap can be switched on and off during measurement
Quadrature mode can be enabled during measurement
Right click menu function can be customized during measurement
Capable of continuous measurement
After measurement , It can delete the measured results
effect
can Web Open online AutoCAD graphics
If in Web Web side display CAD graphics ( Weijie map cloud drawing management platform https://vjmap.com/app/cloud), This has been mentioned in the previous blog post , I won't repeat it here , Friends in need can download the project source code for research .
Measuring distance

Measure the area

Measure the angle

Coordinate notation

Other features
In the course of measurement , Press Alt Key to turn capture on and off ; Press Ctrl Key to enable orthographic mode ; Press backspace You can delete the previous point ; Press ESC Key to cancel the measurement ; Press Enter Key to end the measurement ; Press Right click Pop up context menu

Code implementation
1 import vjmap, { Map } from 'vjmap'
2 import { sleep } from '~/utils/ui';
3 import { getMapSnapPoints } from './snap';
4 let snapObj: any; // Set the snapping entity
5 let curMeasureCmd: string; // Current measurement command
6 export async function runMeasureCmd(map: Map, cmd: string) {
7 curMeasureCmd = cmd;
8 if (cmd != "measureCancel") {
9 // End the current measurement first
10 await measureCancel(map);
11 if (!snapObj) {
12 // Get snap points on the map
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 // Finish drawing
37 const measureCancel = async (map: Map)=> {
38 // Send cancel key continuously , Cancels the current drawing for the first time , Exit the measurement for the second time
39 map.fire("keyup", {keyCode:27});
40 await sleep(100);
41 map.fire("keyup", {keyCode:27});
42 await sleep(100);
43 map.setIsInteracting(false); // There is no interaction
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 // If it's empty , Delete popup
65 if (popup) {
66 popup.setLngLat([0,0]); // Cancel trackPointer
67 popup.remove();
68 popup = null;
69 }
70 }
71
72 }
73 // Measure the distance cycle , Until you press ESC Key cancel , Otherwise, after measuring one line , Continue to measure the next
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 // Measuring distance
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 // The data item to be captured is later , Passing attribute features assignment
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 = `【 Measuring distance 】 Current coordinates :<span style="color: #ff0000"> ${co.x.toFixed(2)}, ${co.y.toFixed(2)}</span>`;
94 if (e.feature.coordinates.length == 1) {
95 html += "<br/> Please specify the coordinate position of the first point to be measured "
96 } else {
97 let len = e.feature.coordinates.length;
98 html += `<br/> Press Alt Keying snap ; Ctrl Key to enable orthogonality ; Backspace key deletes the previous point `
99 html += `<br/> A little distance away : <span style="color: #ff0000">${getDist(map, [e.feature.coordinates[len - 2], e.feature.coordinates[len -1]])}</span>`
100 html += `; Current total distance : <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: ' confirm ',
112 onClick: () => {
113 // Send to map Enter Key message to cancel , Analog press Enter key
114 map.fire("keyup", {keyCode:13})
115 setPopupText("", map);
116 }
117 },
118 {
119 label: ' Cancel ',
120 onClick: () => {
121 // Send to map ESC Key message to cancel , Analog press ESC key
122 map.fire("keyup", {keyCode:27})
123 setPopupText("", map);
124 }
125 },{
126 label: ' Delete the previous point ',
127 onClick: () => {
128 // Send a backspace key to the map Backspace Message to delete the previous point , Analog press Backspace key
129 map.fire("keyup", {keyCode:8})
130 }
131 },{
132 label: ' End ranging ',
133 onClick: () => {
134 // Send to map ESC Key message to cancel , Analog press ESC key
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 // If you haven't drawn , If you cancel , It's over
150 };// Cancel operation
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 // Add a point to the line and a measured result value
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 Direction pixel offset
175 style:{ // Custom 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 // Add a dot to the first dot marker Used to delete
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); // Delete drawn lines
204 markerTexts.forEach((m: any) => m.remove());
205 markerTexts = [];
206
207 // More points , Send a backspace key to the map Backspace Message to delete the previous point , Analog press Backspace key
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 // Add coordinates to the capture array .
221 addSnapCoordinates(snapObj, coordinates);
222 }
223 // Get the distance value
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 // Add snap points
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 // Measure the area
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 // The data item to be captured is later , Passing attribute features assignment
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 = `【 Measure the area 】 Current coordinates :<span style="color: #ff0000"> ${co.x.toFixed(2)}, ${co.y.toFixed(2)}</span>`;
261 if (e.feature.coordinates[0].length == 1) {
262 html += "<br/> Please specify the coordinate position of the first point to be measured "
263 } else {
264 html += `<br/> Press Alt Keying snap ; Ctrl Key to enable orthogonality ; Backspace key deletes the previous point `
265 html += `<br/> Current area : <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: ' confirm ',
277 onClick: () => {
278 // Send to map Enter Key message to cancel , Analog press Enter key
279 map.fire("keyup", {keyCode:13})
280 setPopupText("", map);
281 }
282 },
283 {
284 label: ' Cancel ',
285 onClick: () => {
286 // Send to map ESC Key message to cancel , Analog press ESC key
287 map.fire("keyup", {keyCode:27})
288 setPopupText("", map);
289 }
290 },{
291 label: ' Delete the previous point ',
292 onClick: () => {
293 // Send a backspace key to the map Backspace Message to delete the previous point , Analog press Backspace key
294 map.fire("keyup", {keyCode:8})
295 }
296 },{
297 label: ' End measuring area ',
298 onClick: () => {
299 // Send to map ESC Key message to cancel , Analog press ESC key
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 // If you haven't drawn , If you cancel , It's over
316 };// Cancel operation
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 // Measure the area cycle , Until you press ESC Key cancel , Otherwise, after measuring one line , Continue to measure the next
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 // Add a result of the measurement
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 Direction pixel offset
350 style:{ // Custom 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 // Add a dot to the first dot marker Used to delete
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); // Delete drawn lines
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 // Add coordinates to the capture array .
392 addSnapCoordinates(snapObj, coordinates);
393 }
394 // Get the area value
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 // Measure the angle
411 const measureAngle = async (map: Map, snapObj: any)=> {
412 let isDrawing = false;
413 let line = await vjmap.Draw.actionDrawLineSting(map, {
414 pointCount: 3,// Just three points , After drawing the three points , Automatic end
415 api: {
416 getSnapFeatures: snapObj // The data item to be captured is later , Passing attribute features assignment
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 = `【 Measure the angle 】 Current coordinates :<span style="color: #ff0000"> ${co.x.toFixed(2)}, ${co.y.toFixed(2)}</span>`;
423 if (e.feature.coordinates.length == 1) {
424 html += "<br/> Please specify the coordinate position of the first point to be measured "
425 } else {
426 let len = e.feature.coordinates.length;
427 html += `<br/> Press Alt Keying snap ; Ctrl Key to enable orthogonality ; Backspace key deletes the previous point `
428 html += `<br/> Current angle : <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: ' confirm ',
440 onClick: () => {
441 // Send to map Enter Key message to cancel , Analog press Enter key
442 map.fire("keyup", {keyCode:13})
443 setPopupText("", map);
444 }
445 },
446 {
447 label: ' Cancel ',
448 onClick: () => {
449 // Send to map ESC Key message to cancel , Analog press ESC key
450 map.fire("keyup", {keyCode:27})
451 setPopupText("", map);
452 }
453 },{
454 label: ' Delete the previous point ',
455 onClick: () => {
456 // Send a backspace key to the map Backspace Message to delete the previous point , Analog press Backspace key
457 map.fire("keyup", {keyCode:8})
458 }
459 },{
460 label: ' End angle measurement ',
461 onClick: () => {
462 // Send to map ESC Key message to cancel , Analog press ESC key
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 // If you haven't drawn , If you cancel , It's over
478 };// Cancel operation
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 // Measure the angle cycle , Until you press ESC Key cancel , Otherwise, after measuring one line , Continue to measure the next
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 // Add a result of the measurement
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 // Draw annotation arcs
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)];// Take the midpoint
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 Direction pixel offset
536 style:{ // Custom 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 // Add a dot to the first dot marker Used to delete
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); // Delete drawn lines
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 // Add coordinates to the capture array .
578 addSnapCoordinates(snapObj, coordinates);
579 }
580 // Get the angle value
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);// The angle of arc
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 // Measuring coordinates
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 // The data item to be captured is later , Passing attribute features assignment
619 },
620 updatecoordinate: (e: any) => {
621 if (!e.lnglat) return;
622 isDrawing = true;
623 const co = map.fromLngLat(e.lnglat);
624 let html = `【 Measuring coordinates 】 Current coordinates :<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: ' confirm ',
635 onClick: () => {
636 // Send to map Enter Key message to cancel , Analog press Enter key
637 map.fire("keyup", {keyCode:13})
638 setPopupText("", map);
639 }
640 },
641 {
642 label: ' Cancel ',
643 onClick: () => {
644 // Send to map ESC Key message to cancel , Analog press ESC key
645 map.fire("keyup", {keyCode:27})
646 setPopupText("", map);
647 }
648 },
649 {
650 label: ' End coordinate measurement ',
651 onClick: () => {
652 // Send to map ESC Key message to cancel , Analog press ESC key
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 };// Cancel operation
669 }
670
671 addMarkersToCoord(map, point.features[0].geometry.coordinates);
672 return {
673 point
674 };
675 }
676
677 // Measuring coordinate cycle , Until you press ESC Key cancel
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 // Add a point and a measured result
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 // Add a dot to the first dot marker Used to delete
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 // Leader marks
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
Friends in need can experience it online . The above case code is open source . visit ( Weijie map cloud drawing management platform https://vjmap.com/app/cloud) , Click on Download the source code of this case that will do .
CAD Figure Online Web Measurement tool code implementation ( Measuring distance 、 area 、 Angle, etc. ) More articles about
- CAD Analysis and implementation of the display technology of mutual superposition between map and Internet map web page end
Demand analysis In the previous related blog posts, it was introduced that if Web Web side display CAD graphics ( Weijie map cloud drawing management platform https://vjmap.com/app/cloud), When some CAD When the drawing has actual geographic coordinate position , Such as topographic map , ...
- How to be in Web The front-end implementation CAD Figure technical sharing of text full-text search function
present situation stay CAD In the process of looking at pictures, we often need to use the function of finding words , stay AutoCAD When the software looks for a text , You can enter the command... By opening the lower left corner find, Enter the text you want to find , Then set the search range , You can search the text you need to query . But in We ...
- Meitu Xiu Xiu web Develop a picture editor
Meitu Xiu Xiu web Development platform http://open.web.meitu.com/wiki/ 1. Environment configuration 1.1. Set up crossdomain.xml download crossdomain.xml file , Unpack it c ...
- SSH WebShell: SSH On-line WEB Manager installation tutorial - VPS Manage encyclopedia
SSH WebShell: SSH On-line WEB Manager installation tutorial - VPS Manage encyclopedia SSH WebShell: SSH On-line WEB Manager installation tutorial Original site [ be based on A signature - Non commercial use - Share in the same way 2.5 Association ...
- On-line web Editor
Real online editing web Editor Recently, we are researching and developing an online web Editor Architecture , This is a really stupid web Editor , It can be edited when browsing the page normally , After testing , It is very easy to use and convenient for general web pages , Easier to operate . ...
- Real online editing web Editor
Recently, we are researching and developing an online web Editor Architecture , This is a really stupid web Editor , It can be edited when browsing the page normally , After testing , It is very easy to use and convenient for general web pages , Easier to operate . General online web Although the editor provides ...
- On-line WEB Development Editor ,edt.df5d.com
On-line WEB Development Editor ,http://edt.df5d.com Download from the local server : https://pan.baidu.com/s/11SlcoU_D-KbzGFbs-_9Dpg The local disk can be loaded , Can also be ...
- QQ,MSN,Skype Online customer service code
QQ,MSN,Skype Online customer service code In website construction , In order to better implement the marketing of the website , use QQ,MSN And so on , So that customers can quickly and easily contact us . ad locum , Provide QQ,MSN Online customer service code to share : 1.Q ...
- The online operation HTML Coder
The online operation HTML Coder ( Two ) And the one in front ( One ) Be the same in essentials while differing in minor points , The key part is JS Code , This time it's all about the runner JS Put the functions together . The following is a HTML Code : <!DOCTYPE html PUBLIC "- ...
- be based on jquery Create the right side of the page automatically shrink floating online customer service code
be based on jquery Create the right side of the page automatically shrinks and floats online QQ Customer service code , A popular one at present QQ On-line jquery Special effects code , The code also contains IE6 Next PNG The special effect of picture transparency , If you want to study IE6 Next PNG Transparent students can also download research ...
Random recommendation
- zTree Develop a drop-down tree
lately , Because work requires a tree like drop-down box component , There are generally two ways to achieve this after checking the data . firstly , Is the use of zTree Realization : second , Is the use of easyUI Realization . Because the front end of the company is not using easyUI The design of the , So here I choose zTree ...
- mysql Server configuration
mysql Configuration file for /etc/mysql/my.cnf Found the following configuration # Instead of skip-networking the default is now to listen only ...
- PDF Mending 0.4.2.1023 The beta user manual is released
because PDF Patch D adds a lot of functions in the new version , The interface has also been redesigned , therefore , The user manual needs to be greatly modified to match the software . at present , The user manual has been partially written , However, the introduction of new functions and the screenshot of the new interface have not been completed , Yes 2/3 Within the ...
- 15 The latest cool effect jQuery/CSS3 Special effects
I haven't come to blog Garden for a long time , Share today 15 The latest cool effect jQuery/CSS3 Special effects , Nonsense , Let's see . 1.3D Picture up and down flip switch Based on a jQuery+CSS3 Realized 3D Picture up and down flip switch effect , the ...
- WatiN Frame learning 2 —— How to deal with pop ups
With IE For example ,WatiN Handling pop ups : IE ie = new IE("string"); // Open the specified web page ie.Button(Find.ById("string&q ...
- 【 Re posting 】error C2296: “^”: illegal , The left operand contains “double” type
Want to achieve , Written C++ The procedure is double x; x=2^3; As a result, the program always makes such errors :error C2296: “^”: illegal , The left operand contains “double” type It was discovered later that the operator “^”, stay C++ ...
- Java Interface automation test TestNG Test report ExtentReports Application ( 3、 ... and )
pom.xml Import package <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...
- About Django part
1 install perform pip Can be installed pip install Django 2 Open project 3 The location of the new project : 4 Open port command python manage.py runserver 0.0.0.0:9 ...
- dubbo There are three modes of operation of
1.Tomcat Start in the container pom.xml In file <build> <resources> <resource> <directory>src/main ...
- 1-Python3 From introduction to practice — Basic grammar
Python From the entry to the actual series -- Catalog Coding format By default ,Python 3 Source file to UTF-8 code , All strings are unicode character string # -*- coding=utf-8 -*- It's fine too ...








