I had a great time out in Palm Springs this year. Saw some great presentations and will be definitely going back over the videos. Looks like ESRI has released many of them in their re-vamped video site.
I presented this year on converting an existing Flex application to AIR and running it offline:
Here's a link to my presentation.
.NET
(1)
AIR
(1)
Algorithms
(1)
ArcGIS
(2)
ArcGIS Server
(7)
ArcMap
(2)
ArcObjects
(6)
arcpy
(1)
Arrays
(1)
AS3
(1)
Bing
(1)
C#
(8)
Clean Code
(1)
Clustering
(1)
COM
(1)
Design Patterns
(1)
Developer Interviews
(1)
Django
(1)
ESRI Developer Summit
(3)
ESRI Flex API
(1)
Flash
(1)
Flex
(7)
fuzzy
(1)
Geometry
(1)
Geoprocessing
(3)
Google
(1)
Imaging
(1)
JavaScript
(2)
Map Tiles
(2)
Mobile
(1)
Nokia
(1)
Offline Mapping
(2)
PIL
(1)
Pixel Bender
(1)
Presentations
(1)
PSU
(2)
PyTables
(1)
Python
(18)
Rasters
(2)
Server Object Extensions
(4)
Sorting
(1)
Spatial Analysis
(1)
SQLite
(1)
Sublime Text 2
(1)
VB
(2)
War
(1)
Where Camp
(1)
Yahoo
(1)
Showing posts with label Flex. Show all posts
Showing posts with label Flex. Show all posts
7.5.12
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.
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:
I would much rather not use a timer to achieve this. If anybody has a better way, please let me know with a comment.
- 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.
15.9.11
Sorting an array on multiple fields of a nested object...
I recently ran into the need to sort an array of AS3 objects by multiple fields of a nested object. In JSON, the AS3 would look sort of like this:
Here's the actual function where I call the sort function:
I would love to hear how others accomplish the same task.
[
{"feature":
{"attributes":{"country":"Brazil", "state":"Bahia"}
{"geometry":.....}
},
{"feature":
{"attributes":{"country":"Brazil", "state":"Sao Paulo"}
{"geometry":.....}
}
]
Ok, so the example above is already sorted, but imagine this sort of array and needing to sort alphabetically descending first by country and then by system. I'm pretty sure that the AS3 sortOn() only handles first-level properties for each object in the array. I chose to write a custom function which would use array.sort():private function nestedTwoColumnSort(array:Array, parentField:String,
sortField1:String, sortField2:String):void
{
function multipleSort(a:Object, b:Object):Object
{
var w:String = a[parentField][sortField1].toLowerCase();
var x:String = b[parentField][sortField1].toLowerCase();
//sort first field
if(w < x)
{
return -1;
}
if(w > x)
{
return 1;
}
//if first field is the same, then sort on second field
if(w == x)
{
var y:String = a[parentField][sortField2].toLowerCase();
var z:String = b[parentField][sortField2].toLowerCase();
if(y < z)
{
return -1;
}
if(y > z)
{
return 1;
}
}
return 0;
}
//Sort once for the first field
array.sort(multipleSort);
//Sort once for second field
array.sort(multipleSort);
}
The nestedTwoColumnSort function takes the array, the name of the nested object, and the two fields you wish to sort by. It then runs the sort once to fully sort the first field, then again banking on all first fields to be the same.Here's the actual function where I call the sort function:
private function onFeaturesLoadComplete(event:AppEvent):void
{
var features:Array = event.data as Array;
this.nestedTwoColumnSort(features, 'attributes', 'country', 'system');
blah blah blah....
There very well might be a better way to do this, but this was pretty straightforward to implement and I'm not seeing any noticeable performance issues in the application (but it also only runs once in the app...). I would love to hear how others accomplish the same task.
16.8.11
Singletonitis
I am a self-loathing user of the Singleton design pattern. Global states make small scale development much less painful, especially when maintaining the state of a user interface in Flex.
Misko Hevery gives a great explanation of why the Singleton design pattern is really an anti-pattern. I am continuing to use Singletons for now, but I think it's time to learn Robotlegs or another dependency injection framework for ActionScript...
Misko Hevery gives a great explanation of why the Singleton design pattern is really an anti-pattern. I am continuing to use Singletons for now, but I think it's time to learn Robotlegs or another dependency injection framework for ActionScript...
24.7.11
Metro DC Flash User's Group
This weekend I had the pleasure of attending a meeting of the Metro DC Flash User's Group. The meeting was held at Center for Digital Imaging Arts of Boston University (satellite location) in Georgetown, DC.
Doug Chaplow first presented on developing for mobile devices with Flash. One of the most important points I took away from his presentation was that AIR for iOS (not really AIR) and AIR for Android now have basically all the same capabilities. For a while, Adobe had been focused on Android during the political turmoil with Apple. Once Apple removed restricts on the cross-compiled apps, Adobe began work again on the cross-compiler for iOS and its now supposedly just as robust as AIR for Android.
One gentlemen in the group also mentioned that if you are writing an app for both iOS (Apple), do not include the word "Android" or "Blackberry" in your code or else it will get rejected by Apple.
Example of what NOT to do in your flash mobile app:
Can anybody confirm if this is true? I wonder if this also applies to comments like:
Don Anderson gave the second presentation on his MVC framework called Rivet. While the framework is still in development, it looks like the key goal was event listener management. In Rivet, it looked like all event listeners for a view are added and removed in a separate controller when a view is activated/deactivated. The architecture was definitely more pure ActionScript focused than Flex. Overall, the presentation was very good and I always welcome any talk on a variation of the Model-View-Controller architecture.
I would really urge anybody in the DC metro area to check out this meetup group. It was a great time and everybody was very friendly and knowledgeable.
Doug Chaplow first presented on developing for mobile devices with Flash. One of the most important points I took away from his presentation was that AIR for iOS (not really AIR) and AIR for Android now have basically all the same capabilities. For a while, Adobe had been focused on Android during the political turmoil with Apple. Once Apple removed restricts on the cross-compiled apps, Adobe began work again on the cross-compiler for iOS and its now supposedly just as robust as AIR for Android.
One gentlemen in the group also mentioned that if you are writing an app for both iOS (Apple), do not include the word "Android" or "Blackberry" in your code or else it will get rejected by Apple.
Example of what NOT to do in your flash mobile app:
switch(OS_NAME)
{
case 'Android':
result = 'Get Rejected From Apple Store';
break;
default:
result = 'Get Rejected From Apple Store';
break;
}
Can anybody confirm if this is true? I wonder if this also applies to comments like:
//Developing for Android is better than for iOS
Don Anderson gave the second presentation on his MVC framework called Rivet. While the framework is still in development, it looks like the key goal was event listener management. In Rivet, it looked like all event listeners for a view are added and removed in a separate controller when a view is activated/deactivated. The architecture was definitely more pure ActionScript focused than Flex. Overall, the presentation was very good and I always welcome any talk on a variation of the Model-View-Controller architecture.
I would really urge anybody in the DC metro area to check out this meetup group. It was a great time and everybody was very friendly and knowledgeable.
18.7.11
Setting Feature Layer maxAllowableOffset property
Derek Swingley from ESRI recently enlightened me on the use of feature layers for the ArcGIS APIs for Flex, JavaScript, and Silverlight.
Max Allowable Offset basically determines the level of geometry generalization when returned from the mapping server. The larger the offset, the greater the simplification. To calculate the appropriate maxAllowableOffset, I am simply using the ground resolution of the current zoom level of the map (AS3):
If you are using a WGS84 Basemap, you can just divide the result above by the number of meters per degree:
These functions make it so that at the equator there should only be one vertex per pixel. I've been wanting a little more stylized features, so I've been adding about 35 - 40% additional offset:
For more information on feature layers, check out Derek's blog posts
Max Allowable Offset basically determines the level of geometry generalization when returned from the mapping server. The larger the offset, the greater the simplification. To calculate the appropriate maxAllowableOffset, I am simply using the ground resolution of the current zoom level of the map (AS3):
private const EARTH_CIRCUM:Number = 2 * 3.14159265 * 6378137;
private function computeAllowableOffset():void
{
fLayer.maxAllowableOffset = (EARTH_CIRCUM / (256 * Math.pow(2, oMap.level)));
}
If you are using a WGS84 Basemap, you can just divide the result above by the number of meters per degree:
private const EARTH_CIRCUM:Number = 2 * 3.14159265 * 6378137;
private function computeAllowableOffset():void
{
fLayer.maxAllowableOffset = (EARTH_CIRCUM / (256 * Math.pow(2, oMap.level))) / (EARTH_CIRCUM / 360);
}
These functions make it so that at the equator there should only be one vertex per pixel. I've been wanting a little more stylized features, so I've been adding about 35 - 40% additional offset:
private const EARTH_CIRCUM:Number = 2 * 3.14159265 * 6378137;
private function computeAllowableOffset():void
{
fLayer.maxAllowableOffset = (EARTH_CIRCUM / (256 * Math.pow(2, oMap.level))) * 1.35;
}
For more information on feature layers, check out Derek's blog posts
26.6.11
Where Camp DC
I had a bunch of fun at Where Camp DC's ignite talks. The format was a 5 minute presentation of 20 auto-incrementing slides (15s per slide). Somehow I gained a second chin and a lisp in the process...
Subscribe to:
Posts (Atom)