<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>draw38_3.21</title>
<!--此代码进行到,要实现绘图界面。-->
<!--<link rel="stylesheet" href="https://js.arcgis.com/3.21/dijit/themes/claro/claro.css">-->
<!--<link rel="stylesheet" href="https://js.arcgis.com/3.21/esri/css/esri.css">-->
<!--<script src="https://js.arcgis.com/3.21/"></script>-->
<!--<script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>-->
<!--上下两个接口都行。-->
<link rel="stylesheet" href="https://js.arcgis.com/3.26/dijit/themes/nihilo/nihilo.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.26/esri/css/esri.css">
<script src="https://js.arcgis.com/3.26/"></script>
<style>
html, body, #map {
height: 100%; width: 100%; margin: 0; padding: 0;
}
#search {
z-index: 20;
height: 35px;
width: 300px;
position: absolute;
top: 10px;
left: 0;
right: 0;
margin: auto;
}
#drawOperations {
z-index: 20;
position: absolute;
top: 60px;
left: 5px;
color: #444;
width: 320px;
overflow: auto;
font-family: 仿宋体;
border: solid 1px #4A92E7;
border-radius: 4px;
background-color: #fff;
}
/*#info button {*/
/*width: 30px;*/
/*height:30px;*/
/*line-height:30px;*/
/*text-align: center;*/
/*background-color: #fff;*/
/*padding: 2px;*/
/*margin: 4px;*/
/*cursor: pointer;*/
/*border-radius: 3px;*/
/*border: 1px solid*/
/*}*/
/*#info button:hover {*/
/*border: 1px solid #1e90ff;*/
/*}*/
#drawOperations img{
width:40px;
margin:4px;
}
#drawOperations div{
padding:4px 4px 0px 4px;
}
</style>
<!--导入该js才可以添加多行文本。-->
<script src="js/esri.symbol.MultiLineTextSymbol.js"></script>
<script>
require([
"esri/config",
"esri/tasks/GeometryService",
"esri/tasks/LengthsParameters",
"esri/tasks/AreasAndLengthsParameters",
"esri/symbols/TextSymbol", "esri/Color", "esri/symbols/Font",
"esri/map",
"esri/layers/ArcGISTiledMapServiceLayer",
"esri/layers/ArcGISDynamicMapServiceLayer",
"dojo/_base/connect",
"esri/dijit/BasemapToggle",
"esri/toolbars/draw",
"esri/geometry/Point", "esri/geometry/Polyline", "esri/geometry/Polygon",
"esri/dijit/Search",
"dijit/registry",
"esri/dijit/Scalebar",
"esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/symbols/PictureMarkerSymbol",
"esri/symbols/CartographicLineSymbol",
"esri/symbols/PictureFillSymbol",
"esri/geometry/Extent",
"esri/SpatialReference",
"esri/geometry/mathUtils",
"esri/geometry/ScreenPoint",
"esri/toolbars/edit",
"dijit/Menu",
"dijit/MenuItem",
"dijit/MenuSeparator",
"esri/graphic",
"esri/layers/GraphicsLayer",
"esri/dijit/Popup",
"esri/dijit/PopupTemplate",
"esri/InfoTemplate",
"dojo/dom-construct",
"dojo/dom",
"dojo/on",
"dojo/domReady!"
], function(
esriConfig, GeometryService, LengthsParameters, AreasAndLengthsParameters,
TextSymbol, Color, Font,
Map, ArcGISTiledMapServiceLayer, ArcGISDynamicMapServiceLayer,
connect, BasemapToggle, Draw, Point, Polyline, Polygon, Search, registry, Scalebar,
SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol,
PictureMarkerSymbol, CartographicLineSymbol, PictureFillSymbol,
Extent, SpatialReference, mathUtils, ScreenPoint, Edit, Menu, MenuItem,
MenuSeparator,
Graphic, GraphicsLayer, Popup, PopupTemplate, InfoTemplate,
domConstruct,dom, on
) {
//量算
function doMeasure(geometry) {
let symbol;
measureGeometry = geometry;
draw.deactivate();
switch (geometry.type) {
case "point":
symbol = new SimpleMarkerSymbol();
break;
case "polyline":
symbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new dojo.Color([0, 0, 0]), 5);
break;
case "polygon":
symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NONE, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_DASHDOT, new dojo.Color([255, 0, 0]), 2), new dojo.Color([255, 255, 0, 0.25]));
break;
}
//设置样式
const graphic = new Graphic(geometry, symbol);
map.infoWindow.hide();
graphicsLayer.add(graphic);
//进行投影转换,完成后调用projectComplete
MeasureGeometry(geometry);
}
//投影转换完成后调用方法
function MeasureGeometry(geometry) {
// 如果为点类型,就测量经纬度。
if(geometry.type == "point"){
outputLongitudeLatitude(geometry.x, geometry.y);
}
// 如果为线类型就进行lengths距离测算
else if (geometry.type == "polyline") {
const lengthParams = new LengthsParameters();
lengthParams.polylines = [geometry];
lengthParams.lengthUnit = GeometryService.UNIT_METER;
lengthParams.geodesic = true;
lengthParams.polylines[0].spatialReference = new SpatialReference(4326);
geometryService.lengths(lengthParams);
dojo.connect(geometryService, "onLengthsComplete", outputDistance);
}
// 如果为面类型,需要先进行simplify操作再进行面积测算
else if (geometry.type == "polygon") {
const areasAndLengthParams = new AreasAndLengthsParameters();
areasAndLengthParams.lengthUnit = GeometryService.UNIT_METER;
areasAndLengthParams.areaUnit = GeometryService.UNIT_SQUARE_METERS;
this.outSR = new SpatialReference({wkid: 102113});
geometryService.project([geometry], this.outSR, function (geometry) {
geometryService.simplify(geometry, function (simplifiedGeometries) {
// 此处把各特征点的经纬度,转换成了坐标系中的实际坐标,
// 单位即上边规定的单位。
// console.log('simplifiedGeometries:', simplifiedGeometries);
areasAndLengthParams.polygons = simplifiedGeometries;
areasAndLengthParams.polygons[0].spatialReference = new SpatialReference(102113);
geometryService.areasAndLengths(areasAndLengthParams);
});
});
dojo.connect(geometryService, "onAreasAndLengthsComplete", outputAreaAndLength);
}
}
// 显示经纬度。
function outputLongitudeLatitude(lon, lat) {
const curPos = new Point(lon, lat, map.spatialReference);
let textSymbol = new TextSymbol(
"经度:" + lon.toFixed(3) + "\n纬度:" + lat.toFixed(3)
).setColor(new Color([182,0,0])).setFont(
new Font("14pt").setWeight(Font.WEIGHT_BOLD)
).setHorizontalAlignment("left").setVerticalAlignment('middle');
graphicsLayer.add(new Graphic(curPos, textSymbol));
}
//显示测量距离
function outputDistance(result) {
const curX = measureGeometry.paths[0][measureGeometry.paths[0].length - 1][0];
const curY = measureGeometry.paths[0][measureGeometry.paths[0].length - 1][1];
const curPos = new Point(curX, curY, map.spatialReference);
let len = parseInt(result.lengths[0]);
let textSymbol;
if(len <= 10000){
textSymbol = new TextSymbol(
"长度:" + len + "米"
);
}
else{
textSymbol = new TextSymbol(
"长度:" + len / 1000 + "千米"
);
}
let textSymbol2 = textSymbol.setColor(new Color([182,0,0])).setFont(
new Font("14pt").setWeight(Font.WEIGHT_BOLD)
).setHorizontalAlignment("left").setVerticalAlignment('middle');
graphicsLayer.add(new Graphic(curPos, textSymbol2));
}
// 显示测量面积,周长。
function outputAreaAndLength(result) {
const center = measureGeometry.getCentroid(); //获取查询区域的中心点
let area = parseInt(result.areas[0]);
let len = parseInt(result.lengths[0]);
let area2, len2;
if(len > 10000){
len2 = len / 1000
}
if(area > 1000000){
area2 = (area / 1000000).toFixed(3);
}
let textSymbol;
if(area2 && len2){
textSymbol = new TextSymbol(
"面积:" + area2 + "平方千米\n" +
"周长:" + len2 + "千米"
);
}
else if(area2){
textSymbol = new TextSymbol(
"面积:" + area2 + "平方千米\n" +
"周长:" + len + "米"
);
}
else if(len2){
textSymbol = new TextSymbol(
"面积:" + area + "平方米\n" +
"周长:" + len2 + "千米"
);
}
else{
textSymbol = new TextSymbol(
"面积:" + area + "平方米\n" +
"周长:" + len + "米"
);
}
let textSymbol2 = textSymbol.setColor(new Color([182,0,0])).setFont(
new Font("14pt").setWeight(Font.WEIGHT_BOLD)
).setHorizontalAlignment("left").setVerticalAlignment('middle');
graphicsLayer.add(new Graphic(center, textSymbol2));
}
// 添加图形
function addGraphic(event) {
// 使绘图工具无效。
// draw.deactivate();
// 启用地图导航.
map.enableMapNavigation();
let symbol;
if ( event.geometry.type === "point" || event.geometry.type === "multipoint") {
symbol = markerSymbol;
// symbol = textSymbol;
}
else if ( event.geometry.type === "line" || event.geometry.type === "polyline") {
symbol = lineSymbol;
}
else {
symbol = fillSymbol;
}
const measureOrNot = document.getElementById("measure").checked;
// 绘制并测量
if(measureOrNot){
// 后边的代码,不能处理extent类型的面积长度测量,
// 所以此处需特殊处理。
// 即,把extent类型的数据结构,重构成polygon类型的数据结构,即可。
if(event.geometry.type == "extent"){
let center = event.geometry.getCenter();
// console.log('center:', center);
const polygonJson = {
"rings": [[
[event.geometry.xmin, event.geometry.ymax],
[event.geometry.xmax, event.geometry.ymax],
[event.geometry.xmax, event.geometry.ymin],
[event.geometry.xmin, event.geometry.ymin],
[event.geometry.xmin, event.geometry.ymax]
]],
"spatialReference": {"wkid": 4326},
"cache": {
"geoShape": "polygon",
"_centroid": center,
"_extent": {
"xmin": event.geometry.xmin,
"ymin": event.geometry.ymin,
"xmax": event.geometry.xmax,
"ymax": event.geometry.ymax,
"spatialReference": event.geometry.spatialReference
},
"_partwise": null,
}
};
const polygon = new Polygon(polygonJson);
polygon.setCacheValue("geoShape", polygon.type);
doMeasure(polygon);
}
else {
event.geometry.setCacheValue("geoShape", event.geometry.type);
doMeasure(event.geometry);
}
}
// 只绘制不测量
else {
event.geometry.setCacheValue("geoShape", event.geometry.type);
graphicsLayer.add(new Graphic(event.geometry, symbol));
}
}
//初始化工具栏
function initToolbar() {
// 创建绘图工具。
// showTooltips,默认为true。
draw = new Draw(map, { showTooltips: true });
// 绘图工具监听画完事件。
// console.log('graphicsLayer:', graphicsLayer);
draw.on("draw-end", addGraphic);
// undo_redo_arr,用于存储 操作撤消恢复事件时 的图形对象。
undo_redo_arr = [];
// clear_arr,用于存储清除操作,清除的所有图形对象。
let clear_arr = [];
let len_undo_redo, len_clear, len_graphics;
let textAdd;
// 绘图工具监听 绘制选项。
on(dom.byId("drawOptions"), "click", function(event){
// 没有事件的元素。
if (event.target.id === "drawOptions" ) {
return;
}
const tool = event.target.id.toLowerCase();
// 禁用地图导航。
map.disableMapNavigation();
// 绘图工具激活相应的绘图功能。
draw.activate(tool);
if(textAdd){
textAdd.remove();
}
});
// 监听撤消事件。
on(dom.byId("undo"), "click", function(event) {
// 每单击一次按钮,就更新一遍各个数组的长度。
len_clear = clear_arr.length;
len_graphics = graphicsLayer.graphics.length;
// 撤消 清除事件。
if(len_graphics == 0 && len_clear != 0){
// 前提:视图中没图形,清除数组有图形,才能撤消清除操作。
for(let i=0;i<len_clear;i++){
graphicsLayer.add(clear_arr.pop());
}
}
// 撤消单个图形(多点绘制的是多个点,撤消的话一同撤消。)
else if(len_graphics != 0){
// 前提:视图中有图形,才能撤消绘制的单个图形。
let graphic_pop = graphicsLayer.graphics.pop();
// remove的两个参数,第一个是要移除的图形,第二个是该图形对应的html元素节点。
graphicsLayer.remove(graphic_pop, graphic_pop.getNode());
undo_redo_arr.push(graphic_pop);
// console.log('undo_redo_arr:', undo_redo_arr);
}
});
// 监听恢复事件。
on(dom.byId("redo"), "click", function (event) {
// 每单击一次恢复按钮,就更新一遍undo_redo_arr数组的长度。
len_undo_redo = undo_redo_arr.length;
// 恢复,是相对于撤消而言的。即,只能恢复撤消的图形。
if(len_undo_redo != 0){
// 前提是 undo_redo_arr数组不为空,才有图形可恢复。
graphicsLayer.add(undo_redo_arr.pop());
}
});
// 监听清除事件。
on(dom.byId("clearAll"), "click", function (event) {
// 清除视图中所有图形 事件。
len_graphics = graphicsLayer.graphics.length;
for(let i=0;i<len_graphics;i++){
let graphic_pop = graphicsLayer.graphics.pop();
clear_arr.push(graphicsLayer.remove(graphic_pop, graphic_pop.getNode()));
}
});
// 监听停止标绘事件。
on(dom.byId("stop"), "click", function (event) {
draw.deactivate();
if(textAdd){
textAdd.remove();
}
});
// 监听添加文字事件。
on(dom.byId("text"), "click", function (event) {
// console.log('text');
draw.deactivate();
textAdd = map.on("click", function(event) {
// console.log('event:', event);
graphicsLayer.add(
new Graphic(event.mapPoint, new TextSymbol("Multi-Line \n Text"), {})
);
});
});
}
//创建右键菜单
function createGraphicsMenu(){
ctxMenuForGraphics = new Menu({});
// 在graphicsLayer图层里的元素,重叠时,也有上下之分。
// 即,重叠的元素,哪个在上边,哪个在下边。
//当鼠标在graphicsLayer图层的图形上方时绑定该图形的点击事件
let selected;
graphicsLayer.on("mouse-over", function(event) {
selected = event.graphic;
// 右键菜单绑定dom节点。不绑定则“删除”标签不弹出。
// event.graphic.getDojoShape().getNode(), 指的就是图形对应的html方式的表达。
ctxMenuForGraphics.bindDomNode(event.graphic.getNode());
});
//当鼠标移出graphicsLayer图层的图形上方时取消绑定该图形的点击事件
graphicsLayer.on("mouse-out", function(event) {
ctxMenuForGraphics.unBindDomNode(event.graphic.getNode());
});
ctxMenuForGraphics.addChild(new MenuItem({
label: "删除",
// 此处的onClick是在“删除”标签上的onClick。
onClick: function () {
undo_redo_arr.push(graphicsLayer.remove(selected));
}
}));
}
// 主函数。
function main() {
// 创建popup弹出层
const popup = new Popup(null, domConstruct.create("div"));
// 地图
map = new Map("map", {
slider:false,
center: [121.47003707885744, 31.24853148977224],
zoom: 7,
infoWindow: popup, // 信息窗口,弹窗。
extent: new Extent(
-122.68,45.53,-122.45,45.60,
new SpatialReference({wkid:4326 })
) // 猜测:显示的区域。
});
// 添加地图图层
const mapServiceURL = "https://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer";
map.addLayer(new ArcGISTiledMapServiceLayer(mapServiceURL));
//初始化比例尺
const scalebar = new Scalebar({
map: map,
attachTo: "bottom-left",
scalebarUnit: "dual",
});
//显示比例尺
scalebar.show();
// 创建图层
graphicsLayer = new GraphicsLayer({id: "draw"});
map.addLayer(graphicsLayer);
// 给地图添加事件。
map.on("load", initToolbar);
// 创建右键菜单。
createGraphicsMenu();
//启动右键菜单
ctxMenuForGraphics.startup();
//点击地图响应
map.on("click", function(event) {
//点击空白处隐藏popup
if(event.graphic == undefined){
popup.hide();
}
// mapPoint = event.mapPoint;
});
// 搜索框
const search = new Search({
map: map,
graphicsLayer: graphicsLayer,
}, "search");
search.startup();
// 弹出框信息
graphicsLayer.on("click", function(event) {
let details;
if(event.graphic.geometry.getCacheValue("geoShape") == "polygon"){
// const details = '图形: ' + event.graphic.geometry.cache.geoShape + '<br>';
details = '图形类型: ' + event.graphic.geometry.getCacheValue("geoShape") + '<br>' +
'图形长度:' + event.graphic.geometry.getCacheValue("长度") + '<br>' +
'图形面积:' + event.graphic.geometry.getCacheValue("面积");
}
else if(event.graphic.geometry.getCacheValue("geoShape") == "polyline"){
details = '图形类型: ' + event.graphic.geometry.getCacheValue("geoShape") + '<br>' +
'图形长度:' + event.graphic.geometry.getCacheValue("长度");
}
else if(event.graphic.geometry.getCacheValue("geoShape") == "point"){
details = '图形类型: ' + event.graphic.geometry.getCacheValue("geoShape") + '<br>' +
'经度:' + event.graphic.geometry.getCacheValue("经度") + '<br>' +
'纬度:' + event.graphic.geometry.getCacheValue("纬度");
}
popup.setTitle('图形信息'); // 弹窗标题
popup.setContent(details); // 弹窗内容
popup.show(event.mapPoint); // 弹窗展示及其位置
});
// textSymbol = new TextSymbol("Hello World").setColor(
// new Color([128,0,0])).setAlign(Font.ALIGN_START).setAngle(45).setFont(
// new Font("12pt").setWeight(Font.WEIGHT_BOLD)) ;
//用来展示点的symbol
//链式调用更有性能优势。
markerSymbol = new SimpleMarkerSymbol().setSize(10).setColor(
new Color("#00FFFF")).setStyle(SimpleMarkerSymbol.STYLE_SQUARE);
// 用来展示线的symbol
lineSymbol = new CartographicLineSymbol(
CartographicLineSymbol.STYLE_SOLID, // 线的样式,实线。
new Color([255, 0, 0]), 4, // 颜色 线宽
CartographicLineSymbol.CAP_ROUND, // 两头圆角
CartographicLineSymbol.JOIN_MITER, // 连接处尖角
5 // 最大斜接长度。斜接长度指的是在两条线交汇处内角和外角之间的距离。
// 如果斜接长度超过 miterLimit 的值,边角会以 lineJoin 的 "bevel" 类型来显示。
);
//用来展示面的symbol
fillSymbol = new SimpleFillSymbol(
SimpleFillSymbol.STYLE_SOLID, // 实心
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_SOLID, // 实线
new Color('#fff'), // 边/线的颜色
1 // 边的宽度
),
new Color([0, 255, 0, 0.2]) // 填充的颜色及透明度
);
// console.log('markerSymbol:', markerSymbol);
// console.log('lineSymbol:', lineSymbol);
// console.log('fillSymbol:', fillSymbol);
}
let map, graphicsLayer, draw, ctxMenuForGraphics;
let measureGeometry, undo_redo_arr;
let textSymbol, markerSymbol,lineSymbol,fillSymbol;
const geometryServiceUrl="http://10.254.11.41:6080/arcgis/rest/services/Utilities/Geometry/GeometryServer";
esriConfig.defaults.io.proxyUrl = "/proxy/";
esriConfig.defaults.io.alwaysUseProxy = false;
const geometryService = new GeometryService(geometryServiceUrl);
// esriConfig.defaults.geometryService = new GeometryService(geometryServiceUrl);
main();
});
</script>
</head>
<body class="claro" style="font-size: 0.75em;">
<!--绘图菜单。-->
<div id="drawOperations">
<div align="left">绘图选项</div>
<div id="drawOptions">
<img id="Point" src="../images/multipoint.png">
<img id="Line" src="../images/line.png">
<img id="Polyline" src="../images/polyline.png">
<img id="FreehandPolyline" src="../images/freehand_polyline.png">
<img id="Triangle" src="../images/triangel.png">
<img id="Extent" src="../images/rectangle.png">
<img id="Circle" src="../images/circle.png">
<img id="Ellipse" src="../images/ellipse.png">
<img id="Polygon" src="../images/polygon.png">
<img id="FreehandPolygon" src="../images/freehand_ploygon.png">
</div>
<div>添加文字</div>
<img id="text" src="../images/text.png">
<div><input id="measure" type="checkbox">绘制并测量</div>
<button id="stop">停止标绘</button>
<button id="undo">撤消</button>
<button id="redo">恢复</button>
<button id="clearAll" >清除</button>
</div>
<!--搜索框。-->
<div id="search"></div>
<!--地图显示区。-->
<div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
</div>
</body>
</html>
图上标绘及测量.html
最新推荐文章于 2024-08-25 09:05:23 发布