Skip to content

Instantly share code, notes, and snippets.

@anartzdev
Last active June 29, 2022 14:25
Show Gist options
  • Save anartzdev/1059f82586294081baadfd2dc4dc44c0 to your computer and use it in GitHub Desktop.
Save anartzdev/1059f82586294081baadfd2dc4dc44c0 to your computer and use it in GitHub Desktop.
Default Layer feature
import { IConfigMap, IMarker, tileLayers } from '@mugan86/ng-leaflet';
import { Component } from '@angular/core';
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent{
markers: Array<IMarker> = [
{
position: {
lat: 43.17757110078426,
lng: -2.3661233885984085,
},
},
{
position: {
lat: 43.177781697765305,
lng: -2.367583962060063,
},
},
];
config?: IConfigMap = {
// Usa esta capa sobrescribiendo cualquier capa en global / control de capas
defaultLayer: {
map: 'https://tile.thunderforest.com/neighbourhood/{z}/{x}/{y}.png?apikey=47455e4b0807408c87ead5d6f7a8d1c8',
atribution: tileLayers.baseLayers.default.atribution
},
fitBounds: true,
drawRoute: {
active: false,
showControl: false
},
markerColor: 'orange'
};
// Para usar el global con defaultLayer (en el caso de que esté activado, si no pone la capa básica de OSM)
configTwo?: IConfigMap = {
fitBounds: true,
drawRoute: {
active: false,
showControl: false
},
markerColor: 'orange'
};
/*@Input() markers: Array<IMarker> = [{
position: {
lat: 43.17774378506745,
lng: -2.4150770902633667
}
},
{
position: {
lat: 43.177548188824325,
lng: -2.4145513772964478
}
},
{
position: {
lat: 43.177274353031386,
lng: -2.4141544103622437
}
}];
@Input() randomMarkers: boolean = false;
@Input() size: { width: string, height: string } = { width: '100%', height: '600px' }
@Input() config?: IConfigMap = {
fullscreen: true,
ourLocation: {
active: true,
zoom: 5
},
zoom: {
default: 15
},
drawRoute: {
active: true,
title: 'Jabali Trail Short',
showControl: true
}
};
*/
/*markers: Array<IMarker> = [
{
position: {
lat: 43.17757110078426,
lng: -2.3661233885984085,
},
},
{
position: {
lat: 43.177781697765305,
lng: -2.367583962060063,
},
},
];
config?: IConfigMap = {
fitBounds: true,
drawRoute: {
active: true,
showControl: false
},
markerColor: 'gold'
};
ngOnInit() {
this.markers.length = 0;
fetch('https://raw.githubusercontent.com/leaflet-maps-course/resources/main/tracks/track.gpx')
.then(response => response.text())
.then(data => {
const gpx = new gpxParser(); //Create gpxParser Object
gpx.parse(data); //parse gpx file from string data
gpx.tracks[0].points.map((point) => {
this.markers.push({
position: {
lat: point.lat,
lng: point.lon
}
})
});
});
}*/
}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MapRoutingModule } from './map-routing.module';
import { MapComponent } from './map.component';
import { IConfigMap, NgLeafletModule, tileLayers } from '@mugan86/ng-leaflet';
const config: IConfigMap = {
fullscreen: true,
center: [40.4378698,-3.8196188],
zoom: {
position: 'topright'
},
watermark: {
position: 'topleft'
},
/*defaultLayer: {
map: 'https://tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png?apikey=47455e4b0807408c87ead5d6f7a8d1c8',
atribution: tileLayers.baseLayers.default.atribution
},
layers: {
baseLayers: [{
label: 'Carto - Positron',
map: tileLayers.baseLayers.cartoDb.map.positron,
atribution: tileLayers.baseLayers.cartoDb.atribution,
default: true
},
{
label: 'Cyclo OSM',
map: tileLayers.baseLayers.cycloOsm.map,
atribution: tileLayers.baseLayers.cycloOsm.atribution
}]
},*/
drawRoute: {
active: true,
showControl: true
}
}
@NgModule({
declarations: [
MapComponent
],
imports: [
CommonModule,
MapRoutingModule,
NgLeafletModule.forRoot(config, {
width: '100%',
height: '600px'
})
]
})
export class MapModule { }
import { AfterViewInit, Component, EventEmitter, Input, Output } from '@angular/core';
import { IMarker, IConfigMap } from './../../models';
import { Controls } from '../../services/controls';
import { Markers } from './../../services/markers';
import { LeafletMap as Map } from './../../services/ng-leaflet-map.service';
import { Map as MapObject } from 'leaflet';
import { ISizeMap } from '../../models/config-map';
import { DefaultConfig } from '../../services';
import { DrawMap } from '../../services/draw-map';
@Component({
selector: 'ng-leaflet-map',
templateUrl: './map.component.html',
styles: [
]
})
export class MapComponent implements AfterViewInit {
/**
* Assign map ID that need is unique and not duplicate
*
* @required
*/
@Input() mapId = 'map';
/**
* Markers
*/
@Input() markers!: Array<IMarker>;
/**
* Button contents
*
* @required
*/
@Input() randomMarkers: boolean = false;
/**
* Specify use Map size to working map
*
* @required
*/
@Input() size!: ISizeMap;
/**
* Use map differents configurations to custom
*/
@Input() config?: IConfigMap;
/**
Use the loading state to indicate that the data Avatar needs is still loading.
*/
@Output() setUpMap: EventEmitter<MapObject> = new EventEmitter<MapObject>();
private map!: Map;
constructor(private defaultConfig: DefaultConfig) { }
ngOnInit() {
// Check if size config exist and if not exist, take default 100% w - 500px h
if (this.size && this.defaultConfig.get().size) {
console.warn('Use set size');
}
if (!this.size && !this.defaultConfig.get().size) {
this.size = {
width: '100%',
height: '500px'
};
return;
}
// Check if size config exist and if not exist, take default 100% w - 500px h
if (!this.size && this.defaultConfig.get().size) {
console.warn('Use default global size');
this.size = this.defaultConfig.get().size;
}
}
private checkConfigs() {
if (!this.config && this.defaultConfig.get().config) {
console.warn('Use default config');
this.config = this.defaultConfig.get().config;
return;
}
if (!this.config && !this.defaultConfig.get().config) {
console.warn("Use Library default configs \n" + (JSON.stringify({
fullscreen: false,
center: [43.1824528, -2.3878554],
mapId: 'map',
zoom: true,
zoomValue: 12,
drawRoute: false
}, null, 2)));
return;
}
}
setConfiguration() {
this.checkConfigs();
if (this.config && this.defaultConfig.get().config) {
console.warn("Overwrite defaultConfig with new set config duplicates values properties");
// Rewrite
this.checkAndAsignDefaultConfigs()
}
}
private checkAndAsignDefaultConfigs() {
if (!this.config!.center && this.defaultConfig.get().config.center) {
this.config!.center = this.defaultConfig.get().config.center;
}
if (this.config!.fullscreen === undefined && this.defaultConfig.get().config.fullscreen) {
this.config!.fullscreen = this.defaultConfig.get().config.fullscreen;
}
if (!this.config!.scale && this.defaultConfig.get().config.scale) {
this.config!.scale = this.defaultConfig.get().config.scale;
}
if (!this.config!.defaultLayer && this.defaultConfig.get().config.defaultLayer) {
this.config!.defaultLayer = this.defaultConfig.get().config.defaultLayer;
}
if (!this.config!.layers && !this.config?.defaultLayer && this.defaultConfig.get().config.layers) {
this.config!.layers = this.defaultConfig.get().config.layers;
}
if (!this.config!.zoom && this.defaultConfig.get().config.zoom) {
this.config!.zoom = this.defaultConfig.get().config.zoom;
}
if (!this.config!.watermark && this.defaultConfig.get().config.watermark) {
this.config!.watermark = this.defaultConfig.get().config.watermark;
}
if (!this.config!.fitBounds && this.defaultConfig.get().config.fitBounds) {
this.config!.fitBounds = this.defaultConfig.get().config.fitBounds;
}
if (!this.config!.drawRoute && this.defaultConfig.get().config.drawRoute) {
this.config!.drawRoute = this.defaultConfig.get().config.drawRoute;
}
if (!this.config!.markerColor && this.defaultConfig.get().config.markerColor) {
this.config!.markerColor = this.defaultConfig.get().config.markerColor;
}
}
ngAfterViewInit(): void {
this.setConfiguration();
this.map = new Map(this.config || undefined, this.mapId || undefined);
this.config!! && this.setControls();
if (this.config && this.config!!.drawRoute && this.config!!.drawRoute!!.active) {
if (this.markers.length >= 3) {
new DrawMap(this.map.get()).drawPoints(this.markers);
} else {
console.warn('Need min 3 markers to draw correctly route');
}
} else {
const markerColor = this.config!!.markerColor || 'blue';
this.markers && (this.markers.length) && Markers.add(this.map.get(), this.markers, false, markerColor);
this.randomMarkers && Markers.add(this.map.get(), [], this.randomMarkers, markerColor);
this.markers && this.markers.length && this.config!.fitBounds && this.map.fitBounds(this.markers);
}
this.setUpMap.emit(this.map.get());
}
setControls() {
this.config!!.scale && Controls.addScale(this.map.get(), this.config?.scale);
this.config!!.layers && Controls.addBaseOverLayers(this.map.get(), this.config!!.layers);
this.config!!.zoom && Controls.changeZoomConfig(this.map.get(), this.config?.zoom);
this.config!!.fullscreen && Controls.activeFullScreen(this.map.get());
this.config!!.watermark && Controls.activeWatermark(this.map.get(), this.config!!.watermark);
this.config!!.ourLocation?.active && Controls.getOurLocation(this.map.get(), this.config?.ourLocation.zoom || 12)
this.config!!.drawRoute?.showControl && Controls.addTitle(
this.map.get(),
this.config!!.drawRoute.title || '',
this.config!!.drawRoute.subtitle || '',
this.config!!.drawRoute.position
);
}
}
import { ControlPosition } from "leaflet";
import { MarkerColorOptions } from "../config/markers/default";
import { ILayers, IScaleOptions, IWatermarkOptions, IZoomOptions, IBaseLayer } from './controls';
export interface IConfigMap {
markerColor?: MarkerColorOptions;
center?: [number, number];
scale?: IScaleOptions | undefined;
defaultLayer?: IBaseLayer;
layers?: ILayers;
zoom?: IZoomOptions;
fullscreen?: boolean;
watermark?: IWatermarkOptions;
fitBounds?: boolean;
ourLocation?: {
active: boolean;
zoom?: number;
};
drawRoute?: {
active?: boolean;
title?: string;
subtitle?: string;
position?: ControlPosition;
showControl?: boolean;
};
}
export interface ISizeMap {
width: string;
height: string;
}
import { ControlPosition } from "leaflet";
export interface IScaleOptions {
show?: boolean;
position?: ControlPosition;
maxWidth?: number;
metric?: boolean;
imperial?: boolean;
/**
* If true, the control is updated on moveend, otherwise it's always
* up-to-date (updated on move). Default: false
*/
updateWhenIdle?: boolean | undefined;
}
export interface ILayers {
baseLayers: Array<IBaseLayer>;
overLayers?: Array<IOverLayer>
}
export interface IBaseLayer {
label?: string;
map: string;
atribution: string;
default?: boolean
}
export interface IOverLayer {
label: string;
map: string;
select: boolean
}
export interface IZoomOptions {
zoomInTitle?: string;
zoomOutTitle?: string;
position?: ControlPosition;
default?: number;
}
export interface IWatermarkOptions {
img?: string;
border?: boolean;
position?: ControlPosition;
size?: string;
borderColor?: string;
}
import { control, ControlPosition, Map } from 'leaflet';
import { tileLayerSelect } from '../config/tile-layers/helpers';
import { IBaseLayer, IOverLayer, ILayers, IScaleOptions, IZoomOptions, IWatermarkOptions } from '../models/controls'
import { textContent } from '../plugins/controls';
import { fullScreenMap } from '../plugins/controls/full-screen-map';
import { geolocation } from '../plugins/controls/geolocation';
import { watermark } from '../plugins/controls/watermark';
class Controls {
static changeZoomConfig(map: Map, config?: IZoomOptions) {
control.zoom({
zoomInTitle: config!!.zoomInTitle || 'Zoom in',
zoomOutTitle: config!!.zoomOutTitle || 'Zoom out',
position: config!!.position || 'topleft'
}).addTo(map);
}
static addScale(map: Map, config?: IScaleOptions) {
delete config!.show;
// Add Scale control after remove show property that not include in config options
control.scale(config).addTo(map);
}
/**
* Generate layers control to available users want differente layers
* to use in maps.
* @param map Map instantiate object when add control layers
* @param layers Layers with base and overlayers to add in map
* @param position control position in map
*/
static addBaseOverLayers(map: Map, layers: ILayers, position: ControlPosition = 'topright') {
if (!layers.baseLayers) {
throw new Error("Need to add Base Layers");
}
if (layers.baseLayers.length < 2) {
console.warn("Take advantage of at least two base layers to take advantage of this feature")
}
// Layers controls
control.layers(
this.groupBaseLayers(
layers.baseLayers, map),
(layers.overLayers) && this.groupOverLayers(layers.overLayers, map), {
position
}).addTo(map);
}
private static groupBaseLayers(layers: Array<IBaseLayer>, map: Map) {
const findDefaultLayerConfig = layers.find((layer) => layer.default)
const defaultLayer = tileLayerSelect(findDefaultLayerConfig!!.map, {
attribution: findDefaultLayerConfig!!.atribution
}).addTo(map);
return layers.reduce((a, layer) => {
return (!layer.default) ? ({ // Add NO default layers
...a, [layer.label || '']: tileLayerSelect(layer.map, {
attribution: layer.atribution
})
}) : {
...a, ...{ [layer.label || '']: defaultLayer } // Map Default select layer
}
}, {} // Start value
);
}
private static groupOverLayers(layers: Array<IOverLayer>, map: Map) {
return layers.reduce((a, layer) => ({
...a, [layer.label]: (layer.select) ?
tileLayerSelect(layer.map).addTo(map) :
tileLayerSelect(layer.map)
}), {});
}
static activeFullScreen(map: Map, position?: ControlPosition) {
fullScreenMap({
position: (position) || 'topleft'
}).addTo(map)
}
static activeWatermark(map: Map, config: IWatermarkOptions) {
watermark(config).addTo(map)
}
static getOurLocation(map: Map, zoom: number, position?: ControlPosition) {
geolocation({
position: (position) || 'topleft',
zoom
}).addTo(map);
}
static addTitle(map: Map, title: string, subtitle: string = '', position?: ControlPosition) {
textContent( {
position: (position) || 'bottomleft',
title,
subtitle
}).addTo(map);
}
}
export { Controls }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment