Hit me baby one more time!
I love when people ask me some interesting questions about how to use the ArcGIS API for JavaScript. Sometimes, they are use cases I never really thought about before, although I use the API daily, everyone has different needs. So when I get a question that makes me go hmmm, I get excited.
I was recently asked about how could you sync a hitTest
across multiple map views. That’s interesting, as I never really thought about it. I’ve seen people want to sync the viewpoitns of multiple views, but a hitTest
, which is a click across multiple views got me thinking.
The first thing that comes to mind is that a hitTest
takes a screenPoint
, which is the x and y location relative the top-left corner of the view. Normally, that’s cool, but if you have two map views in your app, the screenPoint
of the first map view is not the same as the screenPoint
of the second map view since they are in different locations in the browser window.
Luckily, there are a couple of helper methods on the view that can help with this. There is toMap
and toScreen
. What you can do, is take convert the screenPoint
to a mapPoint
, then with the second view, convert the mapPoint
to a new screenPoint
and now you can use that screenPoint
for the hitTest
of your second view.
Follow?
Here are the steps.
- Click on view 1
- Perform
hitTest
on view 1 - Convert
sreenPoint
tomapPoint
- Convert
mapPoint
to newscreenPoint
- Perform
hitTest
on view 2
You can do this by making a couple of generic functions.
function hitView(mapPoint, view, layer) {
const sp = view.toScreen(mapPoint);
view.hitTest(sp)
.then(result => {
view.whenLayerView(layer).then(lview => {
const gs = result.results.map(x => x.graphic);
lview.highlight(gs);
});
});
}
This first function performs a hiTest
on a given view and layer by converting the mapPoint
to a screenPoint
. Then it goes throught the steps of highlighting the feature on the map.
Now you need to add some click events to your views, so let me write a generic function for that.
function onClick(v1, v2, lyr1, lyr2) {
v1.on("click", event => {
event.stopPropagation();
hitView(event.mapPoint, v1, lyr1);
hitView(event.mapPoint, v2, lyr2);
});
}
This second method takes two sets of views and layers. It then calls event.stopPopagation()
to the popup doesn’t show up, and passes the mapPoint
, views, and layers to the hitView
method we just created.
Now we just needd to apply this method to our current views and layers.
onClick(view1, view2, flayer1, flayer2);
onClick(view2, view1, flayer2, flayer1);
This will now keep the hitTest
synced across two different map views.
You can see this sample in action here.
You can also watch a video where I cover this code sample step by step.
You’ll notice I’ve refactored the code in the sample above a bit from the video, but I like it much better now!
Go forth and geohack my friends!
If you like this post, don’t forget to subscibe!