{"id":13701367,"url":"https://github.com/terikon/marker-animate-unobtrusive","last_synced_at":"2025-04-04T15:12:01.853Z","repository":{"id":28629095,"uuid":"32147919","full_name":"terikon/marker-animate-unobtrusive","owner":"terikon","description":"Google Maps markers become animated, unobtrusively","archived":false,"fork":false,"pushed_at":"2024-08-27T20:39:50.000Z","size":1829,"stargazers_count":222,"open_issues_count":19,"forks_count":49,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-03-28T14:11:12.504Z","etag":null,"topics":["google-maps","marker-move","markers"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/terikon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-03-13T09:43:23.000Z","updated_at":"2024-01-05T14:15:01.000Z","dependencies_parsed_at":"2025-03-21T13:13:33.565Z","dependency_job_id":"cbe4708a-7cb6-407b-a87b-e6aa26d60918","html_url":"https://github.com/terikon/marker-animate-unobtrusive","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terikon%2Fmarker-animate-unobtrusive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terikon%2Fmarker-animate-unobtrusive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terikon%2Fmarker-animate-unobtrusive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terikon%2Fmarker-animate-unobtrusive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/terikon","download_url":"https://codeload.github.com/terikon/marker-animate-unobtrusive/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247198469,"owners_count":20900081,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google-maps","marker-move","markers"],"created_at":"2024-08-02T20:01:33.179Z","updated_at":"2025-04-04T15:12:01.820Z","avatar_url":"https://github.com/terikon.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# marker-animate-unobtrusive aka SlidingMarker\n\n[![Build Status](https://travis-ci.org/terikon/marker-animate-unobtrusive.svg?branch=master)](https://travis-ci.org/terikon/marker-animate-unobtrusive)\n\nEnables a Google Maps marker to move from its original position to its destination in a natural, animated way\n(unlike the current method of suddenly appearing on the destination spot). Please click on the map below in order to see\nhow it works. Select destination on the map to move marker to.\n\n[![alt tag](http://terikon.github.io/marker-animate-unobtrusive/demo/screenshots/SlidingMarker.jpg)](http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/markermove-sliding.html)\n\nIt can work in two modes.\n\n- In one mode, you create SlidingMarker instead of google.maps.Marker. SlidingMarker inherits google's\nmarker, so working with it is pretty straight-forward.\n\n- In other mode, SlidingMarker replaces google.maps.Marker with itself, so you just can just forget about it and enjoy\nnice and smooth movement of all of your markers.\n\nIn both cases, animated and non-animated marker will behave exactly the same.\n\nmarker.getPosition() will always return final destination of marker, and position_changed event will only trigger when\nmovement starts. That's why it called unobtrusive - your current code will not even notice animation, it's completely\ntransparent.\n\nSlidingMarker is a complete rewrite of markerAnimateUnobtrusive library, with much-much more features and greatly improved\narchitecture.\n\n# Table of contents\n\n- [Install](#install)\n- [Use](#use)\n- [Demo](#demo)\n- [API](#api)\n- [AMD](#amd)\n- [MarkerWithGhost](#markerwithghost)\n- [Integration with OverlappingMarkerSpiderfier](#integration-with-overlappingmarkerspiderfier)\n- [Under the hood](#under-the-hood)\n- [Things to consider for future versions](#things-to-consider-for-future-versions)\n- [Contribute](#contribute)\n\nThis project is based on excellent [marker-animate](https://github.com/combatwombat/marker-animate) project by Robert Gerlach.\n\nThis project is one big step towards animated [OverlappingMarkerSpiderfier](https://github.com/jawj/OverlappingMarkerSpiderfier).\n\n# Install\n\n## with npm\n\n```\nnpm install marker-animate-unobtrusive\n```\n\n## with bower\n\n```\nbower install marker-animate-unobtrusive\n```\n\n## TypeScript support\n\n```\nnpm install @types/googlemaps --save\nnpm install @types/marker-animate-unobtrusive --save\n```\n\nOr with typings:\n\n```\ntypings install dt~google.maps --global --save\ntypings install dt~marker-animate-unobtrusive --global --save\n```\n\nNo need to import anything. See [demo TypeScript project](https://github.com/terikon/marker-animate-unobtrusive/tree/master/demo/typescript)\nfor reference.\n\n## include on page\n\nDownload **SlidingMarker.js**\n[minified](https://raw.githubusercontent.com/terikon/marker-animate-unobtrusive/master/dist/SlidingMarker.min.js) or\n[debug](https://raw.githubusercontent.com/terikon/marker-animate-unobtrusive/master/SlidingMarker.js)\nfrom Github, and include it in your page.\n\nSlidingMarker depends on Google Maps and [jquery](http://jquery.com/download) libraries, so include them as well.\n\njquery.easing may be downloaded from [here](http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js).\n\nDownload marker-animate [from here](https://raw.githubusercontent.com/combatwombat/marker-animate/master/markerAnimate.js).\n\nSo dependencies look like follows:\n\n```html\n\u003c!-- Dependencies --\u003e\n\n\u003c!-- jquery library and jquery.easing plugin are needed --\u003e\n\u003cscript src=\"jquery.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"jquery.easing.1.3.js\"\u003e\u003c/script\u003e\n\n\u003c!-- we provide marker for google maps, so here it comes  --\u003e\n\u003cscript src=\"https://maps.googleapis.com/maps/api/js?sensor=false\"\u003e\u003c/script\u003e\n\n\u003c!-- we use markerAnimate to actually animate marker --\u003e\n\u003cscript src=\"markerAnimate.js\"\u003e\u003c/script\u003e\n\n\u003c!-- SlidingMarker hides details from you - your markers are just animated automagically --\u003e\n\u003cscript src=\"SlidingMarker.min.js\"\u003e\u003c/script\u003e\n```\nAlternatively, the library can be downloaded from CDN:\n\n```html\n\u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/marker-animate-unobtrusive/0.2.8/vendor/markerAnimate.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/marker-animate-unobtrusive/0.2.8/SlidingMarker.min.js\"\u003e\u003c/script\u003e\n```\n\nNote: [jQuery](http://jquery.com/download) is soft dependency, you can prefer not to include it. But if you decide not to,\nyou should provide [alternative animation routine](#SlidingMarker.options.animateFunctionAdapter), and should not include\njquery.easing and markerAnimate libraries.\n\nAll needed dependencies are in [vendor](https://github.com/terikon/marker-animate-unobtrusive/tree/master/vendor) folder.\n\n## NW.js\n\nThe library is compatible with [NW.js](http://nwjs.io). Use it following way:\n\n```html\n\u003cscript type=\"text/javascript\" src=\"http://maps.google.com/maps/api/js?sensor=true\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\"\u003e\n  global.google = google;\n\u003c/script\u003e\n\u003cscript type=\"text/javascript\" src=\"app.js\"\u003e\u003c/script\u003e\n```\n\n```js\nvar SlidingMarker = require('marker-animate-unobtrusive');\nvar marker = new SlidingMarker();\n```\n\n# Use\n\n## locally\n\nWhen you create marker, instantiate SlidingMarker instance with same parameter you used to instantiate google.maps.Marker:\n\n```js\n//old code\n//var marker = new google.maps.Marker();\n\n//new code\nvar marker = new SlidingMarker();\n```\n\n## globally\n\nIf you want to make all markers on map animate, first of all, call SlidingMarker.initializeGlobally() method.\nDo it as soon as SlidingMarker script loads, before any other script:  \n\n```html\n\u003cscript src=\"SlidingMarker.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  SlidingMarker.initializeGlobally();\n\u003c/script\u003e\n```\n\nThat's it. Now all marker movements will be animated, e.g. :\n\n```js\nvar marker = new google.maps.Marker();\n...\nmarker.setPosition(latLng); //Will cause smooth animation\n```\n\n# API\n\n**SlidingMarker** object that inherits google.maps.Marker is created in global scope (on injected with [AMD](#amd)), with following method in it:\n\n\u003ca name=\"SlidingMarker.initializeGlobally\"\u003e\u003c/a\u003e\n[SlidingMarker.initializeGlobally()](#SlidingMarker.initializeGlobally) when called, replaces google.maps.Marker with SlidingMarker, so all\nmarkers of google maps will be animated.\n\nSlidingMarker has all the events, methods and options of google.maps.Marker - that's its beauty.\n\n- **getPosition()** function returns discrete position, instead of animated one. That means that when one calls setPosition()\nand animation is in place, getPosition() will return final position instead of intermediate. Use\n[getAnimationPosition()](#getAnimationPosition) to retrieve intermediate position.\n\n- **position_changed** event will be raised one time per call to setPosition(), even when animation is in place. To receive\nupdates on animated movement, use [animationposition_changed](#animationposition_changed) event.\n\nIn addition, following options are supported to fine-tune animation for each marker:\n\n- **easing** - \"easeInOutQuint\" by default. Possible values are same as in\n[jquery.easing](http://gsgd.co.uk/sandbox/jquery/easing/) library.\n- **duration** - in ms, 1000 by default.\n\u003ca name=\"SlidingMarker.options.animateFunctionAdapter\"\u003e\u003c/a\u003e\n- **animateFunctionAdapter** - by default, SlidingMarker assumes that google.maps.Marker.prototype is enhanced with animateTo method, but you can provide alternative animation adapter. It should be function with following declaration:\nanimateFunctionAdapter(marker, destPosition, easing, duration). If destPosition provided is null, adapter should stop animation.\n\nExample:\n\n```js\nvar marker = new SlidingMarker({\n    position: myLatlng,\n    map: map,\n    title: \"I'm sliding marker\",\n    duration: 2000,\n    easing: \"easeOutExpo\"\n});\n...\n// use marker as ordinal google map's marker.\n// few animation customizations are also possible.\nmarker.setDuration(1000);\n```\n\nThere are few additions to SlidingMarker instance:\n\n\u003ca name=\"SlidingMarker.setDuration\"\u003e\u003c/a\u003e\n[setDuration(duration)](#SlidingMarker.setDuration) sets duration of animation for marker, in ms.\n\n\u003ca name=\"SlidingMarker.getDuration\"\u003e\u003c/a\u003e\n[getDuration()](#SlidingMarker.getDuration) returns duration of animation.\n\n\u003ca name=\"SlidingMarker.setEasing\"\u003e\u003c/a\u003e\n[setEasing(easing)](#SlidingMarker.setEasing) sets easing type of animation.\n\n\u003ca name=\"SlidingMarker.getEasing\"\u003e\u003c/a\u003e\n[getEasing()](#SlidingMarker.getEasing) return easing type.\n\n\u003ca name=\"SlidingMarker.getAnimationPosition\"\u003e\u003c/a\u003e\n[getAnimationPosition()](#SlidingMarker.getAnimationPosition) returns position of animated marker.\n\n\u003ca name=\"SlidingMarker.setPositionNotAnimated\"\u003e\u003c/a\u003e\n[setPositionNotAnimated(position)](#SlidingMarker.setPositionNotAnimated) performs original not animated setPosition() on marker.\n\n\u003ca name=\"SlidingMarker.animationposition_changed\"\u003e\u003c/a\u003e\n[animationposition_changed](#SlidingMarker.animationposition_changed) event is raised when position of visible animated marker changes.\n\n\n# Demo\n\nDemos reside in [demo](https://github.com/terikon/marker-animate-unobtrusive/tree/master/demo) folder.\n\nIn following demo you can see that position_changed is called in natural way. Click any point on map to see marker move. \n\n[![alt unobtrusive](http://terikon.github.io/marker-animate-unobtrusive/demo/screenshots/SlidingMarker.jpg)](http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/markermove-sliding.html)\n\nYou can use SlidingMarker with other libraries that enhance original marker, like\n[MarkerWithLabel](http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerwithlabel/docs/reference.html) or\n[Geolocation Marker](http://google-maps-utility-library-v3.googlecode.com/svn/trunk/geolocationmarker/docs/reference.html).\n\nIt can be used with [OverlappingMarkerSpiderfier](https://github.com/jawj/OverlappingMarkerSpiderfier) as well:\n\n[![alt unobtrusive](http://terikon.github.io/marker-animate-unobtrusive/demo/screenshots/oms.jpg)](http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/map-oms-animate.html)\n\nHere is animated MarkerWithLabel for a first time:\n\n[![alt unobtrusive](http://terikon.github.io/marker-animate-unobtrusive/demo/screenshots/markerWithLabel.jpg)](http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/markerwithlabelmove-sliding.html)\n\nHere is animated version of Geolocation Marker:\n\n[![alt unobtrusive](http://terikon.github.io/marker-animate-unobtrusive/demo/screenshots/geolocationmarker.jpg)](http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/geolocationmarker-sliding.html)\n\nIt can be used with InfoWindow:\n\n[![alt unobtrusive](http://terikon.github.io/marker-animate-unobtrusive/demo/screenshots/infowindow.jpg)](http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/markermove-infowindow.html)\n\nThis demonstrates [MarkerWithGhost](#markerwithghost). Click on map to call setPosition. Right-click to call setGhostPosition.\nOnly the \"ghost\" will move, causing no events.\n\n[![alt unobtrusive](http://terikon.github.io/marker-animate-unobtrusive/demo/screenshots/SlidingMarker.jpg)](http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/markermove-withghost.html)\n\nSometimes libraries should be slightly modified to make use of animation. Animated versions of MarkerWithLabel and\nGeolocation Marker are in [vendor](https://github.com/terikon/marker-animate-unobtrusive/tree/master/vendor) folder.\n\n# AMD\n\nmarker-animate-unobtrusive can be used with [requirejs](http://requirejs.org/).\n\n'jquery' library should be configured with requirejs. marker-animate should be configured as well.\n\n```js\nrequirejs.config({\n  shim: {\n    \"jquery-easing\": [\"jquery\"],\n    \"marker-animate\": { deps: [\"jquery-easing\"] }\n  }\n});\n```\n\nThe usage is simple:\n\n```js\ndefine(['SlidingMarker'], function (SlidingMarker) {\n\t//Use it here\n}\n``` \n\n# MarkerWithGhost\n\nIn addition to SlidingMarker, you can use MarkerWithGhost class. It useful in less scenarios. Example scenario is usage\nwith [OverlappingMarkerSpiderfier](https://github.com/jawj/OverlappingMarkerSpiderfier).\n\nMarkerWithGhost provides \"ghost\" mode. When this mode active, the marker moves as usual, but fires no position_changed\nevents. It's position returned by getPosition method will not change either.\n\nGhost mode is activated by calling setGhostPosition method. It will deactivate as soon as you call to plain setPosition().\n\nGhost will move always and provide ghostPosition property, as well as ghostposition_changed event. When not in \"ghost mode\",\nit will move with marker. When \"ghost mode\" is active, the ghost will move instead of marker.\n\n## API of MarkerWithGhost\n\nMarkerWithGhost inherits SlidingMarker.\n\n\u003ca name=\"MarkerWithGhost.initializeGlobally\"\u003e\u003c/a\u003e\n[MarkerWithGhost.initializeGlobally()](#MarkerWithGhost.initializeGlobally) works just as [same method](#SlidingMarker.initializeGlobally)\nof SlidingMarker.\n\n### instance methods\n\n\u003ca name=\"MarkerWithGhost.setGhostPosition\"\u003e\u003c/a\u003e\n[setGhostPosition(ghostPosition)](#MarkerWithGhost.setGhostPosition) starts \"ghost mode\". Marker moves to provided position,\nbut will not fire position_changed event, and it's position property will not change. To exit \"ghost\" mode call setPosition().\n\n\u003ca name=\"MarkerWithGhost.getGhostPosition\"\u003e\u003c/a\u003e\n[getGhostPosition()](#MarkerWithGhost.getGhostPosition) returns position of ghost. If not in ghost mode, it will be equal to\nposition property.\n\n\u003ca name=\"MarkerWithGhost.getGhostAnimationPosition\"\u003e\u003c/a\u003e\n[getGhostAnimationPosition()](#MarkerWithGhost.getGhostAnimationPosition) return animation position of ghost. If not in \nghost mode, it will be equal to animationPosition property.\n\n### events\n\n\u003ca name=\"MarkerWithGhost.ghostposition_changed\"\u003e\u003c/a\u003e\n[ghostposition_changed](#MarkerWithGhost.ghostposition_changed) fires as position of ghost changes. If not in ghost mode,\nit still will fire.\n\n\u003ca name=\"MarkerWithGhost.ghostanimationposition_changed\"\u003e\u003c/a\u003e\n[ghostanimationposition_changed](#MarkerWithGhost.ghostanimationposition_changed) fires as animationPosition of ghost\nchanges. If not in ghost mode, it still will fire.\n\n# Integration with OverlappingMarkerSpiderfier\n\nIt's possible to add animation to glorious [OverlappingMarkerSpiderfier](https://github.com/jawj/OverlappingMarkerSpiderfier)\nproject by George MacKerron. You can see a demo here, just click a bunch of markers to see them move:\n\n[![alt unobtrusive](http://terikon.github.io/marker-animate-unobtrusive/demo/screenshots/oms.jpg)](http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/map-oms-animate.html)\n\n*Declaimer: I think this demo is one of few things one can stare are indefinitely, along with classic Windows Defragmenter and Mac\nminimize animation :)*\n\nTo achieve this, slightly modified version of oms.js was used that you can find in\n[vendor folder](https://github.com/terikon/marker-animate-unobtrusive/tree/master/vendor), or\nin [this github fork](https://github.com/viskin/OverlappingMarkerSpiderfier/tree/animation).\n\nFor curious ones, the trick to make OverlappingMarkerSpiderfier support animation is to use [MarkerWithGhost](#markerwithghost) instead\nof plain google.maps.Marker, and make oms.js call ghosted properties, e.g. to getGhostPosition() instead of\ngetPosition().\n\nAdditional bonus arises from using MarkerWithGhost, and it is that no unnecessary position_changed events are triggered\nwhen spiderfying occurs. For you, getPostion on your marker will return its actual position, and will not be effected by spiderfier.\n\n# Under the hood\n\n## Imperfection of marker-animate\n\nHere's demonstration of difficulties we met with original [marker-animate](https://github.com/combatwombat/marker-animate) library.\n\n- With it you should call animateTo() method instead of usual setPosition(). We wanted fire-and-forget functionality,\nso all markers will just animate.\n- Huge issue is that original library causes masses of position_changed event while marker is being animated. You can see it in this demo (of original library), with large amount of position_changed event occur: \n\n[![alt obtrusive](http://terikon.github.io/marker-animate-unobtrusive/demo/screenshots/obtrusive.jpg)](http://terikon.github.io/marker-animate-unobtrusive/demo/obtrusive/markermove-obtrusive.html)\n\n- While marker moves in original library, it reports its intermediate position when getPosition() called. If we call\nmarker.setPosition(point), we want to receive the point from marker.getPosition(), and not some useless animation state.\n\nThese facts prevents marker-animate from usage with other libraries that depend on markers.\n\n## Architecture of SlidingMarker\n\nThe solution was to use decorator pattern. SlidingMarker inherits google.maps.Marker, so it can be used anywhere just like\ngoogle.maps.Marker itself. For example, following is true:\n\n```js\nSlidingMarker instanceof google.maps.Marker // true \n```\n\nBut this marker is never attached to the map, even if you call marker.setMap(map). Instead, there's another visible marker,\ncalled _instance, that is attached to the map. You work directly with marker, and every operation you perform on marker is \nredirected to _instance. For example, getMap() method called on marker will call getMap() on _instance .\n\nEvery user event, like click, that triggers on visible _instance marker is redirected back to marker itself.\n\nThis way animation that occur on visible _instance does not interfere with invisible marker that you work with.\n\nSo, storing SlidingMarker takes *2 memory than storing instance of google.maps.Marker. \n\n# Things to consider for future versions\n\n- ~~ Make it possible to use any easing library, not just jquery_easing ~~\n- Make it possible to restore google maps to original state after initializeGlobally() called.\n- Make it possible to stop animation. Animation should stop as well when setPositionNotAnimated is called.\n- Improve speed.\n- Provide support for alternative animation engine, e.g. [Velocity](http://julian.com/research/velocity/).\n- Compile with closure-compiler. Annotations are already provided at [annotations folder](https://github.com/terikon/marker-animate-unobtrusive/tree/master/annotations). \n\n# Contribute\n\nUse [GitHub issues](https://github.com/terikon/marker-animate-unobtrusive/issues) and [Pull Requests](https://github.com/terikon/marker-animate-unobtrusive/pulls).\n\nIdeas are welcome as well :)\n\nTo build:\n\t\n    npm run build\n\nBefore committing, please run jshint:\n\n    npm run jshint\n\nTo run tests:\n\n    npm run test\n    \n\nTests reside in [tests/spec](https://github.com/terikon/marker-animate-unobtrusive/tree/master/tests/spec) folder.\n\nTests are also runnable in browser and debuggable with [tests/SpecRunner.html](\n\u003chttps://github.com/terikon/marker-animate-unobtrusive/tree/master/tests/SpecRunner.html\u003e).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterikon%2Fmarker-animate-unobtrusive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fterikon%2Fmarker-animate-unobtrusive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterikon%2Fmarker-animate-unobtrusive/lists"}