Hi!
I try to create hover pop up in custom widget (related post: https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/hover-popup-experience-builder-de...). In my opinion, one possible way of implementation is layerId tracking. For example, hitTest() look for layerId on map, if there is graphic element popup is open. When mouse move out from layer popup is close. If there isn't any layer pop up isn't call.
I use these components in code but I can't do anything in right way. It doesn't work. I can't found layerId option and add it to equally method.
Thanks a lot for any advice!
/** @jsx jsx */
import { React, AllWidgetProps, jsx, IMDataSourceInfo, DataSource, DataSourceManager, DataSourceStatus, FeatureLayerQueryParams, DataSourceComponent } from 'jimu-core'
import { JimuMapViewComponent, JimuMapView, FeatureLayerDataSource } from "jimu-arcgis";
import { result } from 'lodash-es';
import View from 'esri/views/View';
import {DataSourceSelector, AllDataSourceTypes, FieldSelector} from 'jimu-ui/advanced/data-source-selector';
import { viewChangeBufferCompare } from 'dist/widgets/arcgis/bookmark/src/setting/utils';
export const myFeatureLayer={} as const
export default class Widget extends React.PureComponent<AllWidgetProps<any>, any>{
state = {
jimuMapView: null,
timer: null,
allLayer: [],
lyr: null
};
getDataSourceByLayer: (layerId: string | number, layerOfSubLayerId?: string) => DataSource
onDataSourceCreated = (ds: DataSource) => {
const datasrc=this.props.useDataSources[0]
const myDatasrc=DataSourceManager.getInstance().getDataSource(dataSrc.dataSourceId) as FeatureLayerDataSource
const myFeatureLayer = myDataSrc.layer
this.setState({ allLayer: myFeatureLayer.layerId, lyr: myFeatureLayer })
}
doHitTest = (evt: PointerEvent) => {
if(this.state.jimuMapView){
// Run hitTest on the map view using the pointer event
this.state.jimuMapView.view.hitTest(evt).then((response) => {
if(response.results.length){
const graphic = response.results.filter(function (result) {
return result.graphic.layer === myFeatureLayer;
})[0].graphic
this.state.jimuMapView.view.popup.open({
location: graphic.geometry.centroid,
features: [graphic]
});
} else {
this.state.jimuMapView.view.popup.close();
}
})
}
}
activeViewChangeHandler = (jmv: JimuMapView) => {
if (jmv) {
this.setState({
jimuMapView: jmv
});
// register the pointer-move event handler on the map view
jmv.view.on("pointer-move", (evt) => {
// if there is already a timer, cancel it
if(this.state.timer){
clearTimeout(this.state.timer)
}
// set new timer that will call doHitTest after the interval
// pass the pointer-move event as the parameter to doHitTest
this.setState({
timer: setTimeout(this.doHitTest, 0, evt)
})
});
}
};
render() {
return (
<div className="widget-hoverPopup jimu-widget">
{this.props.hasOwnProperty("useMapWidgetIds") &&
this.props.useMapWidgetIds &&
this.props.useMapWidgetIds[0] && (
<JimuMapViewComponent
useMapWidgetId={this.props.useMapWidgetIds?.[0]}
onActiveViewChange={this.activeViewChangeHandler}
/>
)
}
</div>
);
}
}
Hi there,
So I tried my best to understand what problem you are trying to solve. I apologize if I did not understand the issue you are trying to solve. Seems like you want to display popupTemplate for only selected layers when user moves the mouse over the map? At least I think this is what you are asking.
Displaying popupTemplate from pointer-move is intense. So I suggest you use debounce method to improve the app performance.
The MapView.hittest method lets you specify which layers you want to include in the hittest result. So you can specify the layers there. This way the hittest will return results only for those layers. You can also set the exclude to specify layers to be excluded from the hittest. Hope this helps!
The following codepen app displays popupTemplate from pointer-move event. It uses include parameter to specify to only include cities feature layer to be included in the hittest. It also uses debounce for the hittest so you can "debounce", or cancel the function execution, until the previous execution of the same function call finishes.
https://codepen.io/U_B_U/pen/KKBZmzq?editors=1000
@UndralBatsukh Hi!
Thank you very much for this advice! I have been sitting on this task for several weeks...
Actually, I want to create universal popup widget for any map that we add to the Map widget in Experience Builder (Dev edition; see attachment). My problem is that I can't (don't know) how to declare, specify the layer / featureLayer.
In your example featureLayer declare in simple way. It's cool! But when I do that I get the error.
Does the Experience Builder allow to create a pop-up window for some specific graphic layer? How can this be done?
Thank you very much!
Just in case, I am attaching the widget code.