需求:使用ArcGIS JS自带的Popup弹窗,展示要素属性。部分要素为物联网设备,除了基本的名称、位置等属性之外,还需要通过接口的形式,去获取该要素的实时的流速、流量等数据。
请使用方案(3)
使用PopupTemplate,配置好fieldInfo的方式比较简单,可以快速的实现弹窗(好不好看另说)。但是对于需要二次请求获取实时数据,实现起来较麻烦。
工作中,尝试了以下几种思路去实现
(1)使用拦截器,在拦截器中请求的url做筛选,如果是identify接口的返回值,根据图层名等,要素外键字段,调用接口进行二次请求,之后将请求获取到的数据,identify结果。
大体代码:
esriConfig.request.interceptors.push({
urls: 'http://ddd',
before: function (params) {
},
after:function (params) {
if(imp.afterRequestHandler!=undefined){
imp.afterRequestHandler(params);
}
if(params.url.indexOf("identify")!=-1){
//如果结果中包含等,则进行二次请求,获取实时数据
params.data.results.forEach((element:any) => {
if(element.layerName=="水位计2"){
let swjurl = GConstant.QHIOTUrl+"ap/ll/getLastData?pointIds="+element.attributes.QId;
xhr(swjurl,{sync:true,method:"POST"}).then(function(response:any){
if(response.success){
let dd= response.data[0]; //写入attributes值
element.attributes.CurrentData=dd.data;
element.attributes.DataTime=dd.monitorTime;
}
},function(err){
console.log("水位数据获取失败:"+err);
});
}
console.log(params);
});
}
},
error: function (err) {
// console.log(err);
},
});
问题:经过测试后,已经基本实现了需求。但是对于一个点位多个图标的情况时,点击下一个要素按钮,则下一个要素显示的还是默认的属性,点击上一个要素时,之前显示正确的属性,也恢复了初始的属性状态。推测大体原因是,click时,ArcGIS JS底层调用了请求的缓存结果。
该方案并不完美。
(2)在弹窗显示之后,通过DOM操作的方式,对结显示的表格内容进行覆写。
经过测试,该方法与方案(1)类似,也是存在点击之后,则不显示二次请求的结果的问题。
(3)在Popuptemplate中,通过setContent函数的方式,进行二次请求实时数据,并通过字符串拼接的方式,生成html表格,表格样式按照默认弹窗的样式设置,以保证与其他图层属性弹窗显示效果一致。
核心代码:
import dstring from "dojo/string";
import xhr = require("dojo/request/xhr");
popupTemplate = new PopupTemplate({
title: "流量计",
content: (p: any) => {
return queryLLJ(p);
},
});
function queryLLJ(target: any) {
let attr = target.graphic.attributes;
let tb_template =
"<div class='esri-feature-fields'>" +
"<table class='esri-widget__table' summary='属性和值列表'>" +
"<tbody>" +
"${0}" +
"</tbody>" +
"</table>" +
"</div>";
let trow_template =
"<tr>" +
"<th class='esri-feature-fields__field-header'>${0}</th>" +
"<td class='esri-feature-fields__field-data'>${1}</td>" +
"</tr>";
let tr = dstring.substitute(trow_template, ["名称", attr["名称"]]);
tr += dstring.substitute(trow_template, ["地址", attr["地址"]]);
tr += dstring.substitute(trow_template, ["所在乡镇", attr["Town"]]);
return new Promise((resolve, reject) => {
//请求接口中实时数据
let yljurl =
GConstant.QHIOTUrl + "/af/getLastData?pointId=" + attr.Id;
xhr(yljurl, { method: "POST" }).then(
function (response: any) {
response = JSON.parse(response);
if (response.success) {
let dd = response.data;
resolve(dd);
}
},
function (err) {
console.log("流量计数据获取失败:" + err);
}
);
}).then((res: any) => {
if (res.speed != undefined)
tr += dstring.substitute(trow_template, ["流速(m/s)", res.speed]);
if (res.waterLevel != undefined)
tr += dstring.substitute(trow_template, ["水位(m)", res.waterLevel]);
if (res.temperature != undefined)
tr += dstring.substitute(trow_template, ["温度(℃)", res.temperature]);
if (res.monitorTime != undefined)
tr += dstring.substitute(trow_template, [
"监测时间",
res.monitorTime,
]);
let ro = dstring.substitute(tb_template, [tr]);
return ro;
});
}
参考示例:
PopupTemplate with promise | Sample Code | ArcGIS API for JavaScript 4.23 | ArcGIS Developer
该方式较完美。其他图层的属性弹窗仍然通过PopupTemplate FieldInfo的形式设置,通过上述方法设置的要素属性弹窗,与之样式一致。