Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AMap/高德地图 module wrapper with angular
/*
* 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
You can’t perform that action at this time.