const mapping= [
{ en: "name", ch: "名称", type: "title" },
{ en: "area", ch: "总占地面积", type: "text" },
{ en: "dealLevel", ch: "处理等级", type: "text" },
{ en: "dealNumYear", ch: "年处理量", type: "text" },
{ en: "type", ch: "类型", type: "text" }
];
const getmapData = (
graphic: any,//点击元素对象
res: any,//一个对象 主要是里面的对对应关系mapping如上
htmlId: any,//弹窗的html 的id
attributes: any, //点击元素自身属性
response?: any
) => {
const mapping = res.map;
if (!res) return;
const apiUrl = import.meta.env.VITE_SERVER_URL;
if (res.api == "local") {
const pickedFeature = graphic;
Popupposition(pickedFeature, htmlId, view, response);
//清空
const titleElement: any = document.getElementById("title");
const valueElement: any = document.querySelector(".pop_value");
// 清空内容
titleElement.innerHTML = ""; // 清空标题文本
valueElement.innerHTML = ""; // 清空值内容
var stateShowDiv = document.getElementById(htmlId); // 首先获取 'htmlId' 元素
var contentDiv = (stateShowDiv as any).querySelector(".content");
contentDiv.innerHTML = "";
//设备特殊弹窗
console.log(htmlId, "htmlId");
let resData = pickedFeature.attributes;
console.log(resData, "resDataresData");
(document.getElementById as any)("title").innerHTML =
resData.name || resData.objectid;
for (let item of mapping) {
if (
item.type == "title" ||
item.type == "location" ||
item.type == "id"
)
continue;
if (item.type == "text") {
var propertyValue = resData[item.en];
console.log(propertyValue, "propertyValue ");
if (!propertyValue) continue;
console.log(propertyValue, "propertyValue");
var popInfoDiv = document.createElement("div");
popInfoDiv.className = "popInfo";
popInfoDiv.style.overflowX = "hidden";
popInfoDiv.style.width = "100%";
popInfoDiv.style.height = "50px";
popInfoDiv.style.display = "flex";
popInfoDiv.style.fontFamily = '"OPPOSans-Regular", sans-serif'; // 添加回退字体
popInfoDiv.style.fontSize = "20px";
popInfoDiv.style.lineHeight = "38px";
popInfoDiv.style.color = "rgba(230, 253, 255, 1)";
popInfoDiv.style.padding = "10px";
// 创建并设置 pop_distribute 元素
var distributeDiv = document.createElement("div");
distributeDiv.className = "pop_distribute";
distributeDiv.textContent = item.ch;
popInfoDiv.style.paddingLeft = "20px";
distributeDiv.style.width = "50%";
// 创建并设置 pop_value 元素
var valueDiv = document.createElement("div");
valueDiv.className = "pop_value";
valueDiv.textContent = propertyValue;
valueDiv.style.width = "50%";
// 将 distributeDiv 和 valueDiv 添加到 popInfoDiv
popInfoDiv.appendChild(distributeDiv);
popInfoDiv.appendChild(valueDiv);
popInfoDiv.setAttribute("data-show", item.show);
// 将 popInfoDiv 添加到 contentDiv
contentDiv.appendChild(popInfoDiv);
}
}
return;
}
}
如上是主函数主要原理就是准备好要渲染的数据,然后通过js来添加样式元素,最后再计算位置(点的位置转换为屏幕坐标,同时监听地图的位置,弹窗跟随地图移动)
下面是激发函数
//arcgis激发函数
const popUp = (view: any, htmlId: any) => {
// 创建一个高亮图层
map.add(highlightLayer);
view.on("click", function (event: any) {
view.hitTest(event).then(function (response: any) {
if (response.results.length) {
const graphic = response.results[0].graphic;
let id = graphic.layer.title;
const res: any = apiMap.get(id);
const geometry = graphic.geometry;
showPopUp(graphic, geometry, "stateShow", res, response);
}
});
});
};
const showPopUp = (
graphic: any,
geometry: any,
htmlId: any,
res: any,
response?: any
) => {
if (graphic.layer.type != "building-scene") hightLight(graphic, geometry);
getmapData(graphic, res, htmlId, graphic.attributes, response);
};
然后是弹窗跟随地图而移动的函数,这一步是核心,其他函数都可以视情况而有较大更改,深入理解了就非常好用
//以arcgis为例
const Popupposition = async (
pickedFeature: any,
htmlId: any,
view: any,
response?: any
) => {
const [Point, SpatialReference, projection] = await loadModules([
"esri/geometry/Point",
"esri/geometry/SpatialReference",
"esri/geometry/projection",
]);
(document.getElementById as any)(htmlId).style.display = "none";
console.log(pickedFeature, "pickedFeature");
let x;
let y;
let point4547: any;
let windowPosition: any;
if (pickedFeature.geometry) {
if (pickedFeature.geometry.type == "point") {
x = pickedFeature.geometry.x;
y = pickedFeature.geometry.y;
} else if (pickedFeature.geometry.type == "polygon") {
x = pickedFeature.geometry.centroid.x;
y = pickedFeature.geometry.centroid.y;
} else if (pickedFeature.geometry.type == "polyline") {
x = pickedFeature.geometry.extent.center.x;
y = pickedFeature.geometry.extent.center.y;
}
point4547 = new Point({
x: x,
y: y,
spatialReference: new SpatialReference({ wkid: 4547 }),
});
windowPosition = view.toScreen(point4547);
} else {
windowPosition = response.screenPoint;
console.log("windowPosition-response", response);
}
(document.getElementById as any)(htmlId).style.left =
windowPosition.x + 150 + "px";
(document.getElementById as any)(htmlId).style.top =
windowPosition.y - 220 + "px";
(document.getElementById as any)(htmlId).style.display = "block"; //弹出信息框
if (pickedFeature.geometry) {
view.watch("camera", function (camera: any) {
var windowPosition = view.toScreen(point4547);
(document.getElementById as any)(htmlId).style.left =
windowPosition.x + 150 + "px";
(document.getElementById as any)(htmlId).style.top =
windowPosition.y - 220 + "px";
});
}
};
最后是div弹窗,还有很多不足欢迎批评指正
<div class="state" id="stateShow">
<div class="box">
<div class="box-wrap">
<div class="poptitle">
<div class="poptitle_text" id="title"></div>
<div class="clopoptitle_close" @click="closeClick()">X</div>
</div>
<div class="content" style="max-height: 1000px; overflow-y: auto">
<div class="popInfo">
<div class="pop_distribute"></div>
<div class="pop_value"></div>
</div>
</div>
</div>
</div>
</div>
.state {
width: 500px;
position: absolute;
background-color: rgba(4, 55, 61, 0.8);
z-index: 1;
}
.poptitle {
width: 100%;
height: 50px;
display: flex;
font-size: 26px;
color: rgba(255, 255, 255, 1);
background: linear-gradient(
to right,
rgba(92, 225, 255, 1) 0%,
rgba(92, 225, 255, 0) 100%
);
font-family: "优设标题黑";
line-height: 50px;
&_text {
width: 94%;
padding-left: 20px;
}
}