flash on 2011-3-14

by kikiroom
♥0 | Line 286 | Modified 2011-03-14 00:50:29 | MIT License
play

ActionScript3 source code

/**
 * Copyright kikiroom ( http://wonderfl.net/user/kikiroom )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/47wJ
 */

<!--

 Copyright 2010 Google Inc. 
 Licensed under the Apache License, Version 2.0: 
 http://www.apache.org/licenses/LICENSE-2.0 
 
-->

<mx:Application layout="absolute" width="512" height="618" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#FFFFFF, #FFFFFF]">

<mx:Script>

            import com.google.maps.LatLngBounds;
        
</mx:Script>
<maps:Map3D mapevent_mappreinitialize="onMapPreinitialize(event)" mapevent_mapready="onMapReady(event)" id="map" width="512" height="390" key="ABQIAAAAileP5HJrxmFV0kOk2fke8BQGj0PqsCtxKvarsoS-iqLdqZSKfxQxinA9ISZ9agV9VWN-NZQKaGAr5g" sensor="false" themeColor="#FFFFFF"/>

<mx:ColumnChart id="chart" width="512" height="192" showDataTips="true" x="0" y="426" itemRollOver="chartRollOver(event)" itemRollOut="chartRollOut(event)" seriesFilters="[]" dataTipFunction="dtFunc" columnWidthRatio="1.0">

<mx:verticalAxis>
<mx:LinearAxis title="Elevation (m)"/>
</mx:verticalAxis>

<mx:horizontalAxisRenderer>
<mx:AxisRenderer showLabels="false"/>
</mx:horizontalAxisRenderer>

<mx:series>
<mx:ColumnSeries yField="elevation" displayName="Elevation" dataProvider="{elevations}"/>
</mx:series>
</mx:ColumnChart>

