自定义POI图标:
如果有多个Graphic,如何不清除之前的Graphic:
点击图标弹出框:
设置圆形:
展示:
有多边形的Graphic,还有标记的Graphic,如何点击新标记只删除标记的Graphic,而不删除多边形的Graphic?
修改circle的半径:
重新更新Graphic即可:
点击“定位”后关闭抽屉:
全部代码:
<template>
<div style="width: 100vw; height: 100%; position: relative">
<el-drawer title="poi缓存搜索" :visible.sync="drawer" :with-header="false">
<el-card class="box-card" style="margin: 20px">
<div class="text item">
<p>1.漕河泾</p>
<p>地址:上海市徐汇区漕河泾1011号</p>
<p>电话:021-54210000</p>
<p>坐标:121.42524531217315,31.167829642058244</p>
<p>
<button @click="changeCenter(121.42524531217315, 31.167829642058244)">
定位
</button>
</p>
</div>
</el-card>
<el-card class="box-card" style="margin: 20px">
<div class="text item">
<p>1.世博大道</p>
<p>地址:上海市浦东世博大道1011号</p>
<p>电话:021-54210000</p>
<p>坐标:121.47944750034962,31.18516747580588</p>
<p>
<button @click="changeCenter(121.47944750034962, 31.18516747580588)">
定位
</button>
</p>
</div>
</el-card>
<el-card class="box-card" style="margin: 20px">
<div class="text item">
<p>1.世博大道</p>
<p>地址:上海市浦东世博大道1011号</p>
<p>电话:021-54210000</p>
<p>坐标:121.47944750034962,31.18516747580588</p>
<p>
<button @click="changeCenter(121.47944750034962, 31.18516747580588)">
定位
</button>
</p>
</div>
</el-card>
</el-drawer>
<el-drawer title="常规搜索" :visible.sync="drawer2" :with-header="false">
<span>我来啦!2</span>
</el-drawer>
<!-- 弹出框 -->
<!-- 弹出对话框 -->
<el-dialog
title="编辑poi信息"
:visible.sync="dialogVisible"
width="500px"
@close="handleClose"
>
<el-form :model="form" label-width="100px">
<el-form-item label="项目类型">
<el-input v-model="form.projectType"></el-input>
</el-form-item>
<el-form-item label="所属区域">
<el-input v-model="form.area"></el-input>
</el-form-item>
<el-form-item label="项目名称">
<el-input v-model="form.projectName"></el-input>
</el-form-item>
<el-form-item label="项目编号">
<el-input v-model="form.projectCode"></el-input>
</el-form-item>
<el-form-item label="委托单位">
<el-input v-model="form.client"></el-input>
</el-form-item>
<el-form-item label="批复时间">
<el-date-picker
v-model="form.approvalDate"
type="date"
placeholder="选择日期"
></el-date-picker>
</el-form-item>
<el-form-item label="缓冲宽度">
<el-input v-model="form.bufferWidth" type="number"></el-input>
</el-form-item>
</el-form>
<!-- 对话框操作按钮 -->
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSave">保存</el-button>
</div>
</el-dialog>
<div id="mapDom">
<div
style="
position: absolute;
top: 5px;
left: 5px;
z-index: 1;
display: flex;
flex-direction: column;
"
>
<el-button @click="drawer = true" type="primary"> poi缓存搜索 </el-button>
<br />
<el-button @click="drawer2 = true" type="primary"> 常规搜索 </el-button>
</div>
<!-- 地图实例 -->
<div id="mapView" />
<!-- 底图切换 -->
<div id="baseMapToggle" />
<!-- 比例尺 -->
<div id="scaleBar" />
<!-- 缩放 -->
<div id="zoom" />
<!-- 指北针 -->
<div id="compass" />
<!-- 图例 -->
<div id="selfLegend" />
<!-- Sketch -->
<div id="selfSketch" />
<div class="copyRight">©2023 上海营邑城市规划设计股份有限公司 荣誉出品</div>
<div id="maskDiv" class="hide screenshotCursor" />
</div>
</div>
</template>
<script>
import { loadModules } from "esri-loader";
import config from "@/config/mapOptions";
import { centerPoint, tiandituInfo } from "@/config/mapConfig";
import { showScreenLoading, hideScreenLoading } from "@/utils/loadingContent";
import { listGis } from "@/api/search/gis.js"; // 数据来源的地方
import { geojsonToArcGIS } from "@terraformer/arcgis";
export default {
name: "Search",
data() {
return {
marker: null,
circleGraphic: null,
dialogVisible: false, // 控制对话框显示
form: {
projectType: "", // 项目类型
area: "", // 所属区域
projectName: "", // 项目名称
projectCode: "", // 项目编号
client: "", // 委托单位
approvalDate: "", // 批复时间
bufferWidth: "2000", // 缓冲宽度
},
drawer: false,
drawer2: false,
mapView: null, // 存储 MapView 实例
vectorMapUrl: require("@/assets/dashbord/one.png"),
imageMapUrl: require("@/assets/dashbord/two.png"),
};
},
mounted() {
// 页面加载时调用_createMapView 方法初始化地图
let promiseList = [];
promiseList.push(this._createMapView());
Promise.all(promiseList).then(() => {
console.log("ok");
});
},
methods: {
/**
* @description: 初始化地图
* @return {*}
*/
async _createMapView() {
showScreenLoading({ text: "地图加载中..." });
const [
Map,
GraphicsLayer,
Legend,
Expand,
Sketch,
WebTileLayer,
TileInfo,
MapView,
SpatialReference,
Point,
ScaleBar,
Zoom,
BasemapToggle,
Compass,
// esriConfig,
// Print
] = await loadModules(
[
"esri/Map",
"esri/layers/GraphicsLayer",
"esri/widgets/Legend",
"esri/widgets/Expand",
"esri/widgets/Sketch",
"esri/layers/WebTileLayer",
"esri/layers/support/TileInfo",
"esri/views/MapView",
"esri/geometry/SpatialReference",
"esri/geometry/Point",
"esri/widgets/ScaleBar",
"esri/widgets/Zoom",
"esri/widgets/BasemapToggle",
"esri/widgets/Compass",
"esri/config",
// "esri/widgets/Print",
],
config.options
);
// =================================创建mapView start==========================
// 设置天地图配置(影像地图和矢量地图)
const { tianDiTuBaseUrl, token, TileInfoMsg } = tiandituInfo;
const tileInfo = new TileInfo(TileInfoMsg);
//影像地图
const tiledLayer = new WebTileLayer({
urlTemplate:
tianDiTuBaseUrl + "/DataServer?T=img_c&x={col}&y={row}&l={level}&tk=" + token,
subDomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
tileInfo: tileInfo,
spatialReference: { wkid: 4490 },
});
//影像注记
const tiledLayerAnno = new WebTileLayer({
urlTemplate:
tianDiTuBaseUrl + "/DataServer?T=cia_c&x={col}&y={row}&l={level}&tk=" + token,
subDomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
tileInfo: tileInfo,
spatialReference: { wkid: 4490 },
});
// 矢量地图
const vecLayer = new WebTileLayer({
urlTemplate:
tianDiTuBaseUrl + "/DataServer?T=vec_c&x={col}&y={row}&l={level}&tk=" + token,
subDomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
tileInfo: tileInfo,
spatialReference: { wkid: 4490 },
});
const vecLayerAnno = new WebTileLayer({
urlTemplate:
tianDiTuBaseUrl + "/DataServer?T=cva_c&x={col}&y={row}&l={level}&tk=" + token,
subDomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
tileInfo: tileInfo,
spatialReference: { wkid: 4490 },
});
// Layer
const layer = new GraphicsLayer({
id: "selfSketchLayer",
});
await layer.load();
// 创建地图
const map = new Map({
basemap: {
// baseLayers: [tiledLayer, tiledLayerAnno],
thumbnailUrl: this.vectorMapUrl,
baseLayers: [vecLayer, vecLayerAnno],
},
layers: [layer],
});
// 定位到中心,设置地图中心点
const cityCenter = new Point(
centerPoint.x,
centerPoint.y,
new SpatialReference({ wkid: 4490 })
);
// 创建地图视图
this.mapView = new MapView({
container: "mapView",
map: map,
center: cityCenter,
zoom: 14,
});
//start/
// 地图点击事件监听器
this.mapView.on("click", (event) => {
const latitude = event.mapPoint.latitude;
const longitude = event.mapPoint.longitude;
console.log("Clicked location - Latitude:", latitude, "Longitude:", longitude);
// 你可以在这里执行其他操作,比如显示在界面上或将坐标存储在变量中
});
let resListGis = await listGis(); //获取数据
// 动态加载Polygon模块
const [Polygon, Graphic] = await loadModules([
"esri/geometry/Polygon",
"esri/Graphic",
]);
// 添加GIS数据到地图图层
resListGis.rows.forEach((item) => {
// 解析geometry
const geometryData = JSON.parse(item.geometry);
// 创建Polygon对象
const polygon = new Polygon({
rings: geometryData.coordinates[0],
spatialReference: { wkid: 4490 },
});
// 创建Graphic对象
const graphic = new Graphic({
geometry: polygon,
symbol: {
type: "simple-fill",
color: [51, 51, 204, 0.6], // 填充颜色
outline: {
color: [0, 0, 0], // 边界颜色
width: 2,
},
},
attributes: {
title: item.title,
leader: item.leader,
code: item.code,
area: item.area,
},
popupTemplate: {
title: "{title}",
content: [
{
type: "fields",
fieldInfos: [
{ fieldName: "leader", label: "负责人" },
{ fieldName: "code", label: "项目编号" },
{ fieldName: "area", label: "区域" },
],
},
],
},
});
// 添加Graphic到图层
layer.add(graphic);
});
///end
// 实例化底图切换控件
const mapToggle = new BasemapToggle({
view: this.mapView,
nextBasemap: {
// baseLayers: [vecLayer, vecLayerAnno],
baseLayers: [tiledLayer, tiledLayerAnno],
thumbnailUrl: this.imageMapUrl,
},
// nextBasemap: { baseLayers: [tiledLayer, tiledLayerAnno] },
container: "baseMapToggle",
});
// mapView.ui.add(mapToggle);
// ============================== 创建mapView end ================
await this.mapView
.when(async () => {
// this.$store.commit("map/CHANGE_MAP_VIEW", mapView);//临时
// 去除控件UI
this.mapView.ui.components = [];
// 实例化比例尺
const mapScaleBar = new ScaleBar({
view: this.mapView,
container: "scaleBar",
unit: "metric",
});
this.mapView.ui.add(mapScaleBar);
// 实例化缩放控件
const mapZoom = new Zoom({
container: "zoom",
view: this.mapView,
});
this.mapView.ui.add(mapZoom);
const mapCompass = new Compass({
container: "compass",
view: this.mapView,
});
this.mapView.ui.add(mapCompass);
const legend = new Expand({
content: new Legend({
view: this.mapView,
// style: "card",
}),
view: this.mapView,
expanded: false,
container: "selfLegend",
});
this.mapView.ui.add(legend, "bottom-right");
})
.then(async () => {
hideScreenLoading();
//弹框自定义操作
this.mapView.popup.viewModel.on("trigger-action", async (event) => {
await triggerAction.call(this, event);
});
});
},
// 按钮点击事件:修改中心点
async changeCenter(xx, yy) {
this.drawer = false;
if (this.mapView) {
const newCenter = {
x: xx, // 新经度
y: yy, // 新纬度
};
const [Point, SpatialReference, Graphic, Circle] = await loadModules([
"esri/geometry/Point",
"esri/geometry/SpatialReference",
"esri/Graphic",
"esri/geometry/Circle",
]);
this.mapView.center = new Point({
x: newCenter.x,
y: newCenter.y,
spatialReference: new SpatialReference({ wkid: 4490 }),
});
// 如果存在之前的标记,删除它
if (this.marker) {
const layer = this.mapView.map.findLayerById("selfSketchLayer");
if (layer) {
layer.remove(this.marker); // 从图层中删除 marker
layer.remove(this.circleGraphic); // 从图层中删除 绿色圆形
}
}
// 设置标记
this.marker = new Graphic({
geometry: new Point({
x: newCenter.x,
y: newCenter.y,
spatialReference: { wkid: 4490 },
}),
symbol: {
type: "picture-marker",
url: "/pos.png",
width: "48px",
height: "48px",
},
});
// 创建圆形框选区域
const circleGeometry = new Circle({
center: new Point({
x: newCenter.x,
y: newCenter.y,
spatialReference: { wkid: 4490 },
}),
radius: 2000, // 圆的半径,单位为地图坐标单位
spatialReference: { wkid: 4490 },
});
this.circleGraphic = new Graphic({
geometry: circleGeometry,
symbol: {
type: "simple-fill",
color: [0, 255, 0, 0.5], // 填充绿色半透明
outline: {
color: [0, 0, 255], // 边框颜色
width: 0, // 边框宽度
},
},
});
const layer = this.mapView.map.findLayerById("selfSketchLayer");
if (layer) {
//layer.removeAll();
layer.add(this.circleGraphic); // 添加圆形
layer.add(this.marker);
}
// 为地图视图添加点击事件
this.mapView.on("click", (event) => {
this.mapView.hitTest(event).then((response) => {
// 检查是否点击到标记
if (response.results.length) {
const graphic = response.results[0].graphic;
if (graphic === this.marker) {
this.dialogVisible = true; // 显示对话框
}
}
});
});
}
},
handleClose() {
// 关闭对话框时的处理,可以清空数据或其他操作
this.dialogVisible = false;
},
// 处理保存
async handleSave() {
const [Graphic, Circle] = await loadModules([
"esri/Graphic",
"esri/geometry/Circle",
]);
// 获取缓冲宽度值
const bufferWidth = this.form.bufferWidth;
// 确保 bufferWidth 是有效的
if (bufferWidth && this.marker) {
// 更新 circleGeometry 的 radius
const radius = bufferWidth; // 将缓冲宽度赋值给半径
const circleGeometry = new Circle({
center: this.marker.geometry, // 使用当前标记的位置
radius: radius, // 新的半径值
spatialReference: { wkid: 4490 },
});
// 创建新的 Graphic 对象并添加到图层
const circleGraphic = new Graphic({
geometry: circleGeometry,
symbol: {
type: "simple-fill",
color: [0, 255, 0, 0.5], // 填充颜色为半透明绿色
outline: {
color: [0, 0, 255], // 边框颜色
width: 0, // 边框宽度
},
},
});
const layer = this.mapView.map.findLayerById("selfSketchLayer");
if (layer) {
layer.remove(this.circleGraphic); // 如果有之前的圆形,先移除
layer.add(circleGraphic); // 添加新的圆形
this.circleGraphic = circleGraphic; // 保存对圆形的引用
}
// 关闭对话框
this.dialogVisible = false;
} else {
alert("请确保缓冲宽度有效!");
}
},
},
};
</script>
<style lang="scss" scoped>
#mapDom {
position: relative;
display: flex;
width: 100%;
overflow: hidden;
height: calc(100vh - 86px);
/* stylelint-disable-next-line selector-id-pattern */
#mapView {
flex: 1;
}
/* stylelint-disable-next-line selector-id-pattern */
#baseMapToggle {
position: absolute;
right: 30px;
top: 109px;
transform: scale(0.44);
border: 2px solid #fff;
}
/* stylelint-disable-next-line selector-id-pattern */
#scaleBar {
position: absolute;
bottom: 15px;
right: 60px;
}
/* stylelint-disable-next-line selector-id-pattern */
#mapTools {
position: absolute;
top: 0px;
right: 0px;
}
#zoom {
position: absolute;
right: 48px;
top: 50px;
transform: scale(0.9);
}
#compass {
position: absolute;
right: 48px;
top: 180px;
}
#selfLegend {
position: absolute;
right: 47px;
bottom: 30px;
}
#selfSketch {
position: absolute;
left: 630px;
bottom: 15px;
transform: translateX(-50%);
}
#currentComponent {
position: absolute;
}
#maskDiv {
position: absolute;
background: rgba(255, 51, 0, 0.1);
border: 2px dashed rgb(255, 51, 0);
}
.hide {
display: none;
}
.screenshotCursor {
cursor: crosshair;
}
}
.copyRight {
position: absolute;
bottom: 5px;
left: 60%;
transform: translateX(-50%);
color: #fff;
font-weight: 500;
font-size: 15px;
}
</style>