前言
PopupTemplate 为特定层或图形格式化和定义 Popup 的内容。当选择视图中的要素时,用户还可以使用 PopupTemplate 访问要素属性的值和 Arcade 表达式返回的值。
PopupTemplate 包含 title 和 content 属性,它们充当用于将要素的属性转换为 HTML 表示的模板。语法 {fieldName} 或 {expression/expressionName} 执行参数替换。 Graphic 的默认行为是在单击 Graphic 后显示视图的 Popup。此默认行为需要 PopupTemplate。
PopupTemplate 还允许您格式化 数字(Number)和 日期(Date)字段值并使用 fieldInfos 属性覆盖字段别名。还可以将 操作(Actions)添加到模板中,使用户能够执行与要素相关的操作,例如对其进行缩放或根据要素的位置或属性执行查询。
效果
自定义指定featureLayer的popupTemplte点击后弹出的popup,模板代码如下
popup自定义模板
// 地块图层的popupTemplate
const dkPopupTemplate = {
overwriteActions: true,
outFields: ['*'],
title: ({ graphic: { attributes } }) => {
const dkmc = attributes.dkmc;
return `<div class="flex">
<div class="text-cut">${dkmc || ''}</div>
</div>`;
},
content: ({ graphic: { attributes} }) => {
const {
qylxmc,
dkyxztmc,
zhdcrq,
pjjg_dbs1: pjjg_dbs,
pjjg_dxs1: pjjg_dxs,
pjjg_tr,
} = attributes;
// 地表水和地下水需要转化评价结果值
const pjjg_dbs_color = this.pjjgValueConversion(pjjg_dbs);
const pjjg_dxs_color = this.pjjgValueConversion(pjjg_dxs);
const dcrq = zhdcrq ? moment(zhdcrq)
.format('YYYY-MM-DD') : '';
const tagColor = [ColorEnum.blue, ColorEnum.green, ColorEnum.yellow, ColorEnum.red];
return `<div class="xf-margin-tb-sm">
<div class="text-black-65 flex mb-2" style="white-space: pre;${!qylxmc ? 'display:none;' : ''}"><div class="text-bold" style="word-break: keep-all;">企业类型:</div><div class="text-sm">${qylxmc}</div></div>
<div class="text-black-65 flex mb-2" style="white-space: pre;${!dkyxztmc ? 'display:none;' : ''}"><div class="text-bold" style="word-break: keep-all;">生产状态:</div><div class="text-sm">${dkyxztmc}</div></div>
<div class="text-black-65 flex mb-2" style="white-space: pre;${!dcrq ? 'display:none;' : ''}"><div class="text-bold" style="word-break: keep-all;">调查日期:</div><div class="text-sm">${dcrq}</div></div>
<div class="flex">
<div class="ant-tag" style="background-color: ${util.colorHex2RGBA(tagColor[pjjg_dbs_color], 0.1)};color:${tagColor[pjjg_dbs_color]};border:1px solid ${tagColor[pjjg_dbs_color]};${(!rendererFields?.pjjg_dbs?.[pjjg_dbs] || pjjg_dbs == '0') ? 'display:none;' : ''}">
地表水:${rendererFields?.pjjg_dbs?.[pjjg_dbs]}
</div>
<div class="ant-tag" style="background-color: ${util.colorHex2RGBA(tagColor[pjjg_dxs_color], 0.1)};color:${tagColor[pjjg_dxs_color]};border:1px solid ${tagColor[pjjg_dxs_color]};${(!rendererFields?.pjjg_dxs?.[pjjg_dxs] || pjjg_dxs == '0') ? 'display:none;' : ''}">
地下水:${rendererFields?.pjjg_dxs?.[pjjg_dxs]}
</div>
<div class="ant-tag" style="background-color: ${util.colorHex2RGBA(tagColor[pjjg_tr], 0.1)};color:${tagColor[pjjg_tr]};border:1px solid ${tagColor[pjjg_tr]};${(!rendererFields?.pjjg_tr?.[pjjg_tr] || pjjg_tr == '0') ? 'display:none;' : ''}">
土壤:${rendererFields?.pjjg_tr?.[pjjg_tr]}
</div>
</div>
</div>`;
},
actions: [
{
title: '详情',
id: 'showDKDetail',
className: 'esri-icon-zoom-in-magnifying-glass',
},
{
title: '空间分析',
id: 'showSpatialAnalysis',
className: 'esri-icon-applications',
},
],
};
代码解析
上边模板代码主要有三部分 title、content 和 actions 组成,其中title和content都是一个 function函数,最后返回的也是 HTML 的字符串,里面的内容可以通过function返回的graphic里的attributes属性取值动态拼接。
重点看一下 Actions,这是一个对象集合,每个对象代表一个Action或者功能,可以通过单击弹出窗口中象征它们的图标或图像来执行。弹出窗口中每个Action的顺序与它们在Action集合中出现的顺序相同。 每次单击弹出窗口中的Action按钮时,都会触发 Popup 中的 Popup 事件。 此事件应用于为每个单击的操作执行自定义代码。事件监听如下:
// 初始化activeView的监听事件
initActiveViewEvents() {
if (this.activeView) {
// PopupViewModel的触发动作被触发,然后检查动作id
this.activeView.popup.on('trigger-action', ({ action }) => {
const actionId = action?.id;
// 点击"地块详情"
if (actionId === 'showDKDetail') {
//获取弹出的popup所归属的graphic的attributes
let { attributes } = this?.activeView?.popup?.viewModel?.selectedFeature;
this.handleQuery(() => {
// 地块详情页
this.$router.push({
name: 'dkListDetailPage',
query: { id: attributes?.hid, is_cydc: attributes?.is_cydc },
});
});
} else if (actionId === 'showSpatialAnalysis') { // 空间分析
const selectedFeature = this?.activeView?.popup?.viewModel?.selectedFeature;
const { geometry } = selectedFeature;
let { attributes } = selectedFeature;
attributes = this.formatFeatureAttributeValue(attributes);
// 如果选中要素不是polygon,就要进一步处理
if (geometry?.type !== 'polygon') {
// 地块
if (attributes?.hasOwnProperty('dkmc')) {
// 由于没有直接能取到“is_cydc”,所以就要先到地块图层进行查询
const { subMapLayerIds } = window?.DynamicDataLayersConfig;
const mapLayerId = window.LayersConfig.QYDK_M_LayerName;
const sqlWhereApi = new CreateSqlWhere();
const fieldNamePrefix = this.DynamicDataLayerServiceApi.getJoinDataLayerFieldNamePrefix('', mapLayerId);
const sqlWhere: string = sqlWhereApi.eq(`${fieldNamePrefix}hid`, attributes?.hid)
.getSql();
this.getDynamicDataLayerServiceApi.findFeaturesByQueryConditionsParams(subMapLayerIds[mapLayerId], sqlWhere, undefined, undefined, ([feature]) => {
const { geometry: targetGeometry }: any = feature;
if (targetGeometry) {
this.startSpatialAnalysis(targetGeometry);
}
}, { outFields: null });
} else { // 样点
this.startSpatialAnalysis(geometry);
}
} else {
this.startSpatialAnalysis(geometry);
}
}
});
}
}
主要就是监听地图view的popup的**“trigger-action”**事件,通过上边Actions里Action的id进行区分,完成每个Action的实现功能。
进阶
在实际开发中还有一个很合理的需求,以上面的popup为例,同一个要素图层的使用的都是同一个popupTemplate,所以Actions集合的配置也是不变的,但是因为有些graphic缺少空间分析功能所需要的属性数据,所以我们就应该动态更新空间分析Action的visible。
我没有在官网找到现成的例子,只能通监听地图view弹出的popup所归属的要素(“selectedFeature”),并通过判断动态的控制Action的显示/隐藏,代码如下:
// 初始化activeView的监听事件
initActiveViewEvents(activeView = this.activeView) {
if (activeView) {
// 监听需要popup选中的feature,动态显示/隐藏action的菜单
activeView.popup.watch('selectedFeature', (graphic) => {
if (graphic) {
let { attributes: { type } } = graphic;
//获取当前要素拥有的popupTemplate模板数据
const graphicTemplate = graphic.getEffectivePopupTemplate();
// 地块详情展示Action
const showDKDetailAction = graphicTemplate?.actions?.items?.find(({ id }) => id === 'showDKDetail');
if (showDKDetailAction) {
showDKDetailAction.visible = type === ydlxEnum.dk;
}
// 空间分析展示Action
const showSpatialAnalysisAction = graphicTemplate?.actions?.items?.find(({ id }) => id === 'showSpatialAnalysis');
if (showSpatialAnalysisAction) {
showSpatialAnalysisAction.visible = ydlxEnum.dk;
}
}
});
}
}