├── LICENSE
├── README.md
├── markerAnimate.js
└── demo
├── markermove.html
└── jquery_easing.js
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2012 Robert Gerlach
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Animated marker movement in Google Maps
2 |
3 | **For a much nicer and unobtrusive marker animation library based on this one, check out [marker-animate-unobtrusive](https://github.com/terikon/marker-animate-unobtrusive)**
4 |
5 | A nice alternative to `marker.setPosition(latLng)`. Include jQuery and jQuery Easing Plugin for more easing options.
6 |
7 | Demo: http://robsite.net/static/markermove/markermove.html (click on the map)
8 |
9 | ## Usage
10 |
11 | Include `markerAnimate.js` after Google Maps and call `animateTo` on a `google.maps.Marker`:
12 |
13 | // params:
14 | // newPosition - the new Position as google.maps.LatLng()
15 | // options.duration - animation duration in ms (default 1000)
16 | // options.easing - easing function from jQuery and/or the jQuery easing plugin (default 'linear')
17 | // options.complete - callback function. Gets called, after the animation has finished
18 |
19 | marker.animateTo(newPosition [, {easing: 'easeOutBounce', duration: 1000, complete: function(){}}]);
20 |
21 | ## Example
22 |
23 | var marker = new google.maps.Marker({position: new google.maps.LatLng(0,0), map: myMap, title: 'Hello World!'});
24 | var newPosition = new google.maps.LatLng(13,42);
25 |
26 | // move marker in 1000ms and with linear animation.
27 | marker.animateTo(newPosition);
28 |
29 | // or with callback and options for easing and duration in milliseconds. Needs jQuery Easing Plugin.
30 | marker.animateTo(newPosition, { easing: "easeOutBounce",
31 | duration: 1000,
32 | complete: function() {
33 | alert("animation complete");
34 | }
35 | });
36 |
--------------------------------------------------------------------------------
/markerAnimate.js:
--------------------------------------------------------------------------------
1 | // Animated Marker Movement. Robert Gerlach 2012-2013 https://github.com/combatwombat/marker-animate
2 | // MIT license
3 | //
4 | // params:
5 | // newPosition - the new Position as google.maps.LatLng()
6 | // options - optional options object (optional)
7 | // options.duration - animation duration in ms (default 1000)
8 | // options.easing - easing function from jQuery and/or the jQuery easing plugin (default 'linear')
9 | // options.complete - callback function. Gets called, after the animation has finished
10 | // options.pan - can be 'center', 'inbounds', or null. center keeps marker centered, in bounds keeps it in bounds (default null)
11 | google.maps.Marker.prototype.animateTo = function(newPosition, options) {
12 | defaultOptions = {
13 | duration: 1000,
14 | easing: 'linear',
15 | complete: null,
16 | pan: null
17 | }
18 | options = options || {};
19 |
20 | // complete missing options
21 | for (key in defaultOptions) {
22 | options[key] = options[key] || defaultOptions[key];
23 | }
24 |
25 | // throw exception if easing function doesn't exist
26 | if (options.easing != 'linear') {
27 | if (typeof jQuery == 'undefined' || !jQuery.easing[options.easing]) {
28 | throw '"' + options.easing + '" easing function doesn\'t exist. Include jQuery and/or the jQuery easing plugin and use the right function name.';
29 | return;
30 | }
31 | }
32 |
33 | // make sure the pan option is valid
34 | if (options.pan !== null) {
35 | if (options.pan !== 'center' && options.pan !== 'inbounds') {
36 | return;
37 | }
38 | }
39 |
40 | window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
41 | window.cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;
42 |
43 | // save current position. prefixed to avoid name collisions. separate for lat/lng to avoid calling lat()/lng() in every frame
44 | this.AT_startPosition_lat = this.getPosition().lat();
45 | this.AT_startPosition_lng = this.getPosition().lng();
46 | var newPosition_lat = newPosition.lat();
47 | var newPosition_lng = newPosition.lng();
48 | var newPoint = new google.maps.LatLng(newPosition.lat(), newPosition.lng());
49 |
50 | if (options.pan === 'center') {
51 | this.map.setCenter(newPoint);
52 | }
53 |
54 | if (options.pan === 'inbounds') {
55 | if (!this.map.getBounds().contains(newPoint)) {
56 | var mapbounds = this.map.getBounds();
57 | mapbounds.extend(newPoint);
58 | this.map.fitBounds(mapbounds);
59 | }
60 | }
61 |
62 | // crossing the 180° meridian and going the long way around the earth?
63 | if (Math.abs(newPosition_lng - this.AT_startPosition_lng) > 180) {
64 | if (newPosition_lng > this.AT_startPosition_lng) {
65 | newPosition_lng -= 360;
66 | } else {
67 | newPosition_lng += 360;
68 | }
69 | }
70 |
71 | var animateStep = function(marker, startTime) {
72 | var ellapsedTime = (new Date()).getTime() - startTime;
73 | var durationRatio = ellapsedTime / options.duration; // 0 - 1
74 | var easingDurationRatio = durationRatio;
75 |
76 | // use jQuery easing if it's not linear
77 | if (options.easing !== 'linear') {
78 | easingDurationRatio = jQuery.easing[options.easing](durationRatio, ellapsedTime, 0, 1, options.duration);
79 | }
80 |
81 | if (durationRatio < 1) {
82 | var deltaPosition = new google.maps.LatLng(marker.AT_startPosition_lat + (newPosition_lat - marker.AT_startPosition_lat) * easingDurationRatio,
83 | marker.AT_startPosition_lng + (newPosition_lng - marker.AT_startPosition_lng) * easingDurationRatio);
84 | marker.setPosition(deltaPosition);
85 |
86 | // use requestAnimationFrame if it exists on this browser. If not, use setTimeout with ~60 fps
87 | if (window.requestAnimationFrame) {
88 | marker.AT_animationHandler = window.requestAnimationFrame(function() {
89 | animateStep(marker, startTime)
90 | });
91 | } else {
92 | marker.AT_animationHandler = setTimeout(function() {
93 | animateStep(marker, startTime)
94 | }, 17);
95 | }
96 |
97 | } else {
98 |
99 | marker.setPosition(newPosition);
100 |
101 | if (typeof options.complete === 'function') {
102 | options.complete();
103 | }
104 |
105 | }
106 | }
107 |
108 | // stop possibly running animation
109 | if (window.cancelAnimationFrame) {
110 | window.cancelAnimationFrame(this.AT_animationHandler);
111 | } else {
112 | clearTimeout(this.AT_animationHandler);
113 | }
114 |
115 | animateStep(this, (new Date()).getTime());
116 | }
--------------------------------------------------------------------------------
/demo/markermove.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |