PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/com/google/maps/extras/dragzoomcontrol/DragZoomControl.as

http://gmaps-utility-library-flash.googlecode.com/
ActionScript | 425 lines | 234 code | 47 blank | 144 comment | 4 complexity | 5b669ba0c56838831045b4b67cba702f MD5 | raw file
  1. /*
  2. * DragZoomControl v1.0
  3. * Author: Brian Richardson
  4. * Email: irieb@mac.com
  5. * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
  6. *
  7. * Magifying glass image pulled from the following source:
  8. * http://commons.wikimedia.org/wiki/File:Gnome-zoom-in.svg
  9. * Used in this component under their GNU General Public License
  10. *
  11. * Enables drag zoom functionality
  12. *
  13. * The control is enabled when a user clicks the magnifying
  14. * glass image.
  15. *
  16. * When the control is enable the control listens for a mouse click
  17. * then mouse move to render the selection area
  18. *
  19. * On mouseUp the map will center the selection and zoom to the
  20. * highest possible level on the selected bounds.
  21. *
  22. * A second magnifying glass will appear to enable the user to
  23. * back out to the last map position
  24. */
  25. package com.google.maps.extras.dragzoomcontrol
  26. {
  27. import com.google.maps.LatLng;
  28. import com.google.maps.LatLngBounds;
  29. import com.google.maps.MapMouseEvent;
  30. import com.google.maps.controls.ControlBase;
  31. import com.google.maps.controls.ControlPosition;
  32. import com.google.maps.interfaces.IMap;
  33. import com.google.maps.overlays.Polyline;
  34. import flash.display.BitmapData;
  35. import flash.display.DisplayObject;
  36. import flash.display.Shape;
  37. import flash.display.Sprite;
  38. import flash.events.MouseEvent;
  39. import flash.filters.BevelFilter;
  40. import flash.filters.BitmapFilterQuality;
  41. import flash.filters.BitmapFilterType;
  42. import flash.geom.Matrix;
  43. import flash.geom.Point;
  44. import flash.text.TextField;
  45. import flash.text.TextFieldAutoSize;
  46. import flash.text.TextFormat;
  47. /**
  48. * Dispatched when a Zoom is committed
  49. *
  50. * @eventType mx.events.FlexEvent.DATA_CHANGE
  51. */
  52. [Event(name="zoomCommit", type="com.google.maps.extras.dragzoomcontrol.events.DragZoomEvent")]
  53. public class DragZoomControl extends ControlBase {
  54. //static constants
  55. private static const ACTIVE_ALPHA:Number = 1;
  56. private static const INACTIVE_ALPHA:Number = .7;
  57. //Default configurable properties values
  58. public static const DEFAULT_SELECTION_BG_COLOR:Number = 0xFFFFFF;
  59. public static const DEFAULT_SELECTION_ALPHA:Number = 0.5;
  60. public static const DEFAUT_LINE_COLOR:Number = 0x000000;
  61. public static const DEFAUT_DRAG_ZOOM_MSG:String = "click and drag mouse to zoom into area";
  62. public static const DEFAULT_MARGIN_TOP:int = 7;
  63. public static const DEFAULT_MARGIN_LEFT:int = 7;
  64. //zoom-in image
  65. [Embed(source="/assets/images/zoom-in.png")]
  66. private var zoomInImg_:Class;
  67. //zoom-out image
  68. [Embed(source="/assets/images/zoom-out.png")]
  69. private var zoomOutImg_:Class;
  70. //configurable properties
  71. private var selectionBGColor_:Number;
  72. private var selectionAlpha_:Number;
  73. private var selectionLineColor_:Number;
  74. private var dragZoomMsg_:String;
  75. private var marginTop_:int;
  76. private var margingLeft_:int;
  77. //private
  78. private var map_:IMap;
  79. private var drawArea_:Sprite;
  80. private var zoomArea_:Shape;
  81. private var startXPos_:int;
  82. private var startYPos_:int;
  83. private var zoomState_:Boolean = false;
  84. private var nwPoint_:Point;
  85. private var swPoint_:Point;
  86. private var nePoint_:Point;
  87. private var sePoint_:Point;
  88. private var zoomInBtn_:Sprite;
  89. private var zoomOutBtn_:Sprite;
  90. private var msg_:Sprite;
  91. private var mapBitmapData_:BitmapData;
  92. private var mapDisplayObject_:DisplayObject;
  93. /**
  94. * Creates the DragZoom control
  95. *
  96. * @constructor
  97. * @param {int} The top margin of the control in points.
  98. * @see #DEFAULT_MARGIN_TOP
  99. * @param {int} The left margin of the control in points.
  100. * @see #DEFAULT_MARGIN_LEFT
  101. * @param {Number} The background color message text.
  102. * @see #DEFAULT_SELECTION_BG_COLOR
  103. * @param {Number} The line color of the selection area.
  104. * @see #DEFAUT_LINE_COLOR
  105. * @param {Number} The alpha value of the selection area.
  106. * @see #DEFAULT_SELECTION_ALPHA
  107. * @param {String} The message displayed on screen when the control is enabled.
  108. * @see #DEFAUT_DRAG_ZOOM_MSG
  109. */
  110. public function DragZoomControl(
  111. optMarginTop:int = DEFAULT_MARGIN_TOP,
  112. optMarginLeft:int = DEFAULT_MARGIN_LEFT,
  113. optSelectionBGColor:Number = DEFAULT_SELECTION_BG_COLOR,
  114. optSelectionLineColor:Number = DEFAUT_LINE_COLOR,
  115. optSelectionAlpha:Number = DEFAULT_SELECTION_ALPHA,
  116. optDragZoomMsg:String = DEFAUT_DRAG_ZOOM_MSG) {
  117. super(new ControlPosition(ControlPosition.ANCHOR_TOP_LEFT, optMarginTop, optMarginLeft));
  118. selectionBGColor_ = optSelectionBGColor;
  119. selectionAlpha_ = optSelectionAlpha;
  120. selectionLineColor_ = optSelectionLineColor;
  121. dragZoomMsg_ = optDragZoomMsg;
  122. marginTop_ = optMarginTop;
  123. margingLeft_ = optMarginLeft;
  124. //default selection effect - possibly make this configurable
  125. var bf:BevelFilter = new BevelFilter(1,
  126. 45,
  127. 0xFFFFFF,
  128. 0.8,
  129. 0x000000,
  130. 0.8,
  131. 5,
  132. 5,
  133. 5,
  134. BitmapFilterQuality.HIGH,
  135. BitmapFilterType.INNER,
  136. true);
  137. drawArea_ = new Sprite();
  138. drawArea_.filters = [bf];
  139. addChild(drawArea_);
  140. }
  141. /**
  142. * Initialize the control
  143. *
  144. * @param {IMap} The instance of the Map the control is being
  145. * added to
  146. * @private
  147. */
  148. public override function initControlWithMap(pMap:IMap):void {
  149. super.initControlWithMap(map);
  150. map_ = pMap;
  151. addControlButton();
  152. }
  153. //*****************
  154. //private functions
  155. //*****************
  156. /**
  157. * @private
  158. * Sets the state of the control to listen
  159. * for Map events in order to render the selection area
  160. *
  161. * Map dragging is disabled as it would interfere with
  162. * the drag control of the selection area
  163. *
  164. * @param {MouseEvent} event The mouse event that triggered the call
  165. */
  166. private function enableDragZoom(event:MouseEvent):void {
  167. msg_.visible = true;
  168. map_.disableDragging();
  169. map_.addEventListener(MapMouseEvent.MOUSE_DOWN, startZoom);
  170. map_.addEventListener(MapMouseEvent.MOUSE_UP, commitZoom);
  171. map_.addEventListener(MapMouseEvent.MOUSE_MOVE, updateZoom);
  172. mapDisplayObject_ = map_ as DisplayObject;
  173. mapBitmapData_= new BitmapData(mapDisplayObject_.width, mapDisplayObject_.height);
  174. //this wil have to wait - sandbox security exception thrown
  175. //we can do all kinds of cool effects once this is supported
  176. //_mapBitmapData.draw(_mapDisplayObject);
  177. }
  178. /**
  179. * @private
  180. * Returns the Map to the last saved position
  181. *
  182. * @param {MouseEvent} event The mouse event
  183. */
  184. private function returnToSavedPosition(event:MouseEvent):void {
  185. zoomOutBtn_.visible = false;
  186. map_.returnToSavedPosition();
  187. }
  188. /**
  189. * @private
  190. * Removes Map event listener and enables map dragging
  191. */
  192. private function disableZoom():void {
  193. map_.removeEventListener(MapMouseEvent.MOUSE_DOWN, startZoom);
  194. map_.removeEventListener(MapMouseEvent.MOUSE_UP, commitZoom);
  195. map_.removeEventListener(MapMouseEvent.MOUSE_MOVE, updateZoom);
  196. map_.enableDragging();
  197. }
  198. /**
  199. * @private
  200. * Updates the selection area.
  201. * Cooridinates are calculated using the latitude/longitude
  202. * provided by the MapMouseEvent
  203. *
  204. * @param {MapMouseEvent} event The mouse event
  205. */
  206. private function updateZoom(event:MapMouseEvent):void {
  207. if (zoomState_) {
  208. var latLgn:LatLng = event.latLng;
  209. var point:Point = map_.fromLatLngToViewport(latLgn);
  210. var zoomWidth:int = (point.x - startXPos_);
  211. var zoomHeight:int = (point.y - startYPos_);
  212. resetDrawArea();
  213. zoomArea_ = new Shape();
  214. var recX:int = (point.x - zoomWidth)-marginTop_;
  215. var recY:int = (point.y - zoomHeight)-margingLeft_;
  216. var myMatrix:Matrix = new Matrix();
  217. myMatrix.tx = -(margingLeft_);
  218. myMatrix.ty = -(marginTop_);
  219. zoomArea_.graphics.beginBitmapFill(mapBitmapData_,myMatrix);
  220. zoomArea_.graphics.lineStyle(1, selectionLineColor_);
  221. zoomArea_.graphics.drawRect(recX, recY, zoomWidth, zoomHeight);
  222. zoomArea_.graphics.endFill();
  223. drawArea_.addChild(zoomArea_);
  224. recX = point.x - zoomWidth;
  225. recY = point.y - zoomHeight;
  226. nwPoint_ = new Point(recX, recY);
  227. swPoint_ = new Point(recX, (recY + zoomArea_.height));
  228. sePoint_ = new Point((recX + zoomArea_.width), (recY + zoomArea_.height));
  229. nePoint_ = new Point((recX + zoomArea_.width), recY);
  230. }
  231. }
  232. /**
  233. * @private
  234. * Commits the Zoom based on the selection area
  235. *
  236. * @param {MapMouseEvent} event The mouse event
  237. */
  238. private function commitZoom(event:MapMouseEvent):void {
  239. disableZoom();
  240. map_.savePosition();
  241. zoomState_ = false;
  242. resetDrawArea();
  243. var latLngBounds:LatLngBounds = calculatePolyline();
  244. positionMap(latLngBounds);
  245. zoomOutBtn_.visible = true;
  246. msg_.visible = false;
  247. mapBitmapData_ = null;
  248. mapDisplayObject_ = null;
  249. var evt:DragZoomEvent = new DragZoomEvent(DragZoomEvent.ZOOM_COMMIT);
  250. evt.bounds = latLngBounds;
  251. dispatchEvent(evt);
  252. }
  253. /**
  254. * @private
  255. * Position the Map
  256. *
  257. * @param {LatLngBounds} pLatLngBounds Latitude/Longtitude bounds
  258. * used to postion the map
  259. */
  260. private function positionMap(pLatLngBounds:LatLngBounds):void {
  261. map_.setCenter(pLatLngBounds.getCenter());
  262. map_.setZoom(map_.getBoundsZoomLevel(pLatLngBounds));
  263. }
  264. /**
  265. * @private
  266. * Sets the x/y point of the initial mouse click
  267. * on the Map
  268. *
  269. * @param {MapMouseEvent} event The mouse event
  270. */
  271. private function startZoom(event:MapMouseEvent):void {
  272. zoomState_ = true;
  273. var point:Point = map_.fromLatLngToViewport(event.latLng);
  274. startXPos_ = point.x;
  275. startYPos_ = point.y;
  276. }
  277. /**
  278. * Removes the selection graphic
  279. *
  280. */
  281. private function resetDrawArea():void {
  282. if (zoomArea_) {
  283. drawArea_.removeChild(zoomArea_);
  284. zoomArea_ = null;
  285. }
  286. }
  287. /**
  288. * @private
  289. * Creates a Polyline based on the graphic selection
  290. *
  291. * The Polyline is then used to create latitude/longtitude bounds
  292. * that are used to center the Map and set the highest possible
  293. * Zoom level for the selection
  294. *
  295. */
  296. private function calculatePolyline():LatLngBounds {
  297. var lines:Array =
  298. [map_.fromViewportToLatLng(nwPoint_),
  299. map_.fromViewportToLatLng(swPoint_),
  300. map_.fromViewportToLatLng(sePoint_),
  301. map_.fromViewportToLatLng(nePoint_),
  302. map_.fromViewportToLatLng(nwPoint_)];
  303. var polyLine:Polyline = new Polyline(lines);
  304. return polyLine.getLatLngBounds();
  305. }
  306. /**
  307. * @private
  308. * Used to create the rollover effect
  309. *
  310. * @param {MouseEvent} event The mouse event
  311. */
  312. private function mouseOver(event:MouseEvent):void {
  313. if (event.target is Sprite) {
  314. var s:Sprite = Sprite(event.target);
  315. s.alpha = ACTIVE_ALPHA;
  316. }
  317. return;
  318. }
  319. /**
  320. * @private
  321. * Used to create the rollout effect
  322. *
  323. * @param {MouseEvent} event The mouse event
  324. */
  325. private function mouseOut(event:MouseEvent):void {
  326. if (event.target is Sprite) {
  327. var s:Sprite = Sprite(event.target);
  328. s.alpha = INACTIVE_ALPHA;
  329. }
  330. return;
  331. }
  332. /**
  333. * @private
  334. * Creates the control buttons (zoom in/zoom out)
  335. *
  336. */
  337. private function addControlButton():void {
  338. zoomInBtn_ = new Sprite();
  339. zoomInBtn_.x = 0;
  340. zoomInBtn_.y = 0;
  341. zoomInBtn_.addChild(DisplayObject(new zoomInImg_()));
  342. zoomInBtn_.addEventListener(MouseEvent.CLICK, enableDragZoom);
  343. zoomInBtn_.addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
  344. zoomInBtn_.addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
  345. zoomInBtn_.alpha = INACTIVE_ALPHA;
  346. zoomOutBtn_ = new Sprite();
  347. zoomOutBtn_.x = zoomInBtn_.width;
  348. zoomOutBtn_.y = 0;
  349. zoomOutBtn_.addChild(DisplayObject(new zoomOutImg_()));
  350. zoomOutBtn_.addEventListener(MouseEvent.CLICK, returnToSavedPosition);
  351. zoomOutBtn_.addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
  352. zoomOutBtn_.addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
  353. zoomOutBtn_.alpha = INACTIVE_ALPHA;
  354. zoomOutBtn_.visible = false;
  355. var center:Point = map_.fromLatLngToViewport(map_.getCenter());
  356. msg_ = new Sprite();
  357. msg_.x = center.x;
  358. msg_.y = 10;
  359. var label:TextField = new TextField();
  360. label.text = dragZoomMsg_;
  361. label.selectable = false;
  362. label.autoSize = TextFieldAutoSize.CENTER;
  363. var format:TextFormat = new TextFormat("Verdana");
  364. label.setTextFormat(format);
  365. var background:Shape = new Shape();
  366. background.graphics.beginFill(selectionBGColor_, selectionAlpha_);
  367. background.graphics.lineStyle(1, selectionLineColor_);
  368. background.graphics.drawRoundRect(label.x, label.y, label.width, label.height, 4);
  369. background.graphics.endFill();
  370. msg_.addChild(background);
  371. msg_.addChild(label);
  372. msg_.visible = false;
  373. addChild(msg_);
  374. addChild(zoomInBtn_);
  375. addChild(zoomOutBtn_);
  376. }
  377. }
  378. }