overlapping-marker-spiderfier
Version:
Deals with overlapping markers in Google Maps JS API v3, Google Earth-style
7 lines • 12.8 kB
JavaScript
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.OverlappingMarkerSpiderfier=t():e.OverlappingMarkerSpiderfier=t()}(this,function(){return function(e){function t(r){if(i[r])return i[r].exports;var n=i[r]={exports:{},id:r,loaded:!1};return e[r].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var i={};return t.m=e,t.c=i,t.p="/dist/",t(0)}([function(e,t,i){e.exports=i(1)},function(e,t){/** @preserve OverlappingMarkerSpiderfier
https://github.com/jawj/OverlappingMarkerSpiderfier
Copyright (c) 2011 - 2013 George MacKerron
Released under the MIT licence: http://opensource.org/licenses/mit-license
Note: The Google Maps API v3 must be included *before* this code
*/
var i={}.hasOwnProperty,r=[].slice;this.OverlappingMarkerSpiderfier=function(){function e(e,r){var n,s,o,l,a,u;this.map=e,null==r&&(r={});for(o in r)i.call(r,o)&&(u=r[o],this[o]=u);for(this.projHelper=new this.constructor.ProjHelper(this.map),this.initMarkerArrays(),this.listeners={},a=["click","zoom_changed","maptypeid_changed"],s=0,l=a.length;l>s;s++)n=a[s],t.addListener(this.map,n,function(e){return function(){return e.unspiderfy()}}(this));this.nudgeStackedMarkers&&t.addListenerOnce(this.map,"idle",function(e){return function(){return t.addListener(e.map,"zoom_changed",function(){return e.mapZoomChangeListener()}),e.mapZoomChangeListener()}}(this))}var t,n,s,o,l,a,u;return a=e.prototype,n=google.maps,t=n.event,l=n.MapTypeId,u=2*Math.PI,a.keepSpiderfied=!1,a.markersWontHide=!1,a.markersWontMove=!1,a.spiderfiedShadowColor="white",a.nudgeStackedMarkers=!0,a.minNudgeZoomLevel=8,a.nudgeRadius=1,a.markerCountInBaseNudgeLevel=9,a.maxNudgeCount=9,a.nudgeBucketSize=12,a.nearbyDistance=20,a.circleSpiralSwitchover=9,a.circleFootSeparation=23,a.circleStartAngle=u/12,a.spiralFootSeparation=26,a.spiralLengthStart=11,a.spiralLengthFactor=4,a.spiderfiedZIndex=1e3,a.usualLegZIndex=10,a.highlightedLegZIndex=20,a.event="click",a.minZoomLevel=!1,a.lineToCenter=!0,a.legWeight=1.5,a.legColors={usual:{},highlighted:{}},o=a.legColors.usual,s=a.legColors.highlighted,o[l.HYBRID]=o[l.SATELLITE]="#fff",s[l.HYBRID]=s[l.SATELLITE]="#f00",o[l.TERRAIN]=o[l.ROADMAP]="#444",s[l.TERRAIN]=s[l.ROADMAP]="#f00",a.initMarkerArrays=function(){return this.markers=[],this.markerListenerRefs=[]},a.addMarker=function(e){var i;return null!=e._oms?this:(e._oms=!0,i=[t.addListener(e,this.event,function(t){return function(i){return t.spiderListener(e,i)}}(this))],this.markersWontHide||i.push(t.addListener(e,"visible_changed",function(t){return function(){return t.markerChangeListener(e,!1)}}(this))),this.markersWontMove||i.push(t.addListener(e,"position_changed",function(t){return function(){return t.markerChangeListener(e,!0)}}(this))),this.markerListenerRefs.push(i),this.markers.push(e),this.isNudgingActive()&&this.requestNudge(),this)},a.nudgeTimeout=null,a.requestNudge=function(){return this.nudgeTimeout&&clearTimeout(this.nudgeTimeout),this.nudgeTimeout=setTimeout(function(e){return function(){return e.nudgeAllMarkers()}}(this),10)},a.isNudgingActive=function(){return this.nudgeStackedMarkers&&!(this.minNudgeZoomLevel&&this.map.getZoom()<this.minNudgeZoomLevel)&&!this.spiderfied},a.markerChangeListener=function(e,t){return null==e._omsData||!e._omsData.leg||!t&&e.getVisible()||null!=this.spiderfying||null!=this.unspiderfying?void 0:this.unspiderfy(t?e:null)},a.countsPerLevel=[1,1],a.levelsByCount=[],a.getCountPerNudgeLevel=function(e){return null!=this.countsPerLevel[e]?this.countsPerLevel[e]:this.countsPerLevel[e]=this.getCountPerNudgeLevel(e-1)+Math.pow(2,e-2)*this.markerCountInBaseNudgeLevel},a.getNudgeLevel=function(e){var t;if(null!=this.levelsByCount[e])return this.levelsByCount[e];for(t=0;e>=this.countsPerLevel[t];)t+1>=this.countsPerLevel.length&&this.getCountPerNudgeLevel(t+1),t++;return this.levelsByCount[e]=t-1},a.nudgeAllMarkers=function(){var e,t,i,r,n,s,o,l,a,h,d,g,p,f,m,c,v,k,L,y,P,D,_;if(this.isNudgingActive()){for(m={},r=[],n=[],e=1/((1+this.nudgeBucketSize)*this.nudgeRadius),o=function(t){return function(t){return Math.floor(t.x*e)+","+Math.floor(t.y*e)}}(this),c=this.markers,D=[],l=0,a=c.length;a>l;l++){for(h=c[l],d=!1,p=this.llToPt(null!=(v=null!=(k=h._omsData)?k.usualPosition:void 0)?v:h.position),g={x:p.x,y:p.y},f=o(p);null!=m[f]&&(null==this.maxNudgeCount||this.maxNudgeCount>=m[f]);)s=m[f],m[f]+=1,null!=r[s]?(t=r[s],i=n[s]):(_=this.getNudgeLevel(s),r[s]=t=20*Math.sin(u*s/this.markerCountInBaseNudgeLevel/_)*this.nudgeRadius*_,n[s]=i=20*Math.cos(u*s/this.markerCountInBaseNudgeLevel/_)*this.nudgeRadius*_),p.x=g.x+t,p.y=g.y+i,this.nudged=!0,d=!0,f=o(p);d?(h._omsData=null!=(L=h._omsData)?L:{},h._omsData.usualPosition=null!=(y=null!=(P=h._omsData)?P.usualPosition:void 0)?y:h.position,h.setPosition(this.ptToLl(p))):null!=h._omsData&&null==h._omsData.leg&&(h.setPosition(h._omsData.usualPosition),delete h._omsData),D.push(f in m?void 0:m[f]=1)}return D}},a.resetNudgedMarkers=function(){var e,t,i,r;if(this.nudged){for(r=this.markers,e=0,t=r.length;t>e;e++)i=r[e],null!=i._omsData&&null==i._omsData.leg&&(i.setPosition(i._omsData.usualPosition),delete i._omsData);return delete this.nudged}},a.mapZoomChangeListener=function(){return this.minNudgeZoomLevel&&this.map.getZoom()<this.minNudgeZoomLevel?this.resetNudgedMarkers():this.requestNudge()},a.getMarkers=function(){return this.markers.slice(0)},a.removeMarker=function(e){var i,r,n,s,o;if(null!=e._omsData&&this.unspiderfy(),i=this.arrIndexOf(this.markers,e),0>i)return this;for(o=this.markerListenerRefs.splice(i,1)[0],r=0,n=o.length;n>r;r++)s=o[r],t.removeListener(s);return delete e._oms,this.markers.splice(i,1),this.isNudgingActive()&&this.requestNudge(),this},a.clearMarkers=function(){var e,i,r,n,s,o,l,a,u;for(this.unspiderfy(),u=this.markers,e=i=0,n=u.length;n>i;e=++i){for(a=u[e],l=this.markerListenerRefs[e],r=0,s=l.length;s>r;r++)o=l[r],t.removeListener(o);delete a._oms}return this.initMarkerArrays(),this},a.addListener=function(e,t){var i;return(null!=(i=this.listeners)[e]?i[e]:i[e]=[]).push(t),this},a.removeListener=function(e,t){var i;return i=this.arrIndexOf(this.listeners[e],t),0>i||this.listeners[e].splice(i,1),this},a.clearListeners=function(e){return this.listeners[e]=[],this},a.trigger=function(){var e,t,i,n,s,o,l,a;for(t=arguments[0],e=arguments.length>=2?r.call(arguments,1):[],l=null!=(o=this.listeners[t])?o:[],a=[],n=0,s=l.length;s>n;n++)i=l[n],a.push(i.apply(null,e));return a},a.generatePtsCircle=function(e,t){var i,r,s,o,l,a,h,d;for(s=this.circleFootSeparation*(2+e),a=s/u,r=u/e,d=[],o=l=0,h=e;h>=0?h>l:l>h;o=h>=0?++l:--l)i=this.circleStartAngle+o*r,d.push(new n.Point(t.x+a*Math.cos(i),t.y+a*Math.sin(i)));return d},a.generatePtsSpiral=function(e,t){var i,r,s,o,l,a,h;for(o=this.spiralLengthStart,i=0,h=[],r=s=0,a=e;a>=0?a>s:s>a;r=a>=0?++s:--s)i+=this.spiralFootSeparation/o+5e-4*r,l=new n.Point(t.x+o*Math.cos(i),t.y+o*Math.sin(i)),o+=u*this.spiralLengthFactor/i,h.push(l);return h},a.spiderListener=function(e,t){var i,r,n,s,o,l,u,h,d,g,p;if(l=null!=e._omsData&&null!=e._omsData.leg,l&&this.keepSpiderfied||("mouseover"===this.event?(window.clearTimeout(a.timeout),a.timeout=setTimeout(function(e){return function(){return e.unspiderfy()}}(this),3e3)):this.unspiderfy()),l||this.map.getStreetView().getVisible()||"GoogleEarthAPI"===this.map.getMapTypeId()||this.minZoomLevel&&this.map.getZoom()<this.minZoomLevel)return this.trigger("click",e,t);for(h=[],d=[],u=this.nearbyDistance,g=u*u,o=this.llToPt(e.position),p=this.markers,i=0,r=p.length;r>i;i++)n=p[i],null!=n.map&&n.getVisible()&&(s=this.llToPt(n.position),this.ptDistanceSq(s,o)<g?h.push({marker:n,markerPt:s}):d.push(n));return 1===h.length?this.trigger("click",e,t):this.spiderfy(h,d)},a.markersNearMarker=function(e,t){var i,r,n,s,o,l,a,u,h,d,g;if(null==t&&(t=!1),null==this.projHelper.getProjection())throw"Must wait for 'idle' event on map before calling markersNearMarker";for(a=this.nearbyDistance,u=a*a,o=this.llToPt(e.position),l=[],h=this.markers,i=0,r=h.length;r>i&&(n=h[i],!(n!==e&&null!=n.map&&n.getVisible()&&(s=this.llToPt(null!=(d=null!=(g=n._omsData)?g.usualPosition:void 0)?d:n.position),this.ptDistanceSq(s,o)<u&&(l.push(n),t))));i++);return l},a.markersNearAnyOtherMarker=function(){var e,t,i,r,n,s,o,l,a,u,h,d,g,p,f,m,c,v,k,L,y;if(null==this.projHelper.getProjection())throw"Must wait for 'idle' event on map before calling markersNearAnyOtherMarker";for(m=this.nearbyDistance,c=m*m,p=function(){var e,t,i,r,n,s;for(i=this.markers,s=[],e=0,t=i.length;t>e;e++)a=i[e],s.push({pt:this.llToPt(null!=(r=null!=(n=a._omsData)?n.usualPosition:void 0)?r:a.position),willSpiderfy:!1});return s}.call(this),v=this.markers,t=r=0,s=v.length;s>r;t=++r)if(u=v[t],null!=u.map&&u.getVisible()&&(h=p[t],!h.willSpiderfy))for(k=this.markers,i=n=0,o=k.length;o>n;i=++n)if(d=k[i],i!==t&&null!=d.map&&d.getVisible()&&(g=p[i],(!(t>i)||g.willSpiderfy)&&this.ptDistanceSq(h.pt,g.pt)<c)){h.willSpiderfy=g.willSpiderfy=!0;break}for(L=this.markers,y=[],e=f=0,l=L.length;l>f;e=++f)a=L[e],p[e].willSpiderfy&&y.push(a);return y},a.makeHighlightListenerFuncs=function(e){return{highlight:function(t){return function(){var i;return e._omsData.leg.setOptions({strokeColor:t.legColors.highlighted[t.map.mapTypeId],zIndex:t.highlightedLegZIndex}),null!=e._omsData.shadow?(i=e._omsData.shadow.getIcon(),i.fillOpacity=.8,e._omsData.shadow.setOptions({icon:i})):void 0}}(this),unhighlight:function(t){return function(){var i;return e._omsData.leg.setOptions({strokeColor:t.legColors.usual[t.map.mapTypeId],zIndex:t.usualLegZIndex}),null!=e._omsData.shadow?(i=e._omsData.shadow.getIcon(),i.fillOpacity=.3,e._omsData.shadow.setOptions({icon:i})):void 0}}(this)}},a.spiderfy=function(e,i){var r,s,o,l,a,u,h,d,g,p,f,m,c;return this.spiderfying=!0,m=e.length,r=this.ptAverage(function(){var t,i,r;for(r=[],t=0,i=e.length;i>t;t++)p=e[t],r.push(p.markerPt);return r}()),a=m>=this.circleSpiralSwitchover?this.generatePtsSpiral(m,r).reverse():this.generatePtsCircle(m,r),s=this.ptToLl(r),c=function(){var i,r,p,m,c,v;for(v=[],i=0,r=a.length;r>i;i++)l=a[i],o=this.ptToLl(l),f=this.minExtract(e,function(e){return function(t){return e.ptDistanceSq(t.markerPt,l)}}(this)),g=f.marker,d=this.lineToCenter?s:g.position,h=new n.Polyline({map:this.map,path:[d,o],strokeColor:this.legColors.usual[this.map.mapTypeId],strokeWeight:this.legWeight,zIndex:this.usualLegZIndex}),g._omsData=null!=(p=g._omsData)?p:{},g._omsData.usualPosition=null!=(m=null!=(c=g._omsData)?c.usualPosition:void 0)?m:g.position,g._omsData.leg=h,this.spiderfiedShadowColor&&(g._omsData.shadow=new n.Marker({position:o,map:this.map,clickable:!1,zIndex:-2,icon:{path:google.maps.SymbolPath.CIRCLE,fillOpacity:.3,fillColor:this.spiderfiedShadowColor,strokeWeight:0,scale:20}})),this.legColors.highlighted[this.map.mapTypeId]!==this.legColors.usual[this.map.mapTypeId]&&(u=this.makeHighlightListenerFuncs(g),g._omsData.hightlightListeners={highlight:t.addListener(g,"mouseover",u.highlight),unhighlight:t.addListener(g,"mouseout",u.unhighlight)}),g.setPosition(o),g.setZIndex(Math.round(this.spiderfiedZIndex+l.y)),v.push(g);return v}.call(this),delete this.spiderfying,this.spiderfied=!0,this.trigger("spiderfy",c,i)},a.unspiderfy=function(e){var i,r,n,s,o,l,a,u;if(null==e&&(e=null),null==this.spiderfied&&null==this.nudged)return this;for(this.unspiderfying=!0,u=[],o=[],l=this.markers,i=0,r=l.length;r>i;i++)s=l[i],null!=s._omsData&&null!=s._omsData.leg?(s._omsData.leg.setMap(null),null!=(a=s._omsData.shadow)&&a.setMap(null),s!==e&&s.setPosition(s._omsData.usualPosition),s.setZIndex(null),n=s._omsData.hightlightListeners,null!=n&&(t.removeListener(n.highlight),t.removeListener(n.unhighlight)),delete s._omsData,u.push(s)):o.push(s);return delete this.unspiderfying,delete this.spiderfied,this.trigger("unspiderfy",u,o),this.nudged&&this.requestNudge(),this},a.ptDistanceSq=function(e,t){var i,r;return i=e.x-t.x,r=e.y-t.y,i*i+r*r},a.ptAverage=function(e){var t,i,r,s,o,l;for(o=l=0,t=0,i=e.length;i>t;t++)s=e[t],o+=s.x,l+=s.y;return r=e.length,new n.Point(o/r,l/r)},a.llToPt=function(e){return this.projHelper.getProjection().fromLatLngToDivPixel(e)},a.ptToLl=function(e){return this.projHelper.getProjection().fromDivPixelToLatLng(e)},a.minExtract=function(e,t){var i,r,n,s,o,l,a;for(n=o=0,l=e.length;l>o;n=++o)s=e[n],a=t(s),("undefined"==typeof i||null===i||r>a)&&(r=a,i=n);return e.splice(i,1)[0]},a.arrIndexOf=function(e,t){var i,r,n,s;if(null!=e.indexOf)return e.indexOf(t);for(i=r=0,n=e.length;n>r;i=++r)if(s=e[i],s===t)return i;return-1},e.ProjHelper=function(e){return this.setMap(e)},e.ProjHelper.prototype=new n.OverlayView,e.ProjHelper.prototype.draw=function(){},e}(),e.exports=this.OverlappingMarkerSpiderfier}])});