1 /*************************************** 2 * Copyright 2011, 2012 GlobWeb contributors. 3 * 4 * This file is part of GlobWeb. 5 * 6 * GlobWeb is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation, version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * GlobWeb is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GlobWeb. If not, see <http://www.gnu.org/licenses/>. 18 ***************************************/ 19 20 define( function() { 21 22 /**************************************************************************************************************/ 23 24 /** @export 25 @constructor 26 GoogleMouseNavigationHandler constructor 27 */ 28 var GoogleMouseNavigationHandler = function(options){ 29 30 /**************************************************************************************************************/ 31 32 /** 33 * Private variables 34 */ 35 36 var _navigation = null; 37 var _pressedButton = -1; 38 var _lastMouseX = -1; 39 var _lastMouseY = -1; 40 var _needsStartEvent = false; 41 var _needsEndEvent = false; 42 var _dx = 0; 43 var _dy = 0; 44 var _pressedGeo = null; 45 var _changeInertia = null; 46 var _slower = 0; 47 48 /**************************************************************************************************************/ 49 50 /** 51 * Private methods 52 */ 53 54 /** 55 Event handler for mouse wheel 56 */ 57 var _handleMouseWheel = function(event) 58 { 59 _navigation.globe.publish("startNavigation"); 60 61 var factor; 62 63 // Check differences between firefox and the rest of the world 64 if ( event.wheelDelta === undefined) 65 { 66 factor = event.detail; 67 } 68 else 69 { 70 factor = -event.wheelDelta / 120.0; 71 } 72 73 if (!_navigation.inertia ) 74 { 75 // Compute mouse position and corresponding lon lat before zoom 76 var pos = _navigation.globe.renderContext.getXYRelativeToCanvas(event); 77 var geo = _navigation.globe.getLonLatFromPixel( pos[0], pos[1] ); 78 } 79 80 _navigation.zoom(factor); 81 82 // Stop all animations when an event is received 83 _navigation.stopAnimations(); 84 85 // Launch inertia if needed 86 if ( _navigation.inertia ) 87 { 88 _navigation.inertia.launch("zoom", factor < 0 ? -1 : 1 ); 89 } 90 else{ 91 // Compute the new position of lon lat and pan the globe toward it 92 if(geo){ 93 var pos2 = _navigation.globe.getPixelFromLonLat(geo[0], geo[1]); 94 95 var dx = pos[0] - pos2[0]; 96 var widthHeightFactor = Math.round(_navigation.globe.renderContext.canvas.width / _navigation.globe.renderContext.canvas.height); 97 widthHeightFactor = (widthHeightFactor < 1) ? 1 : widthHeightFactor; 98 dx *= widthHeightFactor; 99 var dy = pos[1] - pos2[1]; 100 _navigation.pan(dx, dy); 101 } 102 } 103 104 // Stop mouse wheel to be propagated, because default is to scroll the page 105 // This is need when using Firefox event listener on DOMMouseScroll 106 if ( event.preventDefault ) 107 { 108 event.preventDefault(); 109 } 110 event.returnValue = false; 111 112 _navigation.globe.publish("endNavigation"); 113 _navigation.globe.renderContext.requestFrame(); 114 115 // Return false to stop mouse wheel to be propagated when using onmousewheel 116 return false; 117 }; 118 119 /** 120 * Event handler for mouse down 121 */ 122 var _handleMouseDown = function(event) 123 { 124 _pressedButton = event.button; 125 126 // Stop all animations when an event is received 127 _navigation.stopAnimations(); 128 129 _lastMouseX = event.clientX; 130 _lastMouseY = event.clientY; 131 _dx = 0; 132 _dy = 0; 133 134 // Middle click 135 if (event.button == 1){ 136 // Cursor's style modification: Rotating icon 137 _navigation.globe.renderContext.canvas.style.cursor = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABeUlEQVR42u2XS07DMBCGbaCCQstzy4YDcAGWCAE3YI3omsN0XcSaGxSEWHIBDsCGLY9SykM80m/CFLkhIBycVpVi6ZetUez/S2x5JtYMudkCYJQBbGJ+pBoIgMybQKUoijrW2hnGr+jNFyILQM+8jHkLc0Nv6OeIPflC+AJ8M++1rBA+AD+a/wfCB2Bczdtp5gmIqkK8hwSQt69gcNu3gJ6BRGyB7kG/QlAAOe3rSD5zFeO6cwj3ibVRC52hTmgA2YJJVUUgML5wAFbVXN78RRV0C+TZMVUZLWJ86QCsELsxn3v/oQp6CN02hZYwvnIAloldo2efhQqAAqAAGKl7IL4JpQDpWyA9F8iVHfwmjHMBZnd/yIbzJodcEGdDtInJ0S/1wA7DE5NDNozrATSLtjE7SKmI9hg20b3JoR74qogUYgvThnMIa8SOHfPgFVEaxAbmh5jvMj71Nc8CkISYRmvoHD36mmcFcCFKOhbDgf0XuHOH9mcUrHUBoVXvIfh2krcAAAAASUVORK5CYII=), auto'; 138 } 139 // Left and right click 140 else{ 141 // Save the lon lat clicked 142 var pressedPos = _navigation.globe.renderContext.getXYRelativeToCanvas(event); 143 _pressedGeo = _navigation.globe.getLonLatFromPixel( pressedPos[0], pressedPos[1] ); 144 145 // Left click 146 if(event.button == 0){ 147 // Cursor's style modification: Grabbing icon 148 _navigation.globe.renderContext.canvas.style.cursor = 'url(data:image/png;base64,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), auto'; 149 150 } 151 // Right click 152 else{ 153 // Cursor's style modification: Zooming (same as Rotating) icon 154 _navigation.globe.renderContext.canvas.style.cursor = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABeUlEQVR42u2XS07DMBCGbaCCQstzy4YDcAGWCAE3YI3omsN0XcSaGxSEWHIBDsCGLY9SykM80m/CFLkhIBycVpVi6ZetUez/S2x5JtYMudkCYJQBbGJ+pBoIgMybQKUoijrW2hnGr+jNFyILQM+8jHkLc0Nv6OeIPflC+AJ8M++1rBA+AD+a/wfCB2Bczdtp5gmIqkK8hwSQt69gcNu3gJ6BRGyB7kG/QlAAOe3rSD5zFeO6cwj3ibVRC52hTmgA2YJJVUUgML5wAFbVXN78RRV0C+TZMVUZLWJ86QCsELsxn3v/oQp6CN02hZYwvnIAloldo2efhQqAAqAAGKl7IL4JpQDpWyA9F8iVHfwmjHMBZnd/yIbzJodcEGdDtInJ0S/1wA7DE5NDNozrATSLtjE7SKmI9hg20b3JoR74qogUYgvThnMIa8SOHfPgFVEaxAbmh5jvMj71Nc8CkISYRmvoHD36mmcFcCFKOhbDgf0XuHOH9mcUrHUBoVXvIfh2krcAAAAASUVORK5CYII=), auto'; 155 } 156 } 157 158 _needsStartEvent = true; 159 160 // Return false to stop mouse down to be propagated when using onmousedown 161 return false; 162 163 }; 164 165 /** 166 * Event handler for mouse up 167 */ 168 var _handleMouseUp = function(event) 169 { 170 // No button pressed anymore 171 _pressedButton = -1; 172 173 if ( _navigation.inertia && (_dx != 0 || _dy != 0) ) 174 { 175 // Left click 176 if ( event.button == 0 ) 177 { 178 //different behavior if the move has change from pan to rotate 179 if(_changeInertia){ 180 _navigation.inertia.launch("rotate", _changeInertia, 0 ); 181 } 182 else{ 183 _navigation.inertia.launch("pan", _dx, _dy ); 184 } 185 186 } 187 // Middle click 188 else if ( event.button == 1 ) 189 { 190 _navigation.inertia.launch("rotate", -_dx, -_dy ); 191 } 192 } 193 194 // Cursor's style modification : Hand icon 195 _navigation.globe.renderContext.canvas.style.cursor = 'url(data:image/png;base64,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), auto'; 196 197 _pressedGeo = null; 198 _slower = 0; 199 200 if (_needsEndEvent ) { 201 _navigation.globe.publish("endNavigation"); 202 } 203 204 _needsStartEvent = false; 205 _needsEndEvent = false; 206 207 // Stop mouse up event 208 return false; 209 }; 210 211 /** 212 Event handler for mouse move 213 */ 214 var _handleMouseMove = function(event) 215 { 216 // No button pressed 217 if (_pressedButton < 0) 218 return; 219 220 _dx = (event.clientX - _lastMouseX); 221 _dy = (event.clientY - _lastMouseY); 222 223 if ( _dx == 0 && _dy == 0 ) 224 return; 225 226 var ret = false; 227 // Pan on Left click 228 if ( _pressedButton == 0 ) 229 { 230 if ( _needsStartEvent ) { 231 _navigation.globe.publish("startNavigation"); 232 _needsStartEvent = false; 233 _needsEndEvent = true; 234 } 235 236 // Compute the mouse position 237 var pos = _navigation.globe.renderContext.getXYRelativeToCanvas(event); 238 if(_pressedGeo){ 239 _changeInertia=null; 240 var inside = _navigation.globe.getLonLatFromPixel(pos[0], pos[1]); 241 if(inside){ 242 var pos2 = _navigation.globe.getPixelFromLonLat(_pressedGeo[0], _pressedGeo[1]); 243 _dx = pos[0] - pos2[0]; 244 _dy = pos[1] - pos2[1]; 245 _navigation.pan( _dx, _dy ); 246 } 247 } 248 // If the mouse not on the globe 249 if(!_pressedGeo || !inside){ 250 if(Math.abs(_dx) > Math.abs(_dy)){ 251 _changeInertia = (pos[1] > (_navigation.globe.renderContext.canvas.height/2)) ? -_dx : _dx; 252 } 253 else{ 254 _changeInertia = (pos[0] > (_navigation.globe.renderContext.canvas.width/2)) ? _dy : -_dy; 255 } 256 _navigation.rotate(_changeInertia,0); 257 pos = _navigation.globe.renderContext.getXYRelativeToCanvas(event); 258 _pressedGeo = _navigation.globe.getLonLatFromPixel(pos[0], pos[1]); 259 if(_pressedGeo) _changeInertia=null; 260 } 261 262 _navigation.globe.renderContext.requestFrame(); 263 ret = true; 264 } 265 // Rotate on Middle click 266 else if ( _pressedButton == 1 ) 267 { 268 _navigation.rotate(-_dx,-_dy); 269 _navigation.globe.renderContext.requestFrame(); 270 ret = true; 271 } 272 // Zoom on Right click 273 else 274 { 275 // Mouse move is too fast for zooming, need to slow it down 276 _slower++; 277 if((_slower % 3 == 0) && ( _slower > 1 )){ 278 279 _navigation.globe.publish("startNavigation"); 280 281 _navigation.zoom(-_dy/10); 282 283 if(_dy > 0 && _dy > _dx){ 284 // Compute the new position of lon lat and pan the globe toward it 285 if(_pressedGeo){ 286 287 var pos = [_navigation.globe.renderContext.canvas.clientLeft+(_navigation.globe.renderContext.canvas.clientWidth / 2), _navigation.globe.renderContext.canvas.clientTop+(_navigation.globe.renderContext.canvas.clientHeight / 2)]; 288 var pos2 = _navigation.globe.getPixelFromLonLat(_pressedGeo[0], _pressedGeo[1]); 289 290 var dx = pos[0] - pos2[0]; 291 dx = dx * 10 / 100; 292 var dy = pos[1] - pos2[1]; 293 dy = dy * 10 / 100; 294 295 _navigation.pan(dx, dy); 296 } 297 } 298 299 // Stop all animations when an event is received 300 _navigation.stopAnimations(); 301 302 _navigation.globe.publish("endNavigation"); 303 _navigation.globe.renderContext.requestFrame(); 304 } 305 306 ret = true; 307 } 308 309 _lastMouseX = event.clientX; 310 _lastMouseY = event.clientY; 311 312 return ret; 313 }; 314 315 /** 316 Event handler for mouse double click 317 */ 318 var _handleMouseDblClick = function(event) 319 { 320 if (event.button == 0) 321 { 322 var pos = _navigation.globe.renderContext.getXYRelativeToCanvas(event); 323 var geo = _navigation.globe.getLonLatFromPixel( pos[0], pos[1] ); 324 325 if (geo) 326 { 327 _navigation.zoomTo(geo); 328 } 329 } 330 }; 331 332 /** 333 Event handler for mouse context menu 334 */ 335 var _handleContextMenu = function(event) 336 { 337 // Need this so browser's context menu won't show up when using right click zooming 338 event.preventDefault(); 339 return false; 340 }; 341 342 343 /**************************************************************************************************************/ 344 345 /** 346 * Public methods 347 */ 348 349 /** 350 * Setup the default event handlers for the _navigation 351 */ 352 this.install = function(nav) 353 { 354 _navigation = nav; 355 356 var canvas = _navigation.globe.renderContext.canvas; 357 358 // Cursor's style modification : Hand icon 359 canvas.style.cursor = 'url(data:image/png;base64,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), auto'; 360 361 362 // Setup the mouse event handlers 363 canvas.addEventListener("mousedown", _handleMouseDown); 364 document.addEventListener("mouseup", _handleMouseUp); 365 canvas.addEventListener("mousemove", _handleMouseMove); 366 canvas.addEventListener("contextmenu", _handleContextMenu); 367 canvas.addEventListener("dblclick", _handleMouseDblClick); 368 369 // For Firefox 370 canvas.addEventListener("DOMMouseScroll", _handleMouseWheel); 371 canvas.addEventListener("mousewheel", _handleMouseWheel); 372 }; 373 374 /** 375 * Remove the default event handlers for the _navigation 376 */ 377 this.uninstall = function() 378 { 379 // Setup the mouse event handlers 380 var canvas = _navigation.globe.renderContext.canvas; 381 382 canvas.style.cursor = 'auto'; 383 384 canvas.removeEventListener("mousedown", _handleMouseDown); 385 document.removeEventListener("mouseup", _handleMouseUp); 386 canvas.removeEventListener("mousemove", _handleMouseMove); 387 canvas.removeEventListener("contextmenu", _handleContextMenu); 388 canvas.removeEventListener("dblclick", _handleMouseDblClick); 389 390 // For Firefox 391 canvas.removeEventListener("DOMMouseScroll", _handleMouseWheel); 392 canvas.removeEventListener("mousewheel", _handleMouseWheel); 393 }; 394 }; 395 396 return GoogleMouseNavigationHandler; 397 398 }); 399 400