Use new optional layers in maps module
This commit is contained in:
parent
eaa9b1c071
commit
1af0d30d94
14 changed files with 280 additions and 184 deletions
|
@ -1,13 +1,15 @@
|
||||||
import React, { useState, useCallback, useRef, useMemo } from 'react';
|
import React, { useState, useCallback, useRef, useMemo } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import mapboxgl from 'mapbox-gl';
|
import mapboxgl from 'mapbox-gl';
|
||||||
import ReactMapboxGl, { GeoJSONLayer, ZoomControl } from 'react-mapbox-gl';
|
import { GeoJSONLayer, ZoomControl } from 'react-mapbox-gl';
|
||||||
import DrawControl from 'react-mapbox-gl-draw';
|
import DrawControl from 'react-mapbox-gl-draw';
|
||||||
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
||||||
|
|
||||||
import { getJSON, ajax, fire } from '@utils';
|
import { getJSON, ajax, fire } from '@utils';
|
||||||
|
|
||||||
import { getMapStyle, SwitchMapStyle } from '../MapStyles';
|
import Mapbox from '../shared/mapbox/Mapbox';
|
||||||
|
import { getMapStyle } from '../shared/mapbox/styles';
|
||||||
|
import SwitchMapStyle from '../shared/mapbox/SwitchMapStyle';
|
||||||
|
|
||||||
import ComboAdresseSearch from '../ComboAdresseSearch';
|
import ComboAdresseSearch from '../ComboAdresseSearch';
|
||||||
import {
|
import {
|
||||||
|
@ -22,9 +24,7 @@ import {
|
||||||
generateId,
|
generateId,
|
||||||
useEvent,
|
useEvent,
|
||||||
findFeature
|
findFeature
|
||||||
} from '../shared/map';
|
} from '../shared/mapbox/utils';
|
||||||
|
|
||||||
const Map = ReactMapboxGl({});
|
|
||||||
|
|
||||||
function MapEditor({ featureCollection, url, preview, options }) {
|
function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
const drawControl = useRef(null);
|
const drawControl = useRef(null);
|
||||||
|
@ -38,10 +38,11 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
const [cadastresFeatureCollection, setCadastresFeatureCollection] = useState(
|
const [cadastresFeatureCollection, setCadastresFeatureCollection] = useState(
|
||||||
filterFeatureCollection(featureCollection, 'cadastre')
|
filterFeatureCollection(featureCollection, 'cadastre')
|
||||||
);
|
);
|
||||||
const mapStyle = useMemo(
|
const mapStyle = useMemo(() => getMapStyle(style, options.layers), [
|
||||||
() => getMapStyle(style, options.cadastres, options.mnhn),
|
style,
|
||||||
[style, options]
|
options
|
||||||
);
|
]);
|
||||||
|
const hasCadastres = useMemo(() => options.layers.includes('cadastres'));
|
||||||
|
|
||||||
const translations = [
|
const translations = [
|
||||||
['.mapbox-gl-draw_line', 'Tracer une ligne'],
|
['.mapbox-gl-draw_line', 'Tracer une ligne'],
|
||||||
|
@ -288,7 +289,7 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Map
|
<Mapbox
|
||||||
onStyleLoad={(map) => onMapLoad(map)}
|
onStyleLoad={(map) => onMapLoad(map)}
|
||||||
fitBounds={bbox}
|
fitBounds={bbox}
|
||||||
fitBoundsOptions={{ padding: 100 }}
|
fitBoundsOptions={{ padding: 100 }}
|
||||||
|
@ -299,7 +300,7 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
height: '500px'
|
height: '500px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{options.cadastres ? (
|
{hasCadastres ? (
|
||||||
<GeoJSONLayer
|
<GeoJSONLayer
|
||||||
data={cadastresFeatureCollection}
|
data={cadastresFeatureCollection}
|
||||||
fillPaint={polygonCadastresFill}
|
fillPaint={polygonCadastresFill}
|
||||||
|
@ -321,7 +322,7 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
/>
|
/>
|
||||||
<SwitchMapStyle style={style} setStyle={setStyle} ign={options.ign} />
|
<SwitchMapStyle style={style} setStyle={setStyle} ign={options.ign} />
|
||||||
<ZoomControl />
|
<ZoomControl />
|
||||||
</Map>
|
</Mapbox>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -335,8 +336,7 @@ MapEditor.propTypes = {
|
||||||
url: PropTypes.string,
|
url: PropTypes.string,
|
||||||
preview: PropTypes.bool,
|
preview: PropTypes.bool,
|
||||||
options: PropTypes.shape({
|
options: PropTypes.shape({
|
||||||
cadastres: PropTypes.bool,
|
layers: PropTypes.array,
|
||||||
mnhn: PropTypes.bool,
|
|
||||||
ign: PropTypes.bool
|
ign: PropTypes.bool
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import React, { useState, useCallback, useMemo } from 'react';
|
import React, { useState, useCallback, useMemo } from 'react';
|
||||||
import ReactMapboxGl, { ZoomControl, GeoJSONLayer } from 'react-mapbox-gl';
|
import { ZoomControl, GeoJSONLayer } from 'react-mapbox-gl';
|
||||||
import mapboxgl, { Popup } from 'mapbox-gl';
|
import mapboxgl, { Popup } from 'mapbox-gl';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { getMapStyle, SwitchMapStyle } from '../MapStyles';
|
import Mapbox from '../shared/mapbox/Mapbox';
|
||||||
|
import { getMapStyle } from '../shared/mapbox/styles';
|
||||||
|
import SwitchMapStyle from '../shared/mapbox/SwitchMapStyle';
|
||||||
import {
|
import {
|
||||||
filterFeatureCollection,
|
filterFeatureCollection,
|
||||||
filterFeatureCollectionByGeometryType,
|
filterFeatureCollectionByGeometryType,
|
||||||
|
@ -12,9 +13,7 @@ import {
|
||||||
findFeature,
|
findFeature,
|
||||||
fitBounds,
|
fitBounds,
|
||||||
getCenter
|
getCenter
|
||||||
} from '../shared/map';
|
} from '../shared/mapbox/utils';
|
||||||
|
|
||||||
const Map = ReactMapboxGl({});
|
|
||||||
|
|
||||||
const MapReader = ({ featureCollection, options }) => {
|
const MapReader = ({ featureCollection, options }) => {
|
||||||
const [currentMap, setCurrentMap] = useState(null);
|
const [currentMap, setCurrentMap] = useState(null);
|
||||||
|
@ -51,11 +50,11 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
),
|
),
|
||||||
[selectionsUtilisateurFeatureCollection]
|
[selectionsUtilisateurFeatureCollection]
|
||||||
);
|
);
|
||||||
const hasCadastres = !!cadastresFeatureCollection.length;
|
const hasCadastres = useMemo(() => options.layers.includes('cadastres'));
|
||||||
const mapStyle = useMemo(
|
const mapStyle = useMemo(() => getMapStyle(style, options.layers), [
|
||||||
() => getMapStyle(style, hasCadastres, options.mnhn),
|
style,
|
||||||
[style, options, cadastresFeatureCollection]
|
options
|
||||||
);
|
]);
|
||||||
const popup = useMemo(
|
const popup = useMemo(
|
||||||
() =>
|
() =>
|
||||||
new Popup({
|
new Popup({
|
||||||
|
@ -147,7 +146,7 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Map
|
<Mapbox
|
||||||
onStyleLoad={(map) => onMapLoad(map)}
|
onStyleLoad={(map) => onMapLoad(map)}
|
||||||
fitBounds={boundData}
|
fitBounds={boundData}
|
||||||
fitBoundsOptions={{ padding: 100 }}
|
fitBoundsOptions={{ padding: 100 }}
|
||||||
|
@ -186,7 +185,7 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
|
|
||||||
<SwitchMapStyle style={style} setStyle={setStyle} ign={options.ign} />
|
<SwitchMapStyle style={style} setStyle={setStyle} ign={options.ign} />
|
||||||
<ZoomControl />
|
<ZoomControl />
|
||||||
</Map>
|
</Mapbox>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -197,8 +196,8 @@ MapReader.propTypes = {
|
||||||
features: PropTypes.array
|
features: PropTypes.array
|
||||||
}),
|
}),
|
||||||
options: PropTypes.shape({
|
options: PropTypes.shape({
|
||||||
ign: PropTypes.bool,
|
layers: PropTypes.array,
|
||||||
mnhn: PropTypes.bool
|
ign: PropTypes.bool
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
const IGN_TOKEN = 'rc1egnbeoss72hxvd143tbyk';
|
|
||||||
|
|
||||||
function ignServiceURL(layer, format = 'image/png') {
|
|
||||||
const url = `https://wxs.ign.fr/${IGN_TOKEN}/geoportail/wmts`;
|
|
||||||
const query =
|
|
||||||
'service=WMTS&request=GetTile&version=1.0.0&tilematrixset=PM&tilematrix={z}&tilecol={x}&tilerow={y}&style=normal';
|
|
||||||
|
|
||||||
return `${url}?${query}&layer=${layer}&format=${format}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function rasterSource(tiles, attribution) {
|
|
||||||
return {
|
|
||||||
type: 'raster',
|
|
||||||
tiles,
|
|
||||||
tileSize: 256,
|
|
||||||
attribution,
|
|
||||||
minzoom: 0,
|
|
||||||
maxzoom: 18
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
version: 8,
|
|
||||||
metadat: {
|
|
||||||
'mapbox:autocomposite': false,
|
|
||||||
'mapbox:groups': {
|
|
||||||
1444849242106.713: { collapsed: false, name: 'Places' },
|
|
||||||
1444849334699.1902: { collapsed: true, name: 'Bridges' },
|
|
||||||
1444849345966.4436: { collapsed: false, name: 'Roads' },
|
|
||||||
1444849354174.1904: { collapsed: true, name: 'Tunnels' },
|
|
||||||
1444849364238.8171: { collapsed: false, name: 'Buildings' },
|
|
||||||
1444849382550.77: { collapsed: false, name: 'Water' },
|
|
||||||
1444849388993.3071: { collapsed: false, name: 'Land' }
|
|
||||||
},
|
|
||||||
'mapbox:type': 'template',
|
|
||||||
'openmaptiles:mapbox:owner': 'openmaptiles',
|
|
||||||
'openmaptiles:mapbox:source:url': 'mapbox://openmaptiles.4qljc88t',
|
|
||||||
'openmaptiles:version': '3.x',
|
|
||||||
'maputnik:renderer': 'mbgljs'
|
|
||||||
},
|
|
||||||
center: [0, 0],
|
|
||||||
zoom: 1,
|
|
||||||
bearing: 0,
|
|
||||||
pitch: 0,
|
|
||||||
sources: {
|
|
||||||
'decoupage-administratif': {
|
|
||||||
type: 'vector',
|
|
||||||
url:
|
|
||||||
'https://openmaptiles.geo.data.gouv.fr/data/decoupage-administratif.json'
|
|
||||||
},
|
|
||||||
openmaptiles: {
|
|
||||||
type: 'vector',
|
|
||||||
url: 'https://openmaptiles.geo.data.gouv.fr/data/france-vector.json'
|
|
||||||
},
|
|
||||||
'photographies-aeriennes': {
|
|
||||||
type: 'raster',
|
|
||||||
tiles: [
|
|
||||||
'https://tiles.geo.api.gouv.fr/photographies-aeriennes/tiles/{z}/{x}/{y}'
|
|
||||||
],
|
|
||||||
tileSize: 256,
|
|
||||||
attribution: 'Images aériennes © IGN',
|
|
||||||
minzoom: 0,
|
|
||||||
maxzoom: 19
|
|
||||||
},
|
|
||||||
cadastre: {
|
|
||||||
type: 'vector',
|
|
||||||
url: 'https://openmaptiles.geo.data.gouv.fr/data/cadastre.json'
|
|
||||||
},
|
|
||||||
'plan-ign': rasterSource(
|
|
||||||
[ignServiceURL('GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2')],
|
|
||||||
'IGN-F/Géoportail'
|
|
||||||
),
|
|
||||||
'protectedareas-gp': rasterSource(
|
|
||||||
[ignServiceURL('PROTECTEDAREAS.GP')],
|
|
||||||
'IGN-F/Géoportail/MNHN'
|
|
||||||
),
|
|
||||||
'protectedareas-pn': rasterSource(
|
|
||||||
[ignServiceURL('PROTECTEDAREAS.PN')],
|
|
||||||
'IGN-F/Géoportail/MNHN'
|
|
||||||
),
|
|
||||||
'protectedareas-pnr': rasterSource(
|
|
||||||
[ignServiceURL('PROTECTEDAREAS.PNR')],
|
|
||||||
'IGN-F/Géoportail/MNHN'
|
|
||||||
),
|
|
||||||
'protectedareas-sic': rasterSource(
|
|
||||||
[ignServiceURL('PROTECTEDAREAS.SIC')],
|
|
||||||
'IGN-F/Géoportail/MNHN'
|
|
||||||
),
|
|
||||||
'protectedareas-zps': rasterSource(
|
|
||||||
[ignServiceURL('PROTECTEDAREAS.ZPS')],
|
|
||||||
'IGN-F/Géoportail/MNHN'
|
|
||||||
)
|
|
||||||
},
|
|
||||||
sprite: 'https://openmaptiles.github.io/osm-bright-gl-style/sprite',
|
|
||||||
glyphs: 'https://openmaptiles.geo.data.gouv.fr/fonts/{fontstack}/{range}.pbf'
|
|
||||||
};
|
|
|
@ -1,55 +0,0 @@
|
||||||
import baseStyle from './base-style';
|
|
||||||
import cadastre from './cadastre';
|
|
||||||
import orthoStyle from './ortho-style';
|
|
||||||
import vectorStyle from './vector-style';
|
|
||||||
|
|
||||||
function rasterStyle(source) {
|
|
||||||
return {
|
|
||||||
id: source,
|
|
||||||
source,
|
|
||||||
type: 'raster',
|
|
||||||
paint: { 'raster-resampling': 'linear' }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMapStyle(style, hasCadastres, hasMNHN) {
|
|
||||||
const mapStyle = { ...baseStyle };
|
|
||||||
|
|
||||||
switch (style) {
|
|
||||||
case 'ortho':
|
|
||||||
mapStyle.layers = orthoStyle;
|
|
||||||
mapStyle.id = 'ortho';
|
|
||||||
mapStyle.name = 'Photographies aériennes';
|
|
||||||
break;
|
|
||||||
case 'vector':
|
|
||||||
mapStyle.layers = vectorStyle;
|
|
||||||
mapStyle.id = 'vector';
|
|
||||||
mapStyle.name = 'Carte OSM';
|
|
||||||
break;
|
|
||||||
case 'ign':
|
|
||||||
mapStyle.layers = [rasterStyle('plan-ign')];
|
|
||||||
mapStyle.id = 'ign';
|
|
||||||
mapStyle.name = 'Carte IGN';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasCadastres) {
|
|
||||||
mapStyle.layers = mapStyle.layers.concat(cadastre);
|
|
||||||
mapStyle.id += '-cadastre';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasMNHN) {
|
|
||||||
mapStyle.layers = mapStyle.layers.concat([
|
|
||||||
rasterStyle('protectedareas-gp'),
|
|
||||||
rasterStyle('protectedareas-pn'),
|
|
||||||
rasterStyle('protectedareas-pnr'),
|
|
||||||
rasterStyle('protectedareas-sic'),
|
|
||||||
rasterStyle('protectedareas-zps')
|
|
||||||
]);
|
|
||||||
mapStyle.id += '-mnhn';
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
export { SwitchMapStyle } from './SwitchMapStyle';
|
|
3
app/javascript/components/shared/mapbox/Mapbox.js
Normal file
3
app/javascript/components/shared/mapbox/Mapbox.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import ReactMapboxGl from 'react-mapbox-gl';
|
||||||
|
|
||||||
|
export default ReactMapboxGl({});
|
|
@ -1,8 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ortho from './images/preview-ortho.png';
|
|
||||||
import vector from './images/preview-vector.png';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import ortho from './styles/images/preview-ortho.png';
|
||||||
|
import vector from './styles/images/preview-vector.png';
|
||||||
|
|
||||||
const STYLES = {
|
const STYLES = {
|
||||||
ortho: {
|
ortho: {
|
||||||
title: 'Satellite',
|
title: 'Satellite',
|
||||||
|
@ -34,7 +35,7 @@ function getNextStyle(style, ign) {
|
||||||
return styles[index];
|
return styles[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SwitchMapStyle = ({ style, setStyle, ign }) => {
|
function SwitchMapStyle({ style, setStyle, ign }) {
|
||||||
const nextStyle = getNextStyle(style, ign);
|
const nextStyle = getNextStyle(style, ign);
|
||||||
const { title, preview, color } = (ign ? IGN_STYLES : STYLES)[nextStyle];
|
const { title, preview, color } = (ign ? IGN_STYLES : STYLES)[nextStyle];
|
||||||
|
|
||||||
|
@ -69,10 +70,12 @@ export const SwitchMapStyle = ({ style, setStyle, ign }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
SwitchMapStyle.propTypes = {
|
SwitchMapStyle.propTypes = {
|
||||||
style: PropTypes.string,
|
style: PropTypes.string,
|
||||||
setStyle: PropTypes.func,
|
setStyle: PropTypes.func,
|
||||||
ign: PropTypes.bool
|
ign: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default SwitchMapStyle;
|
213
app/javascript/components/shared/mapbox/styles/base.js
Normal file
213
app/javascript/components/shared/mapbox/styles/base.js
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
import cadastreLayers from './cadastre-layers';
|
||||||
|
|
||||||
|
const IGN_TOKEN = 'rc1egnbeoss72hxvd143tbyk';
|
||||||
|
|
||||||
|
function ignServiceURL(layer, format = 'image/png') {
|
||||||
|
const url = `https://wxs.ign.fr/${IGN_TOKEN}/geoportail/wmts`;
|
||||||
|
const query =
|
||||||
|
'service=WMTS&request=GetTile&version=1.0.0&tilematrixset=PM&tilematrix={z}&tilecol={x}&tilerow={y}&style=normal';
|
||||||
|
|
||||||
|
return `${url}?${query}&layer=${layer}&format=${format}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OPTIONAL_LAYERS = [
|
||||||
|
{
|
||||||
|
label: 'UNESCO',
|
||||||
|
id: 'unesco',
|
||||||
|
layers: [
|
||||||
|
['Aires protégées Géoparcs', 'PROTECTEDAREAS.GP'],
|
||||||
|
['Réserves de biosphère', 'PROTECTEDAREAS.BIOS']
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Arrêtés de protection',
|
||||||
|
id: 'arretes_protection',
|
||||||
|
layers: [
|
||||||
|
['Arrêtés de protection de biotope', 'PROTECTEDAREAS.APB'],
|
||||||
|
['Arrêtés de protection de géotope', 'PROTECTEDAREAS.APG']
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Conservatoire du Littoral',
|
||||||
|
id: 'conservatoire_littoral',
|
||||||
|
layers: [
|
||||||
|
[
|
||||||
|
'Conservatoire du littoral : parcelles protégées',
|
||||||
|
'PROTECTEDAREAS.MNHN.CDL.PARCELS'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Conservatoire du littoral : périmètres d’intervention',
|
||||||
|
'PROTECTEDAREAS.MNHN.CDL.PERIMETER'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Réserves nationales de chasse et de faune sauvage',
|
||||||
|
id: 'reserves_chasse_faune_sauvage',
|
||||||
|
layers: [
|
||||||
|
[
|
||||||
|
'Réserves nationales de chasse et de faune sauvage',
|
||||||
|
'PROTECTEDAREAS.RNCF'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Réserves biologiques',
|
||||||
|
id: 'reserves_biologiques',
|
||||||
|
layers: [['Réserves biologiques', 'PROTECTEDAREAS.RB']]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Réserves naturelles',
|
||||||
|
id: 'reserves_naturelles',
|
||||||
|
layers: [
|
||||||
|
['Réserves naturelles nationales', 'PROTECTEDAREAS.RN'],
|
||||||
|
[
|
||||||
|
'Périmètres de protection de réserves naturelles',
|
||||||
|
'PROTECTEDAREAS.MNHN.RN.PERIMETER'
|
||||||
|
],
|
||||||
|
['Réserves naturelles de Corse', 'PROTECTEDAREAS.RNC'],
|
||||||
|
[
|
||||||
|
'Réserves naturelles régionales',
|
||||||
|
'PROTECTEDSITES.MNHN.RESERVES-REGIONALES'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Natura 2000',
|
||||||
|
id: 'natura_2000',
|
||||||
|
layers: [
|
||||||
|
['Sites Natura 2000 (Directive Habitats)', 'PROTECTEDAREAS.SIC'],
|
||||||
|
['Sites Natura 2000 (Directive Oiseaux)', 'PROTECTEDAREAS.ZPS']
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Zones humides d’importance internationale',
|
||||||
|
id: 'zones_humides',
|
||||||
|
layers: [
|
||||||
|
['Zones humides d’importance internationale', 'PROTECTEDAREAS.RAMSAR']
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ZNIEFF',
|
||||||
|
id: 'znieff',
|
||||||
|
layers: [
|
||||||
|
[
|
||||||
|
'Zones naturelles d’intérêt écologique faunistique et floristique de type 1 (ZNIEFF 1 mer)',
|
||||||
|
'PROTECTEDAREAS.ZNIEFF1.SEA'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Zones naturelles d’intérêt écologique faunistique et floristique de type 1 (ZNIEFF 1)',
|
||||||
|
'PROTECTEDAREAS.ZNIEFF1'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Zones naturelles d’intérêt écologique faunistique et floristique de type 2 (ZNIEFF 2 mer)',
|
||||||
|
'PROTECTEDAREAS.ZNIEFF2.SEA'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Zones naturelles d’intérêt écologique faunistique et floristique de type 2 (ZNIEFF 2)',
|
||||||
|
'PROTECTEDAREAS.ZNIEFF2'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Cadastre',
|
||||||
|
id: 'cadastres',
|
||||||
|
layers: [['Cadastre', 'CADASTRE']]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function buildSources() {
|
||||||
|
return Object.fromEntries(
|
||||||
|
OPTIONAL_LAYERS.flatMap(({ layers }) => layers).map(([, code]) => [
|
||||||
|
code.toLowerCase().replace(/\./g, '-'),
|
||||||
|
rasterSource([ignServiceURL(code)], 'IGN-F/Géoportail/MNHN')
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function rasterSource(tiles, attribution) {
|
||||||
|
return {
|
||||||
|
type: 'raster',
|
||||||
|
tiles,
|
||||||
|
tileSize: 256,
|
||||||
|
attribution,
|
||||||
|
minzoom: 0,
|
||||||
|
maxzoom: 18
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildLayers(ids) {
|
||||||
|
return OPTIONAL_LAYERS.filter(({ id }) => ids.includes(id))
|
||||||
|
.flatMap(({ layers }) => layers)
|
||||||
|
.map(([, code]) =>
|
||||||
|
code === 'CADASTRE'
|
||||||
|
? cadastreLayers
|
||||||
|
: rasterLayer(code.toLowerCase().replace(/\./g, '-'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rasterLayer(source) {
|
||||||
|
return {
|
||||||
|
id: source,
|
||||||
|
source,
|
||||||
|
type: 'raster',
|
||||||
|
paint: { 'raster-resampling': 'linear' }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
version: 8,
|
||||||
|
metadat: {
|
||||||
|
'mapbox:autocomposite': false,
|
||||||
|
'mapbox:groups': {
|
||||||
|
1444849242106.713: { collapsed: false, name: 'Places' },
|
||||||
|
1444849334699.1902: { collapsed: true, name: 'Bridges' },
|
||||||
|
1444849345966.4436: { collapsed: false, name: 'Roads' },
|
||||||
|
1444849354174.1904: { collapsed: true, name: 'Tunnels' },
|
||||||
|
1444849364238.8171: { collapsed: false, name: 'Buildings' },
|
||||||
|
1444849382550.77: { collapsed: false, name: 'Water' },
|
||||||
|
1444849388993.3071: { collapsed: false, name: 'Land' }
|
||||||
|
},
|
||||||
|
'mapbox:type': 'template',
|
||||||
|
'openmaptiles:mapbox:owner': 'openmaptiles',
|
||||||
|
'openmaptiles:mapbox:source:url': 'mapbox://openmaptiles.4qljc88t',
|
||||||
|
'openmaptiles:version': '3.x',
|
||||||
|
'maputnik:renderer': 'mbgljs'
|
||||||
|
},
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 1,
|
||||||
|
bearing: 0,
|
||||||
|
pitch: 0,
|
||||||
|
sources: {
|
||||||
|
'decoupage-administratif': {
|
||||||
|
type: 'vector',
|
||||||
|
url:
|
||||||
|
'https://openmaptiles.geo.data.gouv.fr/data/decoupage-administratif.json'
|
||||||
|
},
|
||||||
|
openmaptiles: {
|
||||||
|
type: 'vector',
|
||||||
|
url: 'https://openmaptiles.geo.data.gouv.fr/data/france-vector.json'
|
||||||
|
},
|
||||||
|
'photographies-aeriennes': {
|
||||||
|
type: 'raster',
|
||||||
|
tiles: [
|
||||||
|
'https://tiles.geo.api.gouv.fr/photographies-aeriennes/tiles/{z}/{x}/{y}'
|
||||||
|
],
|
||||||
|
tileSize: 256,
|
||||||
|
attribution: 'Images aériennes © IGN',
|
||||||
|
minzoom: 0,
|
||||||
|
maxzoom: 19
|
||||||
|
},
|
||||||
|
cadastre: {
|
||||||
|
type: 'vector',
|
||||||
|
url: 'https://openmaptiles.geo.data.gouv.fr/data/cadastre.json'
|
||||||
|
},
|
||||||
|
'plan-ign': rasterSource(
|
||||||
|
[ignServiceURL('GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2')],
|
||||||
|
'IGN-F/Géoportail'
|
||||||
|
),
|
||||||
|
...buildSources()
|
||||||
|
},
|
||||||
|
sprite: 'https://openmaptiles.github.io/osm-bright-gl-style/sprite',
|
||||||
|
glyphs: 'https://openmaptiles.geo.data.gouv.fr/fonts/{fontstack}/{range}.pbf'
|
||||||
|
};
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
29
app/javascript/components/shared/mapbox/styles/index.js
Normal file
29
app/javascript/components/shared/mapbox/styles/index.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import baseStyle, { rasterLayer, buildLayers } from './base';
|
||||||
|
import orthoStyle from './ortho-style';
|
||||||
|
import vectorStyle from './vector-style';
|
||||||
|
|
||||||
|
export function getMapStyle(style, optionalLayers) {
|
||||||
|
const mapStyle = { ...baseStyle };
|
||||||
|
|
||||||
|
switch (style) {
|
||||||
|
case 'ortho':
|
||||||
|
mapStyle.layers = orthoStyle;
|
||||||
|
mapStyle.id = 'ortho';
|
||||||
|
mapStyle.name = 'Photographies aériennes';
|
||||||
|
break;
|
||||||
|
case 'vector':
|
||||||
|
mapStyle.layers = vectorStyle;
|
||||||
|
mapStyle.id = 'vector';
|
||||||
|
mapStyle.name = 'Carte OSM';
|
||||||
|
break;
|
||||||
|
case 'ign':
|
||||||
|
mapStyle.layers = [rasterLayer('plan-ign')];
|
||||||
|
mapStyle.id = 'ign';
|
||||||
|
mapStyle.name = 'Carte IGN';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapStyle.layers = mapStyle.layers.concat(buildLayers(optionalLayers));
|
||||||
|
|
||||||
|
return mapStyle;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue