In our application, we would like to change the mouse cursor whenever the user hover the mouse over a graphic. We've came up with a way to do it using the GraphicsLayer.HitTestAsync() method whenever the mouse move. But I am not sure if this is the best way to do it because as I move my mouse over the map, my CPU spikes to 10-15%. I think this is too costly in terms of performance for such a simple feature.
private async void MapView_MouseMove(object sender, MouseEventArgs e) { Graphic graphic = await HitTestAsync(_mapView, e.GetPosition(_mapView)); UpdateHoveringGraphic(graphic); }
The UpdateHoveringGraphic() function will then determine if the graphic has changed to generate a MouseEnter and MouseLeave event.
We have several GraphicsLayer, so this adds up. Does anyone have any suggestions to accomplish this feature in a less resource intensive way?
Thanks.
Did you ever find a solution to this problem?
No -- we haven't. Sorry.
Still no success?
I'm attempting the same with poor performance. We have multiple layers to hit test, and attempt the following code. Trying to tweak the query for hitLayers doesn't get any real difference in the result, and alone takes about 60ms. The hit testing of 22 layers in this case takes nearly 400ms. I do the hit testing on click, to select graphics, and I have long ago abandoned doing it on mouse move due to poor performance. Any help would be welcome.
var hitLayers = mapView.Map.Layers.EnumerateLeaves()
.Where(m => m.IsVisible)
.OfType<GraphicsLayer>()
.Where(m => m.Graphics != null && m.Graphics.Count > 0)
.OrderBy(m => m.Graphics.Count)
.ToList();
var list = new List<Graphic>();
foreach (var layer in hitLayers)
{
var items = await layer.HitTestAsync(mapView, screenPoint, maxHits).ContinueWith(t => t.Result);
list.AddRange(items);
if (list.Count > maxHits)
{
return list.Take(maxHits);
}
}
return list.Take(maxHits);
Have you tried to see if using the functions that will do identify to all operational layers in one go and compared how that does affect the performance? Do you have performance problems both in Debug and Release modes?
GeoView.IdentifyLayersAsync Method (Point, Double, Boolean, Int64, CancellationToken)
So far we are still on the 10.2.7 release due to the limitations in v100, so IdentifyLayersAsync is not available. There seems to be some performance boost in release mode, but still not fast enough to consider mouse over, even if making sure the cursor has stopped. Since most of the code is executed in the Esri Runtime, why should release mode have such an impact? I know the optimizer is enabled, but the heavy work is still performed in optimized assemblies.
I just created a zero's matrix of size screenWidth x screenHeight. If there's a button at that pixel I filled that matrix entry with the button's index location in an array of its fellow buttons. Checking the mouse screen xy against this matrix will let you tell if you're hovering and what button you're over... This is probably not the greatest idea but I never found any better solutions.
Hi,
I've had same problem with the performance, so i've added a thread timer to the mouse move event.
private readonly TimeSpan _timerTimeSpan = TimeSpan.FromMilliseconds(300);
Timer _tooltipTimer = new Timer(timerElapsed, null, Timeout.Infinite, Timeout.Infinite);
private void MapViewOnMouseMove(object sender, MouseEventArgs e)
{
_mouseEvent = e;
_tooltipTimer.Change(_timerTimeSpan, Timeout.InfiniteTimeSpan);
}private void timerElapsed(object state)
{........
}
saving the last mouse coordinates and trigger the timer again on every mouse move with 300ms.