场景:
ArcGis 有polygon有marker,只删除marker数组,不删除polygon。
定义markers:
循环删除:
将marker放在markers中:
代码:
<template>
<div style="width: 100vw; height: 100%; position: relative">
<el-drawer title="poi缓存搜索" :visible.sync="drawer" :with-header="false">
<div style="display: flex; height: 100vh; width: 100%; flex-direction: column">
<div style="display: flex; margin: 20px; margin-bottom: 0">
<el-input
v-model="keyword"
@keyup.enter.native="searchPOI"
placeholder="输入关键词搜索POI"
clearable=""
style="flex: 1"
/>
<el-button type="primary" @click="searchPOI" style="margin: 0 10px"
>搜索</el-button
>
</div>
<div v-if="poiList.length > 0" style="flex: 1; overflow-y: auto">
<el-card
class="box-card"
style="margin: 20px"
v-for="(poi, index) in poiList"
:key="poi.hotPointID"
>
<div class="text item">
<p>{
{ index + 1 }}. {
{ poi.name }}</p>
<p>地址:{
{ poi.address }}</p>
<p>电话:{
{ poi.phone }}</p>
<p>坐标:{
{ poi.lonlat }}</p>
<p>
<button @click="showMarker(poi.lonlat, 1,1,1)">定位</button>
</p>
</div>
</el-card>
</div>
<p
v-if="poiList.length == 0"
style="
margin: 20px;
width: calc(100% - 40px);
display: flex;
flex: 1;
align-items: center;
justify-content: center;
background-color: #f9f9f9;
color: #c0c0c0;
font-size: 20px;
text-align: center;
"
>
{
{ noMessage }}
</p>
</div>
</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 axios from "axios";
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 {
keyword: "",
poiList: [],
noMessage: "暂无POI列表信息",
errorMessage: "",
marker: null,
markers: [],
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: {
async searchPOI() {
const layer = this.mapView.map.findLayerById("selfSketchLayer");
//每次搜索之前 start
if (this.markers) {
if (layer) {
this.markers.forEach((marker) => {
layer.remove(marker); // 从图层中移除 marker
});
this.markers = []; // 清空 markers 数组
}
}
///
//
//每次搜索之前 end
if (!this.keyword) {
this.poiList = [];
this.noMessage = "暂无POI列表信息";
return;
}
const postStr = {
queryType: "1",
start: 0,
mapBound:
"121.40641563476055,31.166685323878824,121.44761436522919,31.176654597384555",
yingjiType: 0,
queryTerminal: 10000,
level: 15,
keyWord: this.keyword,
count: 10,
sourceType: 0,
};
try {
const response = await axios.get(`http://api.tianditu.gov.cn/v2/search`, {
params: {
postStr: JSON.stringify(postStr),
type: "query",
tk: tiandituInfo.token, // 确保使用正确的token
},
});
this.poiList = [];
this.poiList = response.data.pois || [];
// 循环
// 循环 poiList,调用 showMarker 方法
this.poiList.forEach((poi) => {
if (poi.lonlat) {
this.showMarker(poi.lonlat, 0, 0,0); //无圆圈,不清除marker
}
});
this.errorMessage =
response.data.status.cndesc === "服务正常" ? "" : response.data.status.cndesc;
} catch (error) {
console.error("Error fetching POI data:", error);
this.errorMessage = "获取POI数据失败";
}
},
/**
* @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: 1,
},
},
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);
});
});
},
// 按钮点击事件:修改中心点 isCircle 是点击单个定位 显示高亮圆圈, isRemove是考虑到搜索多poi列表的时候显示多个marker而不要清除。
async showMarker(zuobiao_str, isCircle = 0, isRemove = 1,isCloseDrawer=0) {
let zuobiao_arr = zuobiao_str.split(",");
const new_x = zuobiao_arr[0];
const new_y = zuobiao_arr[1];
if (isCloseDrawer==1) {
this.drawer = false;
}
if (this.mapView) {
const newCenter = {
x: new_x, // 新经度
y: new_y, // 新纬度
};
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 && isRemove == 1) {
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",
},
});
if (isCircle == 1) {
// 创建圆形框选区域
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) {
if (isCircle == 1) {
layer.add(this.circleGraphic); // 添加圆形
}
layer.add(this.marker);
this.markers.push(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>