很多时候,对于arcgis js api,我们需要控制点击特定的要素才弹出PopupTemplate,其他的点击无效,或者控制要素点击监控,以及对PopupTemplate内容的自定义等功能,本篇将介绍如何进行点击事件的监控以及PopupTemplate内容的自定义。
对于点击控制,首先需要实例化点击事件,在点击事件中通过hitTest方法返回最顶层要素对象,通过OBJECTID进行判定是否弹出PopupTemplate面板。再将实例化的点击事件存入vuex,以便后续将其移除。
that.esriSceneView.whenLayerView(buildingSceneLayer).then(function (layerView) { EsriwatchUtils.whenFalseOnce(layerView, 'updating', function () { let buildingClickInstance = that.esriSceneView.on(['click'], function (event) { that.esriSceneView.hitTest(event).then(function (response) { // let buildingSceneLayerHighlight; buildingSceneLayer.popupEnabled = false; const result = response.results[0].graphic.attributes.OBJECTID; buildingWebScene.emergencyBuildings.map(function (Building, key) { if (result === Building.buildingId) { buildingSceneLayer.popupEnabled = true; } }); }); }); store.dispatch('saveBuildingClickInstance', buildingClickInstance); }); });在vuex中编写点击事件移除函数,就可以随时移除点击事件,使得不再弹出PopupTemplate
/** * 移除建筑物点击事件 * @param {Object} state Vuex全局state */ export const removeBuildingClickInstance = (state) => { state.buildingClickInstance.remove(); };链接: https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest.
PopupTemplate内容可以通过字符串的形式进行自定义,但当面板中存在按钮时则显得不太好用,主要在于按钮的点击函数需要写在外面,并通过ref的方式找的按钮并赋予点击事件函数,但当点击弹出PopupTemplate时进行赋予点击事件函数会存在按钮没有及时挂载的问题,导致找不到按钮进行赋予,点击按钮没效果的现象。
popupTemplate.content = "<p>As of 2015, <b>{MARRIEDRATE}%</b> of the" + " population in this zip code is married.</p>" + "<ul><li>{MARRIED_CY} people are married</li>" + "<li>{NEVMARR_CY} have never married</li>" + "<li>{DIVORCD_CY} are divorced</li><ul>";但PopupTemplate内容可以通过函数的形式进行自定义,通过函数的方式进行内容的拼接,以及其中按钮点击函数的赋予。这种直接在PopupTemplate内容中就进行点击事件函数的赋予则不存在找不到按钮进行赋予函数的现象,使得PopupTemplate自定义的内容显得格外流畅。
let emergencyPointTemplate = new EsriPopupTemplate(); emergencyPointTemplate.title = '应急点:{NAME_1}'; emergencyPointTemplate.content = emergencyPointTemplateContent; function emergencyPointTemplateContent (feature) { let descInfo = buildingWebScene.emergencyBuildings.find(function (building) { return building.buildingId === feature.graphic.attributes.OBJECTID; }).emergencyDesc; // 内容最外部的Div let emergencyContentDiv = document.createElement('div'); // 实现:应急事件描述信息 // <p style="display: grid;">应急点描述信息:'</p> let emergencyContentPTagForDescription = document.createElement('p'); emergencyContentPTagForDescription.style = 'display: grid; font-weight: bold; font-size: 16px; margin-bottom: 10px'; emergencyContentPTagForDescription.innerText = '应急点描述信息:'; emergencyContentDiv.appendChild(emergencyContentPTagForDescription); // 实现:应急事件描述 // <span id="Description" style="font-size: 12px;font-style: italic;color: #999999"> // descrInfo // </span> let emergencyContentSpanTagForDescription = document.createElement('span'); emergencyContentSpanTagForDescription.id = 'Description'; emergencyContentSpanTagForDescription.style = 'font-size: 12px;font-style: italic;color: #999999'; emergencyContentSpanTagForDescription.innerText = descInfo; emergencyContentDiv.appendChild(emergencyContentSpanTagForDescription); // 实现:确定应急事件类型 // <p style="display: grid;">确认应急点类型:'</p> let emergencyContentPTagForDeterminingTheTypeOfEmergencyEvents = document.createElement('p'); emergencyContentPTagForDeterminingTheTypeOfEmergencyEvents.style = 'display: grid; ; font-weight: bold; font-size: 16px; margin-top: 15px; margin-bottom: 10px'; emergencyContentPTagForDeterminingTheTypeOfEmergencyEvents.innerText = '确认应急点类型:'; emergencyContentDiv.appendChild(emergencyContentPTagForDeterminingTheTypeOfEmergencyEvents); // <!-- 开始实现应急事件类型的RadioButton组合 --> let emergencyContentDivForEmergencyTypes = document.createElement('div'); emergencyContentDivForEmergencyTypes.style = 'height: 21px'; // <!-- 开始实现自然灾害类型的RadioButton --> // 添加自然灾害类型的RadioButton外层div,用于确定位置 let emergencyContentDivForNaturalDisaster = document.createElement('div'); emergencyContentDivForNaturalDisaster.style = 'float: left; width: 22%'; // 添加自然灾害类型的radio let emergencyContentInputForNaturalDisasterRadio = document.createElement('input'); emergencyContentInputForNaturalDisasterRadio.id = 'naturalDisasters'; emergencyContentInputForNaturalDisasterRadio.name = 'emergency-points-types'; emergencyContentInputForNaturalDisasterRadio.type = 'radio'; emergencyContentDivForNaturalDisaster.appendChild(emergencyContentInputForNaturalDisasterRadio); // 添加自然灾害类型radio的描述文字 let emergencyContentLabelForNaturalDisasterRadio = document.createElement('label'); emergencyContentLabelForNaturalDisasterRadio.for = 'naturalDisasters'; emergencyContentLabelForNaturalDisasterRadio.innerText = '自然灾害'; emergencyContentLabelForNaturalDisasterRadio.style = 'font-size: 14px; line-height: 24px'; emergencyContentDivForNaturalDisaster.appendChild(emergencyContentLabelForNaturalDisasterRadio); // 将自然灾害类型所在的div添加到radio组合所在的div中 emergencyContentDivForEmergencyTypes.appendChild(emergencyContentDivForNaturalDisaster); // <!-- 结束实现自然灾害类型的RadioButton --> // <!-- 开始实现事故灾难类型的RadioButton --> // 添加事故灾难类型的RadioButton外层div,用于确定位置 let emergencyContentDivForAccidentDisaster = document.createElement('div'); emergencyContentDivForAccidentDisaster.style = 'float: left; width: 22%'; // 添加事故灾难类型的radio let emergencyContentInputForAccidentDisasterRadio = document.createElement('input'); emergencyContentInputForAccidentDisasterRadio.id = 'accidentDisasters'; emergencyContentInputForAccidentDisasterRadio.name = 'emergency-points-types'; emergencyContentInputForAccidentDisasterRadio.type = 'radio'; emergencyContentDivForAccidentDisaster.appendChild(emergencyContentInputForAccidentDisasterRadio); // 添加事故灾难类型radio的描述文字 let emergencyContentLabelForAccidentDisasterRadio = document.createElement('label'); emergencyContentLabelForAccidentDisasterRadio.for = 'accidentDisasters'; emergencyContentLabelForAccidentDisasterRadio.innerText = '事故灾难'; emergencyContentLabelForAccidentDisasterRadio.style = 'font-size: 14px; line-height: 24px'; emergencyContentDivForAccidentDisaster.appendChild(emergencyContentLabelForAccidentDisasterRadio); // 将事故灾难类型所在的div添加到radio组合所在的div中 emergencyContentDivForEmergencyTypes.appendChild(emergencyContentDivForAccidentDisaster); // <!-- 结束实现事故灾难类型的RadioButton --> // <!-- 开始实现公共卫生事件类型的RadioButton --> // 添加公共卫生事件类型的RadioButton外层div,用于确定位置 let emergencyContentDivForPublicHealthEvents = document.createElement('div'); emergencyContentDivForPublicHealthEvents.style = 'float: left; width: 28%'; // 添加公共卫生事件类型的radio let emergencyContentInputForPublicHealthEventsRadio = document.createElement('input'); emergencyContentInputForPublicHealthEventsRadio.id = 'publicHealthEvents'; emergencyContentInputForPublicHealthEventsRadio.name = 'emergency-points-types'; emergencyContentInputForPublicHealthEventsRadio.type = 'radio'; emergencyContentDivForPublicHealthEvents.appendChild(emergencyContentInputForPublicHealthEventsRadio); // 添加公共卫生事件类型radio的描述文字 let emergencyContentLabelForPublicHealthEventsRadio = document.createElement('label'); emergencyContentLabelForPublicHealthEventsRadio.for = 'publicHealthEvents'; emergencyContentLabelForPublicHealthEventsRadio.innerText = '公共卫生事件'; emergencyContentLabelForPublicHealthEventsRadio.style = 'font-size: 14px; line-height: 24px'; emergencyContentDivForPublicHealthEvents.appendChild(emergencyContentLabelForPublicHealthEventsRadio); // 将公共卫生事件类型所在的div添加到radio组合所在的div中 emergencyContentDivForEmergencyTypes.appendChild(emergencyContentDivForPublicHealthEvents); // <!-- 结束实现公共卫生事件类型的RadioButton --> // <!-- 开始实现社会安全事件类型的RadioButton --> // 添加社会安全事件类型的RadioButton外层div,用于确定位置 let emergencyContentDivForSocialSecurityIncidents = document.createElement('div'); emergencyContentDivForSocialSecurityIncidents.style = 'float: left; width: 28%'; // 添加社会安全事件类型的radio let emergencyContentInputForSocialSecurityIncidentsRadio = document.createElement('input'); emergencyContentInputForSocialSecurityIncidentsRadio.id = 'socialSecurityIncidents'; emergencyContentInputForSocialSecurityIncidentsRadio.name = 'emergency-points-types'; emergencyContentInputForSocialSecurityIncidentsRadio.type = 'radio'; emergencyContentDivForSocialSecurityIncidents.appendChild(emergencyContentInputForSocialSecurityIncidentsRadio); // 添加社会安全事件类型radio的描述文字 let emergencyContentLabelForSocialSecurityIncidentsRadio = document.createElement('label'); emergencyContentLabelForSocialSecurityIncidentsRadio.for = 'socialSecurityIncidents'; emergencyContentLabelForSocialSecurityIncidentsRadio.innerText = '社会安全事件'; emergencyContentLabelForSocialSecurityIncidentsRadio.style = 'font-size: 14px; line-height: 24px'; emergencyContentDivForSocialSecurityIncidents.appendChild(emergencyContentLabelForSocialSecurityIncidentsRadio); // 将社会安全事件类型所在的div添加到radio组合所在的div中 emergencyContentDivForEmergencyTypes.appendChild(emergencyContentDivForSocialSecurityIncidents); // 当该Building已选择时,则渲染radio不可选 let radios = [emergencyContentInputForNaturalDisasterRadio, emergencyContentInputForAccidentDisasterRadio, emergencyContentInputForPublicHealthEventsRadio, emergencyContentInputForSocialSecurityIncidentsRadio]; let nowEmergencyPointsType = store.state.emergencyPointsTypesRecord.find(function (item) { return item.buildingId === feature.graphic.attributes.OBJECTID; }); if (nowEmergencyPointsType) { let selectedRadio = radios.find(function (radioItem) { return radioItem.id === nowEmergencyPointsType.type; }); selectedRadio.checked = true; for (let i = 0; i < radios.length; i++) { radios[i].disabled = true; } } // <!-- 结束实现社会安全事件类型的RadioButton --> emergencyContentDiv.appendChild(emergencyContentDivForEmergencyTypes); // <!-- 结束实现应急事件类型的RadioButton组合 --> // <!-- 开始实现已确认类型的应急事件和确定按钮组合 --> // 添加最外层div let emergencyContentDivForLast = document.createElement('div'); emergencyContentDivForLast.style = 'margin-top: 15px'; emergencyContentDiv.appendChild(emergencyContentDivForLast); // 添加已确认的应急事件外层的div let emergencyContentDivForConfirmedEmergenciesCount = document.createElement('div'); emergencyContentDivForConfirmedEmergenciesCount.style = 'float: left; width: 50%'; emergencyContentDivForLast.appendChild(emergencyContentDivForConfirmedEmergenciesCount); // 添加已确认的应急事件描述文字 let emergencyContentPForConfirmedEmergenciesDesc = document.createElement('p'); emergencyContentPForConfirmedEmergenciesDesc.innerText = '已确认:'; emergencyContentPForConfirmedEmergenciesDesc.style = 'font-size: 14px;color: #999999;margin: 25px 0px 0px 15px;'; emergencyContentDivForConfirmedEmergenciesCount.appendChild(emergencyContentPForConfirmedEmergenciesDesc); // 添加已确认的应急事件个数和总的事件个数 let emergencyContentSpanForConfirmedEmergencies = document.createElement('span'); emergencyContentSpanForConfirmedEmergencies.style = 'font-size: 14px;font-style: italic;color: #999999'; emergencyContentSpanForConfirmedEmergencies.innerText = store.state.emergencyPointsTypesRecord.length + '/' + buildingWebScene.emergencyBuildings.length; emergencyContentPForConfirmedEmergenciesDesc.appendChild(emergencyContentSpanForConfirmedEmergencies); // 添加确认按钮外层的div let emergencyContentDivForConfirmButton = document.createElement('div'); emergencyContentDivForConfirmButton.style = 'float: right; width: 50%'; emergencyContentDivForLast.appendChild(emergencyContentDivForConfirmButton); // 添加确认按钮 let emergencyContentButtonForConfirmButton = document.createElement('button'); emergencyContentButtonForConfirmButton.className = 'esvopc_btn'; emergencyContentButtonForConfirmButton.style = 'float: right'; emergencyContentButtonForConfirmButton.onclick = function () { let type, nowBuildingCorrectness; const nowBuilding = buildingWebScene.emergencyBuildings.find(function (obj) { return obj.buildingId === feature.graphic.attributes.OBJECTID; }); const obj = document.getElementsByTagName('input'); for (let i = 0; i < obj.length; i++) { if (obj[i].checked) { type = obj[i].id; } } if (type === undefined) { store.dispatch('changeisShowEmergencyPointTypeSelectionWarningComponentVisibleStatus'); } else { nowBuildingCorrectness = nowBuilding.emergencyType === type; let designatedBuildingFeature = store.state.designatedBuildingsFeature.find(function (item) { return item.buildingId === feature.graphic.attributes.OBJECTID; }); let emergencyPointsTypesRecord = { name: feature.graphic.attributes.NAME_1, geometry: designatedBuildingFeature.geometry, type: type, buildingId: feature.graphic.attributes.OBJECTID, correctness: nowBuildingCorrectness, emergencyDesc: nowBuilding.emergencyDesc, Judgementbasis: '描述该事件的判断依据', conclusion: nowBuilding.emergencyType }; store.dispatch('addEmergencyPointsTypesRecord', emergencyPointsTypesRecord); if (!nowBuildingCorrectness) { let RecordIndex = store.state.emergencyPointsTypesErrorListRecord.length + 1; let emergencyPointsErrorTypeRecord = { name: feature.graphic.attributes.NAME_1, geometry: designatedBuildingFeature.geometry, index: RecordIndex, type: type, buildingId: feature.graphic.attributes.OBJECTID, correctness: nowBuildingCorrectness, emergencyDesc: nowBuilding.emergencyDesc, Judgementbasis: '描述该事件的判断依据', conclusion: nowBuilding.emergencyType }; store.dispatch('addEmergencyPointsErrorTypeRecord', emergencyPointsErrorTypeRecord); } let correctnessCounts = 0; store.state.emergencyPointsTypesRecord.map(function (Record, key) { if (!Record.correctness) { correctnessCounts = correctnessCounts + 1; } }); if (!store.state.isShowEmergencyPointTypeErrorListComponent && correctnessCounts === 1) { store.dispatch('changeEmergencyPointTypeErrorListComponentVisibleStatus'); } emergencyContentSpanForConfirmedEmergencies.innerHTML = store.state.emergencyPointsTypesRecord.length + '/' + buildingWebScene.emergencyBuildings.length; emergencyContentButtonForConfirmButton.disabled = true; emergencyContentButtonForConfirmButton.innerHTML = '已选择'; store.dispatch('deleteNotSelectedEmergencyPoint', emergencyPointsTypesRecord); for (let i = 0; i < obj.length; i++) { obj[i].disabled = true; } } }; // 根据查询列表中是否存在当前应急点类型记录实例来渲染按钮 if (!nowEmergencyPointsType) { emergencyContentButtonForConfirmButton.innerText = '确定'; } else { emergencyContentButtonForConfirmButton.disabled = true; emergencyContentButtonForConfirmButton.innerText = '已选择'; } emergencyContentDivForConfirmButton.appendChild(emergencyContentButtonForConfirmButton); // <!-- 结束实现已确认类型的应急事件和确定按钮组合 --> return emergencyContentDiv; }当然还可以在内容自定义中实例化多个函数并在特定条件下进行点击事件函数的切换。 在按钮中赋予类名,并在css文件中添加样式,使得按钮更加美观,但在内容自定义中的按钮是无法使用第三方组件的(如:elementui)
链接: https://developers.arcgis.com/javascript/latest/api-reference/esri-PopupTemplate.html.