需要用到的类
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/Graphic",
"esri/widgets/Editor",
"esri/layers/GraphicsLayer",
"esri/geometry/support/webMercatorUtils"
], function (Map, MapView, FeatureLayer, Graphic, Editor, GraphicsLayer, webMercatorUtils) {
//这里面编写代码
})
①创建一个地图map
let map = new Map({
basemap: "streets-navigation-vector"; //地图的底图
});
②创建一个地图视图
let view = new MapView({
container: "viewDiv", //容器,可以认为是放置地图的地方
map: map, //地图
center: [-80, 35],
zoom: 3
});
③先创建一个图形要素(一个三角形)
// 创建一个图形
let polygon = {
type: "polygon", // autocasts as new Polygon()
rings: [
[-64.78, 32.3],
[-66.07, 18.45],
[-80.21, 25.78],
[-64.78, 32.3]
]
};
// Create a symbol for rendering the graphic
let fillSymbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [227, 139, 79, 0.8],
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 1
}
};
// Add the geometry and symbol to a new graphic
let polygonGraphic = new Graphic({
geometry: polygon,
symbol: fillSymbol,
attributes: {
state: "hi~"
}
});
④现在我们再创建一个graphicsLayer图层和graphicsLayer_select图层,并且把此图层添加到地图上。
// 创建一个只有graphic要素的FeatureLayer图层
let graphicsLayer = new GraphicsLayer({ id: 'hello' })
let graphicsLayer_select = new GraphicsLayer({ id: 'select' })
// 将图层添加到地图上
map.add(graphicsLayer);
map.add(graphicsLayer_select);
//将前面我们创建的三角形要素添加到graphicsLayer图层上
graphicsLayer.add(polygonGraphic)
此时地图上已经有一个图形要素了
⑤接下来实现长按鼠标选取范围
let select_flag = false; //用来判断当前是否处于范围选取状态
let tmpGraphic = null; //
let origin = null; //存储最开始的点位
view.on('drag', e => {
if (!select_flag) return //如果不是处于范围选取状态,则退出
if (e.action === 'start') { //开始拖拽
remove_border() //去掉要素的红边框
view.hitTest(e).then(resp => {
e.stopPropagation(); //阻止默认行为
origin = view.toMap(e); //存储最开始的点位
})
} else if (e.action === 'update') { //拖拽过程中
e.stopPropagation(); //阻止默认行为
if (!origin) return //如果没有最开始点位则,跳出
if (tmpGraphic !== null) { //判断最新的要素是否存在
graphicsLayer_select.remove(tmpGraphic) //删除最新的要素
tmpGraphic = null
}
tmpGraphic = new Graphic({ //新建最新的要素
symbol: {
type: "simple-fill",
color: 'rgba(102, 102, 102, .1)',
outline: {
color: [255, 255, 255],
width: 1,
},
},
geometry: {
type: "polygon",
rings: generateQuadrilateral([origin.x, origin.y], [view.toMap(e).x, view.toMap(e).y]) //这个函数根据最开始点位和最后点位生成最新要素的各点坐标
}
})
tmpGraphic.geometry = webMercatorUtils.webMercatorToGeographic(tmpGraphic.geometry);//转换坐标系
graphicsLayer_select.add(tmpGraphic) //添加最新的要素到graphicsLayer_select图层上
} else if (e.action === 'end') {
//最后这里是获取被选取的要素,给这些要素添加一个红边框
const graphics = graphicsLayer.graphics.items
const select_graphics = graphics.filter(item => geometryEngine.intersects( //获取被选取的要素
tmpGraphic.geometry,
item.geometry
))
select_graphics.forEach(item => { //生成新的带红边框的要素,且添加到graphicsLayer图层上
const { geometry, symbol, attributes } = item
graphicsLayer.add(new Graphic({
geometry: geometry,
symbol: {
type: symbol.type, // autocasts as new SimpleFillSymbol()
color: symbol.color,
outline: { // autocasts as new SimpleLineSymbol()
color: 'red',
width: 1
}
},
attributes,
}))
graphicsLayer.remove(item) //删除原来graphicsLayer图层上的原来的要素
})
selectedGraphic = null;
tmpGraphic = null;
origin = null;
graphicsLayer_select.removeMany(graphicsLayer_select.graphics.items)
}
});
//下面这个函数是生成面要素(范围选择要素)的各点坐标
function generateQuadrilateral(startPoint, endPoint) {
let point1 = startPoint;
let point2 = [startPoint[0], endPoint[1]];
let point3 = endPoint;
let point4 = [endPoint[0], startPoint[1]];
// 将四个点的坐标按顺序存储在数组中
let quadrilateral = [point1, point2, point3, point4];
return quadrilateral;
}
//去掉所有要素的红边框
const remove_border = () => {
const graphics = graphicsLayer.graphics.items
const new_graphics = []
for (let i = 0; i < graphics.length; i++) {
let { geometry, symbol, attributes } = graphics[i]
let graphic = new Graphic({
geometry: geometry,
symbol: {
type: symbol.type,
color: symbol.color,
outline: {
color: [255, 255, 255],
width: 1
}
},
attributes,
})
new_graphics.push(graphic)
}
graphicsLayer.removeMany(graphics)
graphicsLayer.addMany(new_graphics)
}
所有的代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Creating a FeatureLayer with Graphics in ArcGIS JS 4</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.28/esri/themes/light/main.css">
<script src="https://js.arcgis.com/4.28/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
.container {
position: absolute;
top: 0;
right: 0;
}
.add_container {
position: absolute;
top: 50px;
right: 0;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/Graphic",
"esri/widgets/Editor",
"esri/layers/GraphicsLayer",
"esri/geometry/support/webMercatorUtils",
"esri/geometry/geometryEngine"
], function (Map, MapView, FeatureLayer, Graphic, Editor, GraphicsLayer, webMercatorUtils, geometryEngine) {
//弹出框
let popup_template = {
title: "属性",
content: [
{
type: "fields",
fieldInfos: [
{
fieldName: "座位号",
editable: true, // 设置可编辑
},
{
fieldName: "状态",
editable: true, // 设置可编辑
},
{
fieldName: "描述",
editable: true, // 设置可编辑
},
{
fieldName: "备注",
editable: true, // 设置可编辑
},
],
},
],
};
// 创建一个地图
let map = new Map({
basemap: "streets-navigation-vector"
});
// 创建一个地图视图
let view = new MapView({
container: "viewDiv",
map: map,
center: [-80, 35],
zoom: 3
});
// 创建一个图形
let polygon = {
type: "polygon", // autocasts as new Polygon()
rings: [
[-64.78, 32.3],
[-66.07, 18.45],
[-80.21, 25.78],
[-64.78, 32.3]
]
};
// Create a symbol for rendering the graphic
let fillSymbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [227, 139, 79, 0.8],
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 1
}
};
// Add the geometry and symbol to a new graphic
let polygonGraphic = new Graphic({
geometry: polygon,
symbol: fillSymbol,
attributes: {
座位号: "hi~"
}
});
// 创建一个只有graphic要素的FeatureLayer图层
let graphicsLayer = new GraphicsLayer({ id: 'hello' })
let graphicsLayer_select = new GraphicsLayer({ id: 'select' })
// 将图层添加到地图中
graphicsLayer.add(polygonGraphic)
map.add(graphicsLayer);
map.add(graphicsLayer_select);
let select_flag = false;
let tmpGraphic = null;
let origin = null;
view.on('drag', e => {
if (!select_flag) return
if (e.action === 'start') {
remove_border()
view.hitTest(e).then(resp => {
e.stopPropagation();
origin = view.toMap(e);
})
} else if (e.action === 'update') {
e.stopPropagation();
if (!origin) return
if (tmpGraphic !== null) {
graphicsLayer_select.remove(tmpGraphic)
tmpGraphic = null
}
tmpGraphic = new Graphic({
symbol: {
type: "simple-fill",
color: 'rgba(102, 102, 102, .1)',
outline: {
color: [255, 255, 255],
width: 1,
},
},
geometry: {
type: "polygon",
rings: generateQuadrilateral([origin.x, origin.y], [view.toMap(e).x, view.toMap(e).y])
}
})
tmpGraphic.geometry = webMercatorUtils.webMercatorToGeographic(tmpGraphic.geometry);
graphicsLayer_select.add(tmpGraphic)
} else if (e.action === 'end') {
const graphics = graphicsLayer.graphics.items
const select_graphics = graphics.filter(item => geometryEngine.intersects(
tmpGraphic.geometry,
item.geometry
))
select_graphics.forEach(item => {
const { geometry, symbol, attributes } = item
graphicsLayer.add(new Graphic({
geometry: geometry,
symbol: {
type: symbol.type, // autocasts as new SimpleFillSymbol()
color: symbol.color,
outline: { // autocasts as new SimpleLineSymbol()
color: 'red',
width: 1
}
},
attributes,
}))
graphicsLayer.remove(item)
})
selectedGraphic = null;
tmpGraphic = null;
origin = null;
graphicsLayer_select.removeMany(graphicsLayer_select.graphics.items)
}
});
//下面这个函数是生成面要素(范围选择要素)的各点坐标
function generateQuadrilateral(startPoint, endPoint) {
let point1 = startPoint;
let point2 = [startPoint[0], endPoint[1]];
let point3 = endPoint;
let point4 = [endPoint[0], startPoint[1]];
// 将四个点的坐标按顺序存储在数组中
let quadrilateral = [point1, point2, point3, point4];
return quadrilateral;
}
let add_graphic_flag = false;
//监听视图的点击事件
view.on('click', (e) => {
if (!add_graphic_flag) return
view.hitTest(e).then(res => {
const new_graphic = new Graphic({ //新建一个要素,这个要素也是一个面要素,不过是一个正方形
symbol: {
type: "simple-fill",
color: 'rgba(102, 102, 102, .1)',
outline: {
color: [255, 255, 255],
width: 1,
},
},
geometry: {
type: "polygon",
rings: [
[-80.21, 18.45],
[-80.21, 32.3],
[-64.78, 32.3],
[-64.78, 18.45],
]
},
attributes: {
name: "点击添加"
}
})
if (new_graphic.geometry.spatialReference.isWGS84) { //转换坐标系
new_graphic.geometry = webMercatorUtils.geographicToWebMercator(new_graphic.geometry);
}
translatePolygon(new_graphic.geometry.centroid, view.toMap(e), new_graphic.geometry) //移动要素new_graphic.geometry.centroid就是当前要素的中心位置
if (new_graphic.geometry.spatialReference.isWebMercator) { //转换回坐标系
new_graphic.geometry = webMercatorUtils.webMercatorToGeographic(new_graphic.geometry);
}
graphicsLayer.add(new_graphic)
})
})
function translatePolygon(startPoint, currPoint, polygon) {
let dx = currPoint.x - startPoint.x;
let dy = currPoint.y - startPoint.y;
polygon.rings.forEach(ring => {
if (Array.isArray(ring[0])) {
ring.forEach(coord => {
coord[0] += dx;
coord[1] += dy;
});
} else {
ring[0] += dx;
ring[1] += dy;
}
});
}
window.addEventListener('load', () => {
document.getElementsByClassName('container')[0].addEventListener('click', (e) => {
if (e.target.style.color === 'orange') {
e.target.style.color = 'black'
select_flag = false
remove_border()
}
else {
e.target.style.color = 'orange'
select_flag = true
}
})
document.getElementsByClassName('add_container')[0].addEventListener('click', (e) => {
if (e.target.style.color === 'orange') {
e.target.style.color = 'black'
add_graphic_flag = false
}
else {
e.target.style.color = 'orange'
add_graphic_flag = true
}
})
})
//去掉所有要素的红边框
const remove_border = () => {
const graphics = graphicsLayer.graphics.items
const new_graphics = []
for (let i = 0; i < graphics.length; i++) {
let { geometry, symbol, attributes } = graphics[i]
let graphic = new Graphic({
geometry: geometry,
symbol: {
type: symbol.type,
color: symbol.color,
outline: {
color: [255, 255, 255],
width: 1
}
},
attributes,
})
new_graphics.push(graphic)
}
graphicsLayer.removeMany(graphics)
graphicsLayer.addMany(new_graphics)
}
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div class="container">
<button>选择</button>
</div>
<div class="add_container">
<button>添加要素</button>
</div>
</body>
</html>
结语
不想做前端牛马了~~~