Skip to content
Snippets Groups Projects
Commit 9a4f9fbe authored by ext.sopra.ncastejon's avatar ext.sopra.ncastejon
Browse files

Refacto the mapService. Keep only one layer for the data (instead of the three...

Refacto the mapService. Keep only one layer for the data (instead of the three for line, point and polygon), because we never have multitype layers.
parent 3a1f1ed3
No related branches found
No related tags found
No related merge requests found
......@@ -80,13 +80,17 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
this.mapOptions.mvtUrl = APP_CONFIG.backendUrls.mvt;
this.mapOptions.vectorService = { ...this.metadata.link.find((e) => { return e.service === linkFormats.wfs; }) };
this.mapOptions.rasterService = { ...this.metadata.link.find((e) => { return e.service === linkFormats.wms; }) };
let dataType = '';
const dataType = {
isLinear: false,
isPunctual: false,
isAreal: false,
};
if (this._datasetDetailService.dataset.editorialMetadata.isLinear) {
dataType = 'Line';
dataType.isLinear = true;
} else if (this._datasetDetailService.dataset.editorialMetadata.isPunctual) {
dataType = 'Point';
dataType.isPunctual = true;
} else if (this._datasetDetailService.dataset.editorialMetadata.isAreal) {
dataType = 'Polygon';
dataType.isAreal = true;
}
this.mapOptions.dataType = dataType;
......@@ -142,7 +146,7 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
}
// Create a geojson object from an array of data (a sample here)
private createGeojson(data: Data[]) {
private createGeojson(data: Data[]): GeoJSON.FeatureCollection {
const featureCollection = {
type: 'FeatureCollection',
name: this.mapOptions.vectorService.name,
......@@ -166,7 +170,7 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
}
});
featureCollection.features = newFeatures;
return featureCollection;
return featureCollection as GeoJSON.FeatureCollection;
}
get isReady() {
......
......@@ -5,8 +5,14 @@ export interface MapOptions {
initOptions: boolean;
isMVT: boolean;
mvtUrl?: string;
geojson? : {};
dataType: string;
geojson? : GeoJSON.FeatureCollection;
dataType: DataType;
}
export interface DataType {
isLinear: boolean;
isPunctual: boolean;
isAreal: boolean;
}
export interface GeoService {
......
......@@ -7,8 +7,7 @@ import { notificationMessages } from '../../../i18n/traductions.fr';
import { Notification } from '../../core/models';
import { NotificationService } from '../../core/services';
import { APP_CONFIG } from '../../core/services/app-config.service';
import { Minimap } from '../components/minimap-control';
import { GeoService, MapOptions } from '../models/map-options';
import { DataType, MapOptions } from '../models/map-options';
import { settings } from '../settings';
@Injectable()
......@@ -18,13 +17,10 @@ export class MapService {
private _map: mapboxgl.Map;
private url: string;
selectedBaseLayer: any;
dataType: string;
vectorService: GeoService;
rasterService: GeoService;
mapOptions: MapOptions;
searchFilterApplied: boolean = false;
eventPopupAdded = false;
minimap: Minimap;
mapIsConstructed: boolean = false;
// Map
......@@ -40,10 +36,6 @@ export class MapService {
private _errorSubscription: Subscription;
selectedFeature; // Contains the gid of the selected feature
geojson: GeoJSON.FeatureCollection;
isMVT: boolean;
mvtUrl: string;
totalData: number;
// Properties used to send information to the component
......@@ -52,8 +44,6 @@ export class MapService {
private _mapUpdated = new Subject<any>();
private _featureSelected = new Subject<mapboxgl.MapboxGeoJSONFeature>();
_errorService: any;
constructor(
private _notificationService: NotificationService,
) { }
......@@ -61,12 +51,13 @@ export class MapService {
createMap(
mapOptions: MapOptions,
url: string, baseLayer: any, options?: mapboxgl.MapboxOptions): mapboxgl.Map {
this.vectorService = mapOptions.vectorService;
this.rasterService = mapOptions.rasterService;
this.geojson = mapOptions.geojson as GeoJSON.FeatureCollection;
this.isMVT = mapOptions.isMVT;
this.mvtUrl = mapOptions.mvtUrl;
this.dataType = mapOptions.dataType;
this.mapOptions = mapOptions;
// this.vectorService = mapOptions.vectorService;
// this.rasterService = mapOptions.rasterService;
// this.geojson = mapOptions.geojson as GeoJSON.FeatureCollection;
// this.isMVT = mapOptions.isMVT;
// this.mvtUrl = mapOptions.mvtUrl;
// this.dataType = mapOptions.dataType;
// Reset to false in ordre to set event listener
this.eventPopupAdded = false;
......@@ -75,7 +66,7 @@ export class MapService {
this.url = url;
options.transformRequest = (url, resourceType) => {
if (resourceType === 'Tile' && url.startsWith(this.mvtUrl)) {
if (resourceType === 'Tile' && url.startsWith(this.mapOptions.mvtUrl)) {
return {
url,
credentials: 'include',
......@@ -127,21 +118,21 @@ export class MapService {
this.addWMSLayer();
// Add a geojson layer only if data from the metropole
if (this.rasterService.url.includes(APP_CONFIG.backendUrls.wms)) {
if (this.mapOptions.rasterService.url.includes(APP_CONFIG.backendUrls.wms)) {
// There is two ways to add tha data layers: from a geojson or from a MVT url
if (!this.isMVT) {
if (this.geojson) {
if (!this.mapOptions.isMVT) {
if (this.mapOptions.geojson) {
this._map.addSource('vector-source', {
type: 'geojson',
data: this.geojson,
data: this.mapOptions.geojson,
});
this.addDataLayer();
}
} else {
if (this.vectorService && this.vectorService.url) {
const domain = this.vectorService.url.split('wfs')[1];
const url = `${this.mvtUrl}${domain}?LAYERS` +
`=${this.vectorService.name}&map.imagetype=mvt&tilemode=gmap&tile={x}+{y}+{z}&mode=tile`;
if (this.mapOptions.vectorService && this.mapOptions.vectorService.url) {
const domain = this.mapOptions.vectorService.url.split('wfs')[1];
const url = `${this.mapOptions.mvtUrl}${domain}?LAYERS` +
`=${this.mapOptions.vectorService.name}&map.imagetype=mvt&tilemode=gmap&tile={x}+{y}+{z}&mode=tile`;
this._map.addSource('vector-source', {
type: 'vector',
......@@ -152,6 +143,19 @@ export class MapService {
}
}
}
this._map.on('styledata', () => {
if (this._map.getFilter('data-layer') && !this.searchFilterApplied) {
this._map.setFilter('data-layer', null);
}
});
this._map.on('sourcedata', (event) => {
if (this._map.getFilter('data-layer') && this.searchFilterApplied) {
this.paintPropertyForLayer('data-layer', this.mapOptions.dataType, this.featureColor);
this._map.setPaintProperty('wms-layer', 'raster-opacity', 0.5);
}
});
}
addClickEventOnLayer(layer: string) {
......@@ -198,7 +202,7 @@ export class MapService {
// Ex: {hover: true, highlight: false}
changeFeatureState(featureId: string, state) {
let stateSource = {} as mapboxgl.FeatureIdentifier;
if (!this.isMVT) {
if (!this.mapOptions.isMVT) {
stateSource = {
source: 'vector-source',
id: featureId,
......@@ -206,7 +210,7 @@ export class MapService {
} else {
stateSource = {
source: 'vector-source',
sourceLayer: this.vectorService.name,
sourceLayer: this.mapOptions.vectorService.name,
id: featureId,
};
}
......@@ -225,8 +229,8 @@ export class MapService {
this._map.addSource('wms-source', {
type: 'raster',
tiles: [
`${this.rasterService.url}?bbox={bbox-epsg-3857}&format=image/png&service=WMS&version=1.1.1&request=GetMap&` +
`srs=EPSG:3857&width=256&height=256&transparent=true&layers=${this.rasterService.name}`,
`${this.mapOptions.rasterService.url}?bbox={bbox-epsg-3857}&format=image/png&service=WMS&version=1.1.1&request=GetMap&` +
`srs=EPSG:3857&width=256&height=256&transparent=true&layers=${this.mapOptions.rasterService.name}`,
],
tileSize: 256,
});
......@@ -241,152 +245,110 @@ export class MapService {
}
addDataLayer() {
// For 'Polygon' and 'MultiPolygon' features
if (this.dataType === 'Polygon') {
this._map.addLayer(
{
id: 'polygon-features',
type: 'fill',
source: 'vector-source',
// 'source-layer': this.vectorService.name,
paint: {
'fill-color': ['case',
['boolean', ['feature-state', 'highlight'], false],
this.featureHighlightedColor,
['boolean', ['feature-state', 'hover'], false],
this.featureHoverColor,
['boolean', ['feature-state', 'visited'], false],
this.visitedColor,
'transparent',
],
'fill-opacity': 0.7,
'fill-outline-color': ['case',
['boolean', ['feature-state', 'visited'], false],
'white',
'transparent',
],
},
filter: ['match', ['geometry-type'], ['Polygon', 'MultiPolygon'], true, false],
...(this.isMVT ? { 'source-layer': this.vectorService.name } : {}), // if not MVT, this property is not needed
});
let layerOptions = {};
// For 'Polygon' and 'MultiPolygon' features
if (this.mapOptions.dataType.isAreal) {
layerOptions = {
type: 'fill',
paint: {
'fill-color': ['case',
['boolean', ['feature-state', 'highlight'], false],
this.featureHighlightedColor,
['boolean', ['feature-state', 'hover'], false],
this.featureHoverColor,
['boolean', ['feature-state', 'visited'], false],
this.visitedColor,
'transparent',
],
'fill-opacity': 0.7,
'fill-outline-color': ['case',
['boolean', ['feature-state', 'visited'], false],
'white',
'transparent',
],
},
};
}
if (this.dataType === 'Line') {
// For 'LineString' and 'MultiLineString features
this._map.addLayer(
{
id: 'line-features',
type: 'line',
source: 'vector-source',
// 'source-layer': this.vectorService.name,
layout: {
'line-cap': 'round',
'line-join': 'round',
},
paint: {
'line-color': ['case',
['boolean', ['feature-state', 'highlight'], false],
this.featureHighlightedColor,
['boolean', ['feature-state', 'hover'], false],
this.featureHoverColor,
['boolean', ['feature-state', 'visited'], false],
this.visitedColor,
'transparent',
],
'line-width': [
'interpolate', ['linear'], ['zoom'],
9, 2,
13, 4,
],
},
filter: ['match', ['geometry-type'], ['LineString', 'MultiLineString'], true, false],
...(this.isMVT ? { 'source-layer': this.vectorService.name } : {}), // if not MVT, this property is not needed
if (this.mapOptions.dataType.isLinear) {
layerOptions = {
type: 'line',
paint: {
'line-color': ['case',
['boolean', ['feature-state', 'highlight'], false],
this.featureHighlightedColor,
['boolean', ['feature-state', 'hover'], false],
this.featureHoverColor,
['boolean', ['feature-state', 'visited'], false],
this.visitedColor,
'transparent',
],
'line-width': [
'interpolate', ['linear'], ['zoom'],
9, 2,
13, 4,
],
},
);
};
}
if (this.dataType === 'Point') {
if (this.mapOptions.dataType.isPunctual) {
// Add layer + style for the points
// Get paint options depending the dataset size
this._map.addLayer(
{
id: 'point-features',
type: 'circle',
source: 'vector-source',
// 'source-layer': this.vectorService.name,
filter: ['match', ['geometry-type'], ['Point'], true, false],
paint: {
'circle-radius': ['case',
['boolean', ['feature-state', 'highlight'], false],
2.5,
5,
],
'circle-color': ['case',
['boolean', ['feature-state', 'highlight'], false],
'white',
['boolean', ['feature-state', 'hover'], false],
this.featureHoverColor,
['boolean', ['feature-state', 'visited'], false],
this.visitedColor,
'transparent',
],
'circle-stroke-width': ['case',
['boolean', ['feature-state', 'highlight'], false],
5,
['boolean', ['feature-state', 'visited'], false],
1,
0,
],
'circle-stroke-color': ['case',
['boolean', ['feature-state', 'highlight'], false],
this.featureHighlightedColor,
['boolean', ['feature-state', 'visited'], false],
'white',
'transparent',
],
},
...(this.isMVT ? { 'source-layer': this.vectorService.name } : {}), // if not MVT, this property is not needed
});
layerOptions = {
type: 'circle',
paint: {
'circle-radius': ['case',
['boolean', ['feature-state', 'highlight'], false],
2.5,
5,
],
'circle-color': ['case',
['boolean', ['feature-state', 'highlight'], false],
'white',
['boolean', ['feature-state', 'hover'], false],
this.featureHoverColor,
['boolean', ['feature-state', 'visited'], false],
this.visitedColor,
'transparent',
],
'circle-stroke-width': ['case',
['boolean', ['feature-state', 'highlight'], false],
5,
['boolean', ['feature-state', 'visited'], false],
1,
0,
],
'circle-stroke-color': ['case',
['boolean', ['feature-state', 'highlight'], false],
this.featureHighlightedColor,
['boolean', ['feature-state', 'visited'], false],
'white',
'transparent',
],
},
};
}
console.log(this._map.getStyle().layers);
this._map.addLayer(
{
id: 'data-layer',
source: 'vector-source',
...layerOptions,
...(this.mapOptions.isMVT ? { 'source-layer': this.mapOptions.vectorService.name } : {}), // if not MVT, this property is not needed
});
if (!this.eventPopupAdded) {
// Manage the cursor and feature state for point-features layer when mouse events
this._map.on('mousemove', 'point-features', (e) => {
this.manageFeatureOnMouseMove(e.features);
});
this._map.on('mouseleave', 'point-features', (e) => {
this.manageFeatureOnMouseEnd();
});
// Manage the cursor and feature state for polygon-features layer when mouse events
this._map.on('mousemove', 'polygon-features', (e) => {
this._map.on('mousemove', 'data-layer', (e) => {
this.manageFeatureOnMouseMove(e.features);
});
this._map.on('mouseleave', 'polygon-features', (e) => {
this._map.on('mouseleave', 'data-layer', (e) => {
this.manageFeatureOnMouseEnd();
});
// Manage the cursor and feature state for line-features layer when mouse events
this._map.on('mousemove', 'line-features', (e) => {
this.manageFeatureOnMouseMove(e.features);
});
this._map.on('mouseleave', 'line-features', (e) => {
this.manageFeatureOnMouseEnd();
});
if (this._map.getLayer('point-features')) {
this.addClickEventOnLayer('point-features');
}
if (this._map.getLayer('polygon-features')) {
this.addClickEventOnLayer('polygon-features');
}
if (this._map.getLayer('line-features')) {
this.addClickEventOnLayer('line-features');
}
this.addClickEventOnLayer('data-layer');
// [WARNING] The click event on the map has to be declared after the click event on layers
// in order for the stopPropagation to work properly
......@@ -499,9 +461,6 @@ export class MapService {
this._map.setMaxZoom(this.selectedBaseLayer.maxzoom);
this._map.setStyle(`assets/mapbox-gl-styles/${this.selectedBaseLayer.fileName}`);
// Uncomment if you activate the minimap
// this.minimap.switchLayer(this.selectedBaseLayer);
}
setSelectedFeature(selectedFeature) {
......@@ -547,59 +506,24 @@ export class MapService {
properties.forEach((property) => {
filters.push(['in', ['upcase', searchValue], ['upcase', ['get', property]]]);
});
console.log(this._map.getLayer('point-features'));
console.log(this._map.getLayer('line-features'));
// For each type layer if exists (point, line, polyon), add this filter and set a color to replace transparent
if (this._map.getLayer('point-features')) {
console.log('layer exists');
this._map.setFilter('point-features', ['any', ...filters]);
this.paintPropertyForLayer('point-features', 'Point', this.featureColor);
}
if (this._map.getLayer('line-features')) {
this._map.setFilter('line-features', ['any', ...filters]);
this.paintPropertyForLayer('line-features', 'Line', this.featureColor);
}
if (this._map.getLayer('polygon-features')) {
this._map.setFilter('polygon-features', ['any', ...filters]);
this.paintPropertyForLayer('polygon-features', 'Polygon', this.featureColor);
}
this._map.setPaintProperty('wms-layer', 'raster-opacity', 0.5);
this._map.setFilter('data-layer', ['any', ...filters]);
this.searchFilterApplied = true;
} else {
// If value is empty, remove the filter and set the opacity for the raster layer back to 1.
if (this._map.getLayer('point-features')) {
this._map.setFilter('point-features', null);
this.paintPropertyForLayer('point-features', 'Point', 'transparent');
}
if (this._map.getLayer('line-features')) {
this._map.setFilter('line-features', null);
this.paintPropertyForLayer('line-features', 'Line', 'transparent');
}
if (this._map.getLayer('polygon-features')) {
this._map.setFilter('polygon-features', null);
this.paintPropertyForLayer('polygon-features', 'Polygon', 'transparent');
}
this.searchFilterApplied = false;
this.paintPropertyForLayer('data-layer', this.mapOptions.dataType, 'transparent');
this._map.setPaintProperty('wms-layer', 'raster-opacity', 1);
}
}
private paintPropertyForLayer(layerId: string, type: string, color: string) {
console.log('paint property');
console.log(type);
if (type === 'Point') {
private paintPropertyForLayer(layerId: string, type: DataType, color: string) {
if (type.isPunctual) {
this._map.setPaintProperty(layerId, 'circle-color', color);
} else if (type === 'Line') {
console.log('add line color');
} else if (type.isLinear) {
this._map.setPaintProperty(layerId, 'line-color', color);
} else if (type === 'Polygon') {
} else if (type.isAreal) {
this._map.setPaintProperty(layerId, 'fill-color', color);
}
}
......
......@@ -8,7 +8,7 @@
"rules": {
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"],
"strict-boolean-expressions": [false],
"max-line-length": [true, 120],
"max-line-length": [true, 150],
"rxjs-collapse-imports": true,
"rxjs-pipeable-operators-only": true,
"rxjs-no-static-observable-methods": true,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment