13.10.11

Managing MapMouseEvents: Double-click zoom vs. showing infowindow (ESRI Flex API 2.4)

Apps built with the ESRI Flex API have the default behavior of zooming-in when you double-click on the map.  This is a great feature, but the double-click and single-click dispatch the same event may confuse your handler functions. 
  • When you click once on the map, MapMouseEvent.MAP_CLICK is dispatched.
  • When you double-click, MapMouseEvent.MAP_CLICK is dispatched twice before zooming begins.

Here is a great example of the events which are dispatched with the Flex API.

If you are listening to MapMouseEvent.MAP_CLICK to show an infowindow, the infowindow will open during the double-click zoom which I consider an undesirable behavior.

You can see the behavior I am trying to fix here.

The fix which I am using involves using a timer in the single-click handler to wait and see if a second MAP_CLICK event is dispatched.  If so, I assume that a double-click zoom is going on and I don't let the infowindow open.

Here is the code from the example above modified so the infowindow does not appear during a double-click:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:esri="http://www.esri.com/2008/ags"
               pageTitle="MapClick - click map to get current location">
    <fx:Script>
        <![CDATA[
            import com.esri.ags.events.MapMouseEvent;
            import com.esri.ags.geometry.MapPoint;
            import com.esri.ags.utils.WebMercatorUtil;
            
            /**
             * This whole timer business here is to deal with the
             * double-click zoom vs. the single click info window issue.
             * 
             * If another MAP_CLICK event is heard within the alloted time
             * then the infowindow will not open.
             */ 
            private const eventTimer:Timer = new Timer(300, 1);
            private function onMapClick(event:MapMouseEvent):void 
            {
                function onTimerComplete(timerEvent:TimerEvent):void
                {
                    this.eventTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
                    var latlong:MapPoint = WebMercatorUtil.webMercatorToGeographic(event.mapPoint) as MapPoint;
                    myMap.infoWindow.label = "You clicked at "
                        + event.mapPoint.x.toFixed(1) + " / " + event.mapPoint.y.toFixed(1)
                        + "\nLat/Long is: " + latlong.y.toFixed(6)
                        + " / " + latlong.x.toFixed(6);
                    myMap.infoWindow.show(event.mapPoint);
                }
                
                //If timer is already running then don't show the infowindow
                if(eventTimer.running)
                {
                    this.eventTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
                    this.eventTimer.stop();
                    return;
                }
                
                eventTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
                eventTimer.start();
            }
        ]]>
    </fx:Script>
    
    <esri:Map id="myMap"
              mapClick="onMapClick(event)"
              scale="50000000">
        <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"/>
    </esri:Map>
</s:Application>


I would much rather not use a timer to achieve this.  If anybody has a better way, please let me know with a comment.

No comments:

Post a Comment