<mx:Script>

        import mx.charts.AreaChart;
        import mx.charts.HitData;
        import mx.charts.events.ChartItemEvent;
   
        import com.google.maps.LatLng;
        import com.google.maps.Map3D;
        import com.google.maps.MapEvent;
        import com.google.maps.MapOptions;
        import com.google.maps.MapType;
        import com.google.maps.View;
        import com.google.maps.geom.Attitude;
        import com.google.maps.MapMouseEvent;
        import com.google.maps.overlays.Marker;
        import com.google.maps.overlays.Polyline;
        import com.google.maps.overlays.PolylineOptions;
        import com.google.maps.services.Directions;
        import com.google.maps.services.DirectionsEvent;
        import com.google.maps.services.Elevation;
        import com.google.maps.services.ElevationEvent;
        import com.google.maps.services.ClientGeocoder;
        import com.google.maps.services.GeocodingEvent;
        import com.google.maps.overlays.MarkerOptions;    
        import com.google.maps.controls.MapTypeControl;
        import com.google.maps.controls.NavigationControl;
        import com.google.maps.services.Directions;
        import com.google.maps.services.DirectionsOptions;
  
 
        private var directionsService:Directions = null;
        private var elevationService:Elevation = null;
        private var geocodingService:ClientGeocoder = null;
        
        private var rollOverMarker:Marker = null;
        private var markers:Array = [];
        private var polyline:Polyline = null;
        private var zoom:int = 12;
        
        [Bindable]
        private var elevations:Array = null;

        private var SAMPLES:int = 250;
        
        private function onMapPreinitialize(event:MapEvent):void {
          var myMapOptions:MapOptions = new MapOptions();
          myMapOptions.zoom = zoom;
          myMapOptions.center = new LatLng(40.756054, -73.986951);
          myMapOptions.mapType = MapType.NORMAL_MAP_TYPE;
          myMapOptions.viewMode = View.VIEWMODE_PERSPECTIVE;
          myMapOptions.attitude = new Attitude(0,30,0);
          map.setInitOptions(myMapOptions);
              
          this.elevationService = new Elevation();
          this.elevationService.addEventListener(ElevationEvent.ELEVATION_SUCCESS, plotElevation);
          this.elevationService.addEventListener(ElevationEvent.ELEVATION_FAILURE, elevationError);
         
          this.directionsService = new Directions();
          this.directionsService.addEventListener(DirectionsEvent.DIRECTIONS_SUCCESS, getRouteElevation);
          this.directionsService.addEventListener(DirectionsEvent.DIRECTIONS_FAILURE, directionsError);
          
          this.geocodingService = new ClientGeocoder();
          this.geocodingService.addEventListener(GeocodingEvent.GEOCODING_SUCCESS, addAddress);
          this.geocodingService.addEventListener(GeocodingEvent.GEOCODING_FAILURE, geocodingError);
            
          this.map.addEventListener(MapMouseEvent.CLICK, function(event:MapMouseEvent):void {
            addMarker(event.latLng, true);
          });
        }
        
        private function onMapReady(event:MapEvent):void {
          map.addControl(new MapTypeControl());
          map.addControl(new NavigationControl());
          addMarker(new LatLng(37.80805,-122.426544), false);
          addMarker(new LatLng(37.802116,-122.418884), false);
          addMarker(new LatLng(37.800404,-122.409743), false);
          addMarker(new LatLng(37.799844,-122.398907), true);
          recenterMap();
        }
        
        private function addMarker(latLng:LatLng, doQuery:Boolean):void {
          if (markers.length < 10) {
              
            var marker:Marker = new Marker(latLng, new MarkerOptions({
              draggable: true
            }));
              
            marker.addEventListener(MapMouseEvent.DRAG_END, function(event:MapMouseEvent):void {
              updateElevation();
            });
            
            map.addOverlay(marker);
            markers.push(marker);
              
            if (doQuery) {
              updateElevation();
            }
              
            if (markers.length == 10) {
              address.enabled = false;
            }
          } else {
             popup.title = "Points limit reached";
             error.text = "No more than 10 points can be added.";
             popup.visible = true;
          }
        }

        private function addAddress(event:GeocodingEvent):void {
          address.text = "";
          var latlng:LatLng = event.response.placemarks[0].point;
          addMarker(latlng, true);
          recenterMap();
        }
      
        private function recenterMap():void {          
          if (markers.length > 0) {
              zoom = 16;
            var center:LatLng = markers[0].getLatLng();
            var pitch:Number = map.getAttitude().pitch;     
                     
            if (markers.length > 1) {
              var bounds:LatLngBounds = new LatLngBounds();
              
              for (var i:int = 0; i < markers.length; i++) {
                bounds.extend(markers[i].getLatLng());
              }
              center = bounds.getCenter();
              zoom = map.getBoundsZoomLevel(bounds);
            }
            map.setCenter(center, zoom);
            map.setAttitude(new Attitude(0, pitch, 0));
          }
        }
        
        private function updateElevation():void {
          if (markers.length > 1) {
            var latlngs:Array = [];
            for (var i:int = 0; i < markers.length; i++) {
              latlngs.push(markers[i].getLatLng())
            }
            if (mode.selectedIndex > 0) {
              directionsService.setOptions(new DirectionsOptions({
                 travelMode: (mode.selectedIndex == 1 ?
                DirectionsOptions.TRAVEL_MODE_DRIVING :
                DirectionsOptions.TRAVEL_MODE_WALKING)
              }));
             directionsService.loadFromWaypoints(latlngs);
            } else {
              elevationService.loadElevationAlongPath(latlngs, SAMPLES);
            }
          }
        }
        
        private function getRouteElevation(event:DirectionsEvent):void {
          elevationService.loadElevationAlongEncodedPath(event.directions.encodedPolylineData, SAMPLES);
        }
        
        private function plotElevation(event:ElevationEvent):void {
          elevations = event.elevations;
          
          var path:Array = [];

          for (var i:int = 0; i < elevations.length; i++) {
            path.push(elevations[i].location);
          }
          
          if (polyline) {
            map.removeOverlay(polyline);
          }
          
          polyline = new Polyline(path, new PolylineOptions({
            geodesic: true,
            strokeStyle: {
              color: 0x000000,
              alpha: 0.9,
              thickness: 3.0,
              pixelHinting: true
            }
          }));
          
          map.addOverlay(polyline);
        }
        
        private function chartRollOver(event:ChartItemEvent):void {
          if (rollOverMarker == null) {
            rollOverMarker = new Marker(event.hitData.item.location,
              new MarkerOptions({
                fillStyle: {
                  color: 0x00d000
                }
              }));
              map.addOverlay(rollOverMarker);
            } else {
              rollOverMarker.visible = true;
            }
          var location:LatLng = event.hitData.item.location;
          rollOverMarker.setLatLng(location);
            
          var yaw:Number = getBearing(event.hitData.chartItem.index);
          var pitch:Number = 45 + getGradient(event.hitData.chartItem.index);
          map.cancelFlyTo();
          map.flyTo(location, zoom + 2, new Attitude(yaw, pitch, 0.5));
        }
        
        private function chartRollOut(event:ChartItemEvent):void {
          if (rollOverMarker != null) {
            rollOverMarker.visible = false;
          }
        }
        
        public function dtFunc(hd:HitData):String {
          return "<B>Elevation: </B>" + Math.round(hd.item.elevation) + "m<br/>" + 
                 "<B>Gradient: </B>" + Math.round(getGradient(hd.chartItem.index)) + "°";
        }
        
        private function reset():void {
          map.clearOverlays();
          polyline = null;
          rollOverMarker = null;
          markers = new Array();
          elevations = new Array();
          address.enabled = true;
       }
       
       private function getGradient(id:int):Number {
         var id0:int = (id - 1 < 0 ? id : id - 1);
         var id1:int = (id + 1 == elevations.length ? id : id + 1);
         var location0:LatLng = elevations[id0].location;
         var location1:LatLng = elevations[id1].location;
         var locationDelta:Number = location0.distanceFrom(location1);
            
         var elevation0:Number = elevations[id0].elevation;
         var elevation1:Number = elevations[id1].elevation;
         var elevationDelta:Number = elevation1 - elevation0;
            
         var gradient:Number = Math.atan2(elevationDelta, locationDelta);
         return deg(gradient);
       }
        
       private function geocodingError(event:GeocodingEvent):void {
         popup.title = "Address lookup failed";
         error.text = "Address not found.";
         popup.visible = true;
       }

       private function directionsError(event:DirectionsEvent):void {
         popup.title = "Address lookup failed";
         error.text = "Could not generate a route between these points.";
         popup.visible = true;
       }
       
       private function elevationError(event:ElevationEvent):void {
         popup.title = "Elevation lookup failed";
         error.text = "Could not obtain an elevation profile for this route.";
         popup.visible = true;
         elevations = new Array();
       }
                
       private function getBearing(id:int):Number {
         var id0:int = (id - 1 < 0 ? id : id - 1);
         var id1:int = (id + 1 == elevations.length ? id : id + 1);
         var location0:LatLng = elevations[id0].location;
         var location1:LatLng = elevations[id1].location;
         return rhumbBearing(location0, location1);   
       }
    
      /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
      /*  Based on the spherical geodesy formulae & scripts (c) Chris Veness 2002-2010   */
      /*   - www.movable-type.co.uk/scripts/latlong.html                                 */
      /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */   
       private function rhumbBearing(location0:LatLng, location1:LatLng):Number {
         var lat1:Number = rad(location0.lat()), lat2:Number = rad(location1.lat());
         var dLng:Number = rad((location1.lng()-location0.lng()));

         var dPhi:Number = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4));
         if (Math.abs(dLng) > Math.PI) dLng = dLng>0 ? -(2*Math.PI-dLng) : (2*Math.PI+dLng);
         var brng:Number = Math.atan2(dLng, dPhi);

         return (deg(brng)+360) % 360;
       }
       
       private function deg(r:Number):Number {
         return r * 180 / Math.PI;
       }
       
       private function rad(d:Number):Number {
         return d * Math.PI / 180;
       }
  
</mx:Script>
<mx:TextInput x="61.5" y="398" id="address" enter="geocodingService.geocode(address.text)" width="113"/>
<mx:Text x="5.5" y="400" text="Address:" width="57"/>
<mx:Text x="182.5" y="400" text="Mode of transport:"/>

<mx:ComboBox x="299.5" y="398" id="mode" change="updateElevation()" selectedIndex="1" width="106">

<mx:ArrayCollection>
<mx:String>Direct</mx:String>
<mx:String>Driving</mx:String>
<mx:String>Walking</mx:String>
</mx:ArrayCollection>
</mx:ComboBox>
<mx:Button x="413.5" y="398" label="Clear points" id="clear" buttonDown="reset()"/>

<mx:TitleWindow x="195" y="176" width="250" height="124" layout="absolute" id="popup" visible="false" backgroundColor="#FFFFFF">
<mx:TextArea x="10" y="10" height="35" width="210" id="error" borderThickness="0" borderStyle="none"/>
<mx:Button x="93.5" y="52" label="OK" buttonDown="popup.visible=false"/>
</mx:TitleWindow>
<mx:HRule x="0" y="389" width="512"/>
</mx:Application>