依赖文件:js/myApp/measure.js
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
define(["esri/geometry/Point", "esri/geometry/Extent"], function (Point, Extent) { var measure = {}; measure.getMidPoint = function (p1, p2) { var theReturn = null; if (p1 && p1.type && p1.type == "point" && p2 && p2.type && p2.type == "point") { var x = (p1.x + p2.x) / 2; var y = (p1.y + p2.y) / 2; theReturn = new Point(x, y, p1.spatialReference); } return theReturn; }; measure.getAngle = function (p1, p2) { var theReturn = 0; if (p1 && p1.type && p1.type == "point" && p2 && p2.type && p2.type == "point") { var dx = (p1.x - p2.x); var dy = (p1.y - p2.y); var rad = Math.PI / 2; if (dx !== 0) { rad = Math.atan(dy / dx) * -1; } theReturn = measure.radiansToDegrees(rad); } return theReturn; }; measure.radiansToDegrees = function (radians) { return radians * 180 / Math.PI; }; measure.getRingExtent = function (polygon, ringIndex) { var ext = null; if (polygon && polygon.type && polygon.type == "polygon") { var minX = null; var maxX = null; var minY = null; var maxY = null; for (var j = 0; j < polygon.rings[ringIndex].length; j++) { x = polygon.rings[ringIndex][j][0]; y = polygon.rings[ringIndex][j][1]; if (minX) { minX = Math.min(minX, x); } else { minX = x; } if (minY) { minY = Math.min(minY, y); } else { minY = y; } if (maxX) { maxX = Math.max(maxX, x); } else { maxX = x; } if (maxY) { maxY = Math.max(maxY, y); } else { maxY = y; } } ext = new Extent(minX, minY, maxX, maxY, polygon.spatialReference); } return ext; }; measure.calculateLength = function (polyline, isGeographic) { var length = []; if (polyline && polyline.type && polyline.type == "polyline") { for (var i in polyline.paths) { var l = 0; for (var j = 0; j < polyline.paths[i].length - 1; j++) { var x1 = polyline.paths[i][j][0]; var y1 = polyline.paths[i][j][1]; var x2 = polyline.paths[i][j + 1][0]; var y2 = polyline.paths[i][j + 1][1]; var d; if (isGeographic) { d = measure.getGreatCircleDistance2(y1, x1, y2, x2); } else { d = measure.getDistanceXYXY(x1, y1, x2, y2); } l += d; } length.push(l); } } return length; }; measure.getDistanceXYXY = function (x1, y1, x2, y2) { return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); }; measure.getGreatCircleDistance2 = function (/*Number*/lat1, /*Number*/lon1, /*Number*/lat2, /*Number*/lon2) { try { var rlat1 = measure.degreesToRadians(lat1); var rlon1 = measure.degreesToRadians(lon1); var rlat2 = measure.degreesToRadians(lat2); var rlon2 = measure.degreesToRadians(lon2); var ellipse = { name: "WGS80", a: 6378.137 / 1.852, invf: 298.257223563 }; // Some util functions var mod = function (x, y) { return x - y * Math.floor(x / y); }; var modcrs = function (x) { return mod(x, 2 * Math.PI); }; var a = ellipse.a; var f = 1 / ellipse.invf; var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1; var x, sx, cx, sy, cy, y, sa, c2a, cz, e, c, d; var EPS = 0.00000000005; var faz, baz, s; var iter = 1; var MAXITER = 100; if ((rlat1 + rlat2 === 0.0) && (Math.abs(rlon1 - rlon2) == Math.PI)) { alert("Course and distance between antipodal points is undefined"); rlat1 = rlat1 + 0.00001; // allow algorithm to complete } if (rlat1 == rlat2 && (rlon1 == rlon2 || Math.abs(Math.abs(rlon1 - rlon2) - 2 * Math.PI) < EPS)) { //console.warn("Points 1 and 2 are identical- course undefined"); return 0; } r = 1 - f; tu1 = r * Math.tan(rlat1); tu2 = r * Math.tan(rlat2); cu1 = 1.0 / Math.sqrt(1.0 + tu1 * tu1); su1 = cu1 * tu1; cu2 = 1.0 / Math.sqrt(1.0 + tu2 * tu2); s1 = cu1 * cu2; b1 = s1 * tu2; f1 = b1 * tu1; x = rlon2 - rlon1; d = x + 1; // force one pass while ((Math.abs(d - x) > EPS) && (iter < MAXITER)) { iter = iter + 1; sx = Math.sin(x); cx = Math.cos(x); tu1 = cu2 * sx; tu2 = b1 - su1 * cu2 * cx; sy = Math.sqrt(tu1 * tu1 + tu2 * tu2); cy = s1 * cx + f1; y = measure.atan2(sy, cy); sa = s1 * sx / sy; c2a = 1 - sa * sa; cz = f1 + f1; if (c2a > 0.0) { cz = cy - cz / c2a; } e = cz * cz * 2.0 - 1.0; c = ((-3.0 * c2a + 4.0) * f + 4.0) * c2a * f / 16.0; d = x; x = ((e * cy * c + cz) * sy * c + y) * sa; x = (1.0 - c) * x * f + rlon2 - rlon1; } faz = modcrs(measure.atan2(tu1, tu2)); baz = modcrs(measure.atan2(cu1 * sx, b1 * cx - su1 * cu2) + Math.PI); x = Math.sqrt((1 / (r * r) - 1) * c2a + 1); x += 1; x = (x - 2.0) / x; c = 1.0 - x; c = (x * x / 4.0 + 1.0) / c; d = (0.375 * x * x - 1.0) * x; x = e * cy; s = ((((sy * sy * 4.0 - 3.0) * (1.0 - e - e) * cz * d / 6.0 - x) * d / 4.0 + cz) * sy * d + y) * c * a * r; var out = {}; out.d = s; out.dist = s * 1852; // to meters out.crs12 = faz; out.crs21 = baz; if (Math.abs(iter - MAXITER) < EPS) { alert("Algorithm did not converge"); } return out.dist; } catch (err) { console.error("Error calculating great circle distance", err); return 0; } }; measure.degreesToRadians = function (degrees) { return Math.PI * degrees / 180; }; measure.atan2 = function (y, x) { var out; if (x < 0) { out = Math.atan(y / x) + Math.PI; } if ((x > 0) && (y >= 0)) { out = Math.atan(y / x); } if ((x > 0) && (y < 0)) { out = Math.atan(y / x) + 2 * Math.PI; } if ((x === 0) && (y > 0)) { out = Math.PI / 2; } if ((x === 0) && (y < 0)) { out = 3 * Math.PI / 2; } if ((x === 0) && (y === 0)) { console.error("com.esri.solutions.jsviewer.util.atan2(0,0) undefined"); out = 0.0; } return out; }; measure.convertDistanceUnits = function (distance, fromUnits, toUnits) { if (fromUnits == "DecimalDegrees") { console.error("convertDistanceUnits: DecimalDegrees are not a distance unit"); return 0; } // Number of meters in a unit var cFactors = { "Feet": 0.3048, "Meters": 1, "Miles": 1609.344, "Kilometers": 1000, "Yards": 0.9144 }; if (!cFactors[fromUnits]) { console.error("convertDistanceUnits: Unknown units '" + fromUnits + "'"); return 0; } if (!cFactors[toUnits]) { console.error("convertDistanceUnits: Unknown units '" + toUnits + "'"); return 0; } // Convert to meters var dInMeters = distance * cFactors[fromUnits]; // Convert to output units var convDistance = dInMeters / cFactors[toUnits]; return convDistance; }; measure.convertAreaUnits = function (area, fromUnits, toUnits) { if (fromUnits == "DecimalDegrees") { console.error("convertDistanceUnits: DecimalDegrees are not an area unit"); return 0; } // Number of square meters in a unit var cFactors = { "Feet": 0.09290304, "Meters": 1, "Miles": 2589988.11, "Kilometers": 1000000, "Yards": 0.83612736, "Acres": 4046.85642, "Hectares": 10000 }; if (!cFactors[fromUnits]) { console.error("convertAreaUnits: Unknown units '" + fromUnits + "'"); return 0; } if (!cFactors[toUnits]) { console.error("convertAreaUnits: Unknown units '" + toUnits + "'"); return 0; } // Convert to meters var aInMeters = area * cFactors[fromUnits]; // Convert to output units var convArea = aInMeters / cFactors[toUnits]; return convArea; }; measure.significantDigits = function (number, numSignificantDigits) { var text = number + ""; //console.debug("significantDigits(" + text + ", " + numSignificantDigits + ")"); var output = ""; var bCounting = false; var count = 0; var bFoundDot = false; for (var i = 0; i < text.length; i++) { var char = text.substr(i, 1); bFoundDot = bFoundDot || char == "."; bCounting = bCounting || (char != "-" && char != "." && char != "0"); if (bCounting && char != ".") { count++; } if (count == numSignificantDigits) { if (char == ".") { break; } if (i == text.length - 1) { output += char; } else { var next = text.substr(i + 1, 1); if (next == ".") { next = text.substr(i + 2, 1); } var frag = char + "." + next; output += Math.round(parseFloat(frag)); } } else if (count > numSignificantDigits) { if (bFoundDot) { break; } else { output += 0; } } else { output += char; } } //console.debug(output); if (output.length > 0) { output = parseFloat(output); } return output; }; measure.round = function (number, numPlaces) { //console.debug("round(" + number + ", " + numPlaces + ")"); if (!numPlaces) { numPlaces = 0; } if (numPlaces > 5) { numPlaces = 5; } if (numPlaces < -5) { numPlaces = -5; } numPlaces = Math.round(numPlaces); //console.debug("rounding " + number + " to " + numPlaces + " places"); var factor = Math.pow(10, numPlaces); return Math.round(number * factor) / factor; }; return measure; });
代码示例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Label Points</title> <link rel="stylesheet" href="http://js.arcgis.com/3.9/js/dojo/dijit/themes/tundra/tundra.css" /> <link rel="stylesheet" href="http://js.arcgis.com/3.9/js/esri/css/esri.css" /> <style> html, body{ padding: 0; margin: 0; width: 100%; height: 100%; } </style> <script> var dojoConfig = { packages: [{ name: "myApp", location: location.pathname.replace(/\/[^/]+$/, "") + "/js/myApp" }] }; </script> <script src="http://js.arcgis.com/3.9/"></script> <script type="text/javascript"> var map, tb, markerSymbol, lineSymbol, fillSymbol; var bMapIsDegrees = true; var geometryService = null; var displayDistUnits = "Kilometers", displayDistUnitsAbbr = "km"; var displayAreaUnits = "Kilometers", displayAreaUnitsAbbr = "sq km"; var fontFace = "Arial"; require(["dojo/parser", "dijit/registry", "esri/geometry/Point", "esri/map", "esri/layers/ArcGISTiledMapServiceLayer", "esri/toolbars/draw", "esri/graphic", "esri/SpatialReference", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol", "esri/symbols/TextSymbol", "esri/Color", "esri/tasks/ProjectParameters", "esri/tasks/AreasAndLengthsParameters", "esri/tasks/GeometryService", "myApp/measure", "dojo/domReady!"], function (parser, registry, Point, Map, ArcGISTiledMapServiceLayer, Draw, Graphic, SpatialReference, SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol, TextSymbol, Color, ProjectParameters, AreasAndLengthsParameters, GeometryService, measure) { parser.parse(); map = new Map("mapDiv"); var agoServiceURL = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"; var agoLayer = new ArcGISTiledMapServiceLayer(agoServiceURL); map.addLayer(agoLayer); markerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 10, /**点符号**/ new SimpleLineSymbol(SimpleLineSymbol.STYLE_CIRCLE, new Color([0, 0, 255]), 2)); lineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASHDOT, new Color([255, 0, 0]), 2); fillSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([0, 0, 0]), 2), new Color([0, 0, 255, 0.5]) ); var geometryUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer"; geometryService = new GeometryService(geometryUrl); map.on("load", createToolbar); registry.forEach(function (d) { if (d.declaredClass === "dijit.form.Button") { d.on("click", activateTool); } }); function createToolbar(themap) { toolbar = new Draw(map); toolbar.on("draw-end", addToMap); } function activateTool() { var tool = null; switch (this.label) { case "点": tool = "POINT"; break; case "多点": tool = "MULTIPOINT"; break; case "线": tool = "POLYLINE"; break; case "徒手线": tool = "FREEHAND_POLYLINE"; break; case "多边形": tool = "POLYGON"; break; } toolbar.activate(Draw[tool]); map.hideZoomSlider(); } function addToMap(evt) { map.graphics.clear(); var geometry = evt.geometry; var symbol; // 将用户绘制的几何对象加入到地图中 switch (geometry.type) { case "point": symbol = markerSymbol; break; case "multipoint": symbol = markerSymbol; break; case "polyline": symbol = lineSymbol; break; case "polygon": symbol = fillSymbol; break; } var graphic = new Graphic(geometry, symbol); map.graphics.add(graphic); // 增加标注 addLabel(geometry); } function addLabel(geometry) { var x, y, g; switch (geometry.type) { case "point": x = measure.round(geometry.x, 2); y = measure.round(geometry.y, 2); g = getPointLabel(x + ", " + y, geometry); map.graphics.add(g); break; case "multipoint": for (var i in geometry.points) { var coords = geometry.points[i]; x = measure.round(coords[0], 2); y = measure.round(coords[1], 2); g = getPointLabel(x + ", " + y, new Point(coords, geometry.spatialReference)); map.graphics.add(g); } break; case "polyline": if (displayDistUnits) { var length = measure.calculateLength(geometry, bMapIsDegrees); for (var i in geometry.paths) { if (bMapIsDegrees) { mapUnits = "Meters"; } var len = measure.convertDistanceUnits(length[i], mapUnits, displayDistUnits); var text = measure.significantDigits(len, 4) + " " + displayDistUnitsAbbr; g = getPathLabel(text, geometry, i); map.graphics.add(g); } } break; case "polygon": if (displayDistUnits || displayAreaUnits) { var measureFunc = function (result) { for (var i in result.areas) { var perimeter = result.lengths[i]; var area = result.areas[i]; // 标注周长 if (displayDistUnits) { var peri = measure.convertDistanceUnits(perimeter, mapUnits, displayDistUnits); var text = measure.significantDigits(peri, 4) + " " + displayDistUnitsAbbr; map.graphics.add(getPathLabel(text, geometry, i)); } // 标注面积 if (displayAreaUnits) { var a = measure.convertAreaUnits(area, mapUnits, displayAreaUnits); text = measure.significantDigits(a, 6) + " " + displayAreaUnitsAbbr; map.graphics.add(getAreaLabel(text, geometry, i)); } } }; var polyGraphic = new Graphic(geometry); if (bMapIsDegrees) { mapUnits = "Meters"; var outSR = new SpatialReference({ wkid: 54034 //World_Cylindrical_Equal_Area }); var params = new ProjectParameters(); params.geometries = [geometry]; params.outSR = outSR; geometryService.project(params, function (geometries) { var areasAndLengthParams = new AreasAndLengthsParameters(); areasAndLengthParams.lengthUnit = GeometryService.UNIT_METER; areasAndLengthParams.areaUnit = GeometryService.UNIT_SQUARE_METERS; areasAndLengthParams.polygons = geometries; geometryService.areasAndLengths(areasAndLengthParams, measureFunc); }); } else { geometryService.areasAndLengths([geometry], measureFunc); } } break; } } function getFont() { var size = 18; var f = new esri.symbol.Font(size + "pt", esri.symbol.Font.STYLE_NORMAL, esri.symbol.Font.VARIANT_NORMAL, esri.symbol.Font.WEIGHT_BOLD, fontFace); return f; } function getPointLabel(text, point) { var sym = new TextSymbol(text, getFont(), new Color([0, 0, 0])); sym.setAlign(TextSymbol.ALIGN_START); var g = new Graphic(point, sym); return g; } function getPathLabel(text, polyline, pathIndex) { try { var sym = new TextSymbol(text, getFont(), new Color([0, 0, 0])); if (polyline.paths) { var path = polyline.paths[pathIndex]; } else { var path = polyline.rings[pathIndex]; } var idx = Math.floor(path.length / 2); var p1 = polyline.getPoint(pathIndex, idx - 1); var p2 = polyline.getPoint(pathIndex, idx); var point = measure.getMidPoint(p1, p2); var angle = measure.getAngle(p1, p2); sym.setAngle(angle); sym.setOffset(0, 2); var g = new Graphic(point, sym); return g; } catch (err) { console.error("创建标注出错:", err); } } function getAreaLabel(text, polygon, ringIndex) { try { var sym = new TextSymbol(text, getFont(), new Color([0, 0, 0])); var point = measure.getRingExtent(polygon, ringIndex).getCenter(); var g = new Graphic(point, sym); return g; } catch (err) { console.error("创建面积标注出错:", err); } } } ); </script> </head> <body class="tundra"> <button data-dojo-type="dijit/form/Button">点</button> <button data-dojo-type="dijit/form/Button">多点</button> <button data-dojo-type="dijit/form/Button">线</button> <button data-dojo-type="dijit/form/Button">徒手线</button> <button data-dojo-type="dijit/form/Button">多边形</button> <div id="mapDiv" style="width:900px; height:600px; border:1px solid #000;"></div> </body> </html>