Last active
July 5, 2016 05:45
-
-
Save abruzzihraig/efd55d1f5bc00a1712e7793bf86f4668 to your computer and use it in GitHub Desktop.
AMap/高德地图 module wrapper with angular
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The module amap below is a simplest implementation, there is no any updated or proper libraries when I wrote it. | |
* Since there is a new full-feature library which wrote by another guy, so I just recommend it below. | |
* https://github.com/leftstick/angular-amap | |
* | |
* If you just want version with a few features like below, you could just build your version on top of it. | |
*/ | |
angular.module('amap', []) | |
.constant('amapConstant', { | |
TOOLBAR_HEIGHT: 280, | |
MARKER_WIDTH: 20, | |
MARKER_HEIGHT: 20 | |
}) | |
.factory('amapScriptLoader', ['$q', function($q) { | |
var PROTOCAL = 'http'; | |
var BASE_URL = PROTOCAL + '://webapi.amap.com/maps?'; | |
function generateUrl(options) { | |
var distUrl = Object.keys(options).reduce(function(prev, cur) { | |
prev = prev + cur + '=' + options[cur] + '&'; | |
return prev; | |
}, BASE_URL); | |
return distUrl.substring(0, distUrl.length - 1); | |
} | |
function insertScript(options) { | |
var script = document.createElement('script'); | |
script.type = 'text/javascript'; | |
script.src = generateUrl(options); | |
return document.body.appendChild(script); | |
} | |
function hasMapLoaded() { | |
return angular.isDefined(window.AMap); | |
} | |
return { | |
load: function(options) { | |
var deferred = $q.defer(); | |
if (hasMapLoaded()) { | |
deferred.resolve(window.AMap); | |
return deferred.promise; | |
} | |
window[options.callback] = function() { | |
window[options.callback] = null; | |
deferred.resolve(window.AMap); | |
} | |
if (window.navigator.connection && window.Connection && window.navigator.connection.type === window.Connection.NONE) { | |
document.addEventListener('online', function() { | |
if (!hasMapLoaded()) { | |
return insertScript(options); | |
} | |
}); | |
} else { | |
insertScript(options); | |
} | |
return deferred.promise; | |
} | |
}; | |
}]) | |
.provider('amapApi', function() { | |
var jsonpCallbackName = 'onAmapLoad' + Math.round(Math.random() * 1e3); | |
this.options = { | |
key: '', | |
v: 3, | |
plugins: '', | |
callback: jsonpCallbackName | |
}; | |
this.configure = function(options) { | |
angular.extend(this.options, options); | |
}; | |
this.$get = ['amapScriptLoader', (function(_this) { | |
return function(loader) { return loader.load(_this.options) }; | |
})(this)]; | |
return this; | |
}) | |
.directive('amap', function(amapApi, amapConstant) { | |
return { | |
restrict: 'E', | |
scope: { | |
center: '=', | |
zoom: '=', | |
events: '=' | |
}, | |
transclude: true, | |
template: '\ | |
<div class="angular-amap">\ | |
<div id="{{randomId}}" class="angular-amap-container">\ | |
<ng-transclude></ng-transclude>\ | |
</d\>\ | |
</div>', | |
controller: function($scope) { | |
$scope.randomId = 'amap-' + Math.random() * 1e3; | |
var markerInstances = {}; | |
var map = null; | |
var unwatch = null; | |
this.addMarker = function(markerConf) { | |
return amapApi.then(function(AMap) { | |
var marker = new AMap.Marker({ | |
map: map, | |
position: new AMap.LngLat(markerConf.position.lon, markerConf.position.lat), | |
zIndex: markerConf.zIndex, | |
}); | |
if (markerConf.icon) { | |
marker.setIcon(new AMap.Icon({ | |
size: new AMap.Size(amapConstant.MARKER_WIDTH, amapConstant.MARKER_HEIGHT), | |
image: markerConf.icon | |
})); | |
} | |
if (markerConf.zIndex) { | |
marker.setzIndex(markerConf.zIndex); | |
} | |
markerInstances[markerConf.idkey] = marker; | |
return marker; | |
}); | |
}; | |
this.updateMarker = function(markerConf) { | |
return amapApi.then(function(AMap) { | |
var marker = markerInstances[markerConf.idkey]; | |
marker.setIcon(markerConf.image); | |
marker.setzIndex(markerConf.zIndex); | |
marker.setPosition(new AMap.LngLat(markerConf.position.lon, markerConf.position.lat)); | |
return marker; | |
}); | |
}; | |
this.deleteMarker = function(markerConf) { | |
return amapApi.then(function(AMap) { | |
var marker = markerInstances[markerConf.idkey]; | |
marker.setMap(null); | |
marker = null; | |
delete markerInstances[markerConf.idkey]; | |
}) | |
}; | |
amapApi.then(function(AMap) { | |
initAmap(AMap); | |
}); | |
function initAmap(AMap) { | |
map = new AMap.Map($scope.randomId, { | |
center: new AMap.LngLat($scope.center.longitude, $scope.center.latitude), | |
zoom: $scope.zoom | |
}); | |
AMap.plugin(['AMap.ToolBar','AMap.Scale'], function() { | |
var mapSize = map.getSize(); | |
var toolBar = new AMap.ToolBar({ | |
offset: new AMap.Pixel(10, mapSize.height - amapConstant.TOOLBAR_HEIGHT) | |
}); | |
var scale = new AMap.Scale(); | |
map.addControl(toolBar); | |
map.addControl(scale); | |
}); | |
Object.keys($scope.events || {}).forEach(function(key) { | |
map.on(key, function() { | |
$scope.events[key](map); | |
$scope.$apply(); | |
}); | |
}); | |
unwatch = $scope.$watch('center', function (newVal, oldVal) { | |
if (!oldVal) return; | |
map.setCenter(new AMap.LngLat(newVal.longitude, newVal.latitude)) | |
}); | |
} | |
$scope.$on('$destroy', function() { | |
unwatch(); | |
}); | |
} | |
}; | |
}) | |
.directive('amapMarker', function(amapApi) { | |
return { | |
restrict: 'E', | |
require: '^amap', | |
scope: { | |
click: '&', | |
coords: '=', | |
events: '=', | |
idkey: '=', | |
options: '=', | |
other: '=' | |
}, | |
link: function(scope, elem, attrs, ctrl) { | |
var marker = { | |
idkey: scope.idkey, | |
zIndex: scope.options ? scope.options.zIndex || 1 : 1, | |
position: { | |
lat: scope.coords.latitude, | |
lon: scope.coords.longitude | |
} | |
}; | |
Object.keys(scope.options || {}).forEach(function(key) { | |
if (scope.options[key]) marker[key] = key; | |
}); | |
ctrl.addMarker(marker).then(function(markerInstance) { | |
amapApi.then(function(AMap) { | |
AMap.event.addListener(markerInstance, 'click', function() { | |
scope.click({id: scope.idkey, other: scope.other}); | |
scope.$apply(); | |
}) | |
}) | |
}); | |
var unwatchOptions = scope.$watch('options.icon', function(newVal, oldVal) { | |
if (!oldVal) return; | |
marker.image = newVal; | |
ctrl.updateMarker(marker); | |
}); | |
var unwatchCoords = scope.$watch('coords', function(newVal, oldVal) { | |
if (!oldVal) return; | |
marker.position = { | |
lat: newVal.latitude, | |
lon: newVal.longitude | |
} | |
ctrl.updateMarker(marker); | |
}); | |
scope.$on('$destroy', function() { | |
ctrl.deleteMarker(marker); | |
unwatchOptions(); | |
unwatchCoords(); | |
}); | |
} | |
}; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment