UNPKG

ui.leaflet.webpack

Version:

Webpack version of ui-leaflet (https://github.com/angular-ui/ui-leaflet)

374 lines (345 loc) 13.8 kB
angular.module('ui-leaflet') .factory('leafletLayerHelpers', /** @ngInject */ [ '$rootScope', '$q', 'leafletLogger', 'leafletHelpers', 'leafletIterators', 'L', function ($rootScope, $q, leafletLogger, leafletHelpers, leafletIterators, L) { var Helpers = leafletHelpers; var isString = leafletHelpers.isString; var isObject = leafletHelpers.isObject; var isArray = leafletHelpers.isArray; var isDefined = leafletHelpers.isDefined; var errorHeader = leafletHelpers.errorHeader; var $it = leafletIterators; var $log = leafletLogger; var utfGridCreateLayer = function(params) { if (!Helpers.UTFGridPlugin.isLoaded()) { $log.error('[AngularJS - Leaflet] The UTFGrid plugin is not loaded.'); return; } var utfgrid = new L.UtfGrid(params.url, params.pluginOptions); var toSend = { model: params.$parent }; // TODO Use event manager utfgrid.on('mouseover', function(e) { angular.extend(toSend, { leafletEvent: e, leafletObject: e.target, }); $rootScope.$broadcast('leafletDirectiveMap.utfgridMouseover', toSend); }); utfgrid.on('mouseout', function(e) { angular.extend(toSend, { leafletEvent: e, leafletObject: e.target, }); $rootScope.$broadcast('leafletDirectiveMap.utfgridMouseout', toSend); }); utfgrid.on('click', function(e) { angular.extend(toSend, { leafletEvent: e, leafletObject: e.target, }); $rootScope.$broadcast('leafletDirectiveMap.utfgridClick', toSend); }); utfgrid.on('mousemove', function(e) { angular.extend(toSend, { leafletEvent: e, leafletObject: e.target, }); $rootScope.$broadcast('leafletDirectiveMap.utfgridMousemove', toSend); }); return utfgrid; }; var layerTypes = { xyz: { mustHaveUrl: true, createLayer: function(params) { return L.tileLayer(params.url, params.options); } }, geoJSON: { mustHaveUrl: true, createLayer: function(params) { if (!Helpers.GeoJSONPlugin.isLoaded()) { return; } return new L.TileLayer.GeoJSON(params.url, params.pluginOptions, params.options); } }, geoJSONShape: { mustHaveUrl: false, createLayer: function(params) { return new L.GeoJSON(params.data, params.options); } }, geoJSONAwesomeMarker: { mustHaveUrl: false, createLayer: function(params) { return new L.geoJson(params.data, { pointToLayer: function (feature, latlng) { return L.marker(latlng, {icon: L.AwesomeMarkers.icon(params.icon)}); } }); } }, geoJSONVectorMarker: { mustHaveUrl: false, createLayer: function(params) { return new L.geoJson(params.data, { pointToLayer: function (feature, latlng) { return L.marker(latlng, {icon: L.VectorMarkers.icon(params.icon)}); } }); } }, cartodbTiles: { mustHaveKey: true, createLayer: function(params) { var url = isDefined(params.url)? params.url+'/'+params.user: '//' + params.user + '.cartodb.com'; url += '/api/v1/map/' + params.key + '/{z}/{x}/{y}.png'; return L.tileLayer(url, params.options); } }, cartodbUTFGrid: { mustHaveKey: true, mustHaveLayer : true, createLayer: function(params) { var url = isDefined(params.url)? params.url+'/'+params.user: '//' + params.user + '.cartodb.com'; params.url = url + '/api/v1/map/' + params.key + '/' + params.layer + '/{z}/{x}/{y}.grid.json'; return utfGridCreateLayer(params); } }, cartodbInteractive: { mustHaveKey: true, mustHaveLayer : true, createLayer: function(params) { var url = isDefined(params.url)? params.url+'/'+params.user: '//' + params.user + '.cartodb.com'; var tilesURL = url + '/api/v1/map/' + params.key + '/{z}/{x}/{y}.png'; var tileLayer = L.tileLayer(tilesURL, params.options); var layers = [tileLayer]; var addUtfLayer = function(parent, params, layer) { var paramsCopy = angular.copy(params); paramsCopy.url = url + '/api/v1/map/' + paramsCopy.key + '/' + layer + '/{z}/{x}/{y}.grid.json'; parent.push(utfGridCreateLayer(paramsCopy)); }; if(isArray(params.layer)) { for(var i = 0; i < params.layer.length; i++) { addUtfLayer(layers, params, params.layer[i]); } } else { addUtfLayer(layers, params, params.layer); } return L.layerGroup(layers); } }, wms: { mustHaveUrl: true, createLayer: function(params) { return L.tileLayer.wms(params.url, params.options); } }, wmts: { mustHaveUrl: true, createLayer: function(params) { return L.tileLayer.wmts(params.url, params.options); } }, group: { mustHaveUrl: false, createLayer: function (params) { var lyrs = []; $it.each(params.options.layers, function(l){ lyrs.push(createLayer(l)); }); params.options.loadedDefer = function() { var defers = []; if(isDefined(params.options.layers)) { for (var i = 0; i < params.options.layers.length; i++) { var d = params.options.layers[i].layerOptions.loadedDefer; if(isDefined(d)) { defers.push(d); } } } return defers; }; return L.layerGroup(lyrs); } }, featureGroup: { mustHaveUrl: false, createLayer: function () { return L.featureGroup(); } }, markercluster: { mustHaveUrl: false, createLayer: function(params) { if (!Helpers.MarkerClusterPlugin.isLoaded()) { $log.warn(errorHeader + ' The markercluster plugin is not loaded.'); return; } return new L.MarkerClusterGroup(params.options); } }, imageOverlay: { mustHaveUrl: true, mustHaveBounds : true, createLayer: function(params) { return L.imageOverlay(params.url, params.bounds, params.options); } }, iip: { mustHaveUrl: true, createLayer: function(params) { return L.tileLayer.iip(params.url, params.options); } }, // This "custom" type is used to accept every layer that user want to define himself. // We can wrap these custom layers like heatmap or yandex, but it means a lot of work/code to wrap the world, // so we let user to define their own layer outside the directive, // and pass it on "createLayer" result for next processes custom: { createLayer: function (params) { if (params.layer instanceof L.Class) { return angular.copy(params.layer); } else { $log.error('[AngularJS - Leaflet] A custom layer must be a leaflet Class'); } } }, cartodb: { mustHaveUrl: true, createLayer: function(params) { return cartodb.createLayer(params.map, params.url); } } }; function isValidLayerType(layerDefinition) { // Check if the baselayer has a valid type if (!isString(layerDefinition.type)) { $log.error('[AngularJS - Leaflet] A layer must have a valid type defined.'); return false; } if (Object.keys(layerTypes).indexOf(layerDefinition.type) === -1) { $log.error('[AngularJS - Leaflet] A layer must have a valid type: ' + Object.keys(layerTypes)); return false; } // Check if the layer must have an URL if (layerTypes[layerDefinition.type].mustHaveUrl && !isString(layerDefinition.url)) { $log.error('[AngularJS - Leaflet] A base layer must have an url'); return false; } if (layerTypes[layerDefinition.type].mustHaveData && !isDefined(layerDefinition.data)) { $log.error('[AngularJS - Leaflet] The base layer must have a "data" array attribute'); return false; } if(layerTypes[layerDefinition.type].mustHaveLayer && !isDefined(layerDefinition.layer)) { $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have an layer defined'); return false; } if (layerTypes[layerDefinition.type].mustHaveBounds && !isDefined(layerDefinition.bounds)) { $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have bounds defined'); return false ; } if (layerTypes[layerDefinition.type].mustHaveKey && !isDefined(layerDefinition.key)) { $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have key defined'); return false ; } return true; } function createLayer(layerDefinition) { if (!isValidLayerType(layerDefinition)) { return; } if (!isString(layerDefinition.name)) { $log.error('[AngularJS - Leaflet] A base layer must have a name'); return; } if (!isObject(layerDefinition.layerParams)) { layerDefinition.layerParams = {}; } if (!isObject(layerDefinition.layerOptions)) { layerDefinition.layerOptions = {}; } // Mix the layer specific parameters with the general Leaflet options. Although this is an overhead // the definition of a base layers is more 'clean' if the two types of parameters are differentiated for (var attrname in layerDefinition.layerParams) { layerDefinition.layerOptions[attrname] = layerDefinition.layerParams[attrname]; } var params = { url: layerDefinition.url, data: layerDefinition.data, options: layerDefinition.layerOptions, layer: layerDefinition.layer, icon: layerDefinition.icon, type: layerDefinition.layerType, bounds: layerDefinition.bounds, key: layerDefinition.key, apiKey: layerDefinition.apiKey, pluginOptions: layerDefinition.pluginOptions, user: layerDefinition.user, $parent: layerDefinition }; //TODO Add $watch to the layer properties return layerTypes[layerDefinition.type].createLayer(params); } function safeAddLayer(map, layer) { if (layer && typeof layer.addTo === 'function') { layer.addTo(map); } else { map.addLayer(layer); } } function safeRemoveLayer(map, layer, layerOptions) { if(isDefined(layerOptions) && isDefined(layerOptions.loadedDefer)) { if(angular.isFunction(layerOptions.loadedDefer)) { var defers = layerOptions.loadedDefer(); $log.debug('Loaded Deferred', defers); var count = defers.length; if(count > 0) { var resolve = function() { count--; if(count === 0) { map.removeLayer(layer); } }; for(var i = 0; i < defers.length; i++) { defers[i].promise.then(resolve); } } else { map.removeLayer(layer); } } else { layerOptions.loadedDefer.promise.then(function() { map.removeLayer(layer); }); } } else { map.removeLayer(layer); } } let changeOpacityListener = (op) => { return (ly) => { if(isDefined(ly.setOpacity)) { ly.setOpacity(op); } }; }; return { createLayer: createLayer, layerTypes: layerTypes, safeAddLayer: safeAddLayer, safeRemoveLayer: safeRemoveLayer, changeOpacityListener: changeOpacityListener }; }]);