Merge pull request #6316 from tchak/carto-layers
Make IGN layers opacity configurable
This commit is contained in:
commit
50ebd6d17a
5 changed files with 76 additions and 32 deletions
|
@ -46,6 +46,7 @@
|
||||||
margin-bottom: $default-spacer;
|
margin-bottom: $default-spacer;
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
|
list-style: none;
|
||||||
padding: $default-spacer;
|
padding: $default-spacer;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
margin-bottom: -$default-spacer;
|
margin-bottom: -$default-spacer;
|
||||||
|
|
|
@ -42,7 +42,7 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
<Mapbox
|
<Mapbox
|
||||||
onStyleLoad={(map) => onLoad(map)}
|
onStyleLoad={(map) => onLoad(map)}
|
||||||
style={style}
|
style={style}
|
||||||
containerStyle={{ height: '400px' }}
|
containerStyle={{ height: '500px' }}
|
||||||
>
|
>
|
||||||
<SelectionUtilisateurPolygonLayer
|
<SelectionUtilisateurPolygonLayer
|
||||||
featureCollection={featureCollection}
|
featureCollection={featureCollection}
|
||||||
|
|
|
@ -3,8 +3,10 @@ import PropTypes from 'prop-types';
|
||||||
import { Popover, RadioGroup } from '@headlessui/react';
|
import { Popover, RadioGroup } from '@headlessui/react';
|
||||||
import { usePopper } from 'react-popper';
|
import { usePopper } from 'react-popper';
|
||||||
import { MapIcon } from '@heroicons/react/outline';
|
import { MapIcon } from '@heroicons/react/outline';
|
||||||
|
import { Slider } from '@reach/slider';
|
||||||
|
import '@reach/slider/styles.css';
|
||||||
|
|
||||||
import { getMapStyle, getLayerName } from './styles';
|
import { getMapStyle, getLayerName, NBS } from './styles';
|
||||||
|
|
||||||
const STYLES = {
|
const STYLES = {
|
||||||
ortho: 'Satellite',
|
ortho: 'Satellite',
|
||||||
|
@ -16,7 +18,10 @@ function optionalLayersMap(optionalLayers) {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
optionalLayers
|
optionalLayers
|
||||||
.filter((layer) => layer != 'cadastres')
|
.filter((layer) => layer != 'cadastres')
|
||||||
.map((layer) => [layer, { enabled: true, opacity: 100 }])
|
.map((layer) => [
|
||||||
|
layer,
|
||||||
|
{ enabled: true, opacity: 70, name: getLayerName(layer) }
|
||||||
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +48,10 @@ export function useMapStyle(
|
||||||
() =>
|
() =>
|
||||||
getMapStyle(
|
getMapStyle(
|
||||||
styleId,
|
styleId,
|
||||||
enabledLayers.map(([layer]) => layer)
|
enabledLayers.map(([layer]) => layer),
|
||||||
|
Object.fromEntries(
|
||||||
|
enabledLayers.map(([layer, { opacity }]) => [layer, opacity])
|
||||||
|
)
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
styleId,
|
styleId,
|
||||||
|
@ -56,7 +64,13 @@ export function useMapStyle(
|
||||||
return { style, layers, setStyle, setLayerEnabled, setLayerOpacity };
|
return { style, layers, setStyle, setLayerEnabled, setLayerOpacity };
|
||||||
}
|
}
|
||||||
|
|
||||||
function MapStyleControl({ style, layers, setStyle, setLayerEnabled }) {
|
function MapStyleControl({
|
||||||
|
style,
|
||||||
|
layers,
|
||||||
|
setStyle,
|
||||||
|
setLayerEnabled,
|
||||||
|
setLayerOpacity
|
||||||
|
}) {
|
||||||
const [buttonElement, setButtonElement] = useState();
|
const [buttonElement, setButtonElement] = useState();
|
||||||
const [panelElement, setPanelElement] = useState();
|
const [panelElement, setPanelElement] = useState();
|
||||||
const { styles, attributes } = usePopper(buttonElement, panelElement, {
|
const { styles, attributes } = usePopper(buttonElement, panelElement, {
|
||||||
|
@ -111,19 +125,40 @@ function MapStyleControl({ style, layers, setStyle, setLayerEnabled }) {
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
{Object.keys(layers).length ? (
|
{Object.keys(layers).length ? (
|
||||||
<ul className="layers-list">
|
<ul className="layers-list">
|
||||||
{Object.entries(layers).map(([layer, { enabled }]) => (
|
{Object.entries(layers).map(
|
||||||
<li key={layer} className="flex">
|
([layer, { enabled, opacity, name }]) => (
|
||||||
<input
|
<li key={layer}>
|
||||||
className="m-0 p-0 mr-1"
|
<div className="flex mb-1">
|
||||||
type="checkbox"
|
<input
|
||||||
checked={enabled}
|
className="m-0 p-0 mr-1"
|
||||||
onChange={(event) => {
|
type="checkbox"
|
||||||
setLayerEnabled(layer, event.target.checked);
|
checked={enabled}
|
||||||
}}
|
onChange={(event) => {
|
||||||
/>
|
setLayerEnabled(layer, event.target.checked);
|
||||||
<label>{getLayerName(layer)}</label>
|
}}
|
||||||
</li>
|
/>
|
||||||
))}
|
<label className="m-0">{name}</label>
|
||||||
|
</div>
|
||||||
|
<Slider
|
||||||
|
min={10}
|
||||||
|
max={100}
|
||||||
|
step={5}
|
||||||
|
value={opacity}
|
||||||
|
onChange={(value) => {
|
||||||
|
setLayerOpacity(layer, value);
|
||||||
|
}}
|
||||||
|
className="mb-1"
|
||||||
|
title={`Réglage de l’opacité de la couche «${NBS}${name}${NBS}»`}
|
||||||
|
getAriaLabel={() =>
|
||||||
|
`Réglage de l’opacité de la couche «${NBS}${name}${NBS}»`
|
||||||
|
}
|
||||||
|
getAriaValueText={(value) =>
|
||||||
|
`L’opacité de la couche «${NBS}${name}${NBS}» est à ${value}${NBS}%`
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
) : null}
|
) : null}
|
||||||
</Popover.Panel>
|
</Popover.Panel>
|
||||||
|
|
|
@ -119,9 +119,9 @@ const OPTIONAL_LAYERS = [
|
||||||
function buildSources() {
|
function buildSources() {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
OPTIONAL_LAYERS.filter(({ id }) => id !== 'cadastres')
|
OPTIONAL_LAYERS.filter(({ id }) => id !== 'cadastres')
|
||||||
.flatMap(({ layers }) => layers)
|
.flatMap(({ layers }) => layers.map(([, code]) => code))
|
||||||
.map(([, code]) => [
|
.map((code) => [
|
||||||
code.toLowerCase().replace(/\./g, '-'),
|
getLayerCode(code),
|
||||||
rasterSource([ignServiceURL(code)], 'IGN-F/Géoportail/MNHN')
|
rasterSource([ignServiceURL(code)], 'IGN-F/Géoportail/MNHN')
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
@ -138,32 +138,40 @@ function rasterSource(tiles, attribution) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function rasterLayer(source) {
|
function rasterLayer(source, opacity) {
|
||||||
return {
|
return {
|
||||||
id: source,
|
id: source,
|
||||||
source,
|
source,
|
||||||
type: 'raster',
|
type: 'raster',
|
||||||
paint: { 'raster-resampling': 'linear' }
|
paint: { 'raster-resampling': 'linear', 'raster-opacity': opacity }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildOptionalLayers(ids) {
|
export function buildOptionalLayers(ids, opacity) {
|
||||||
return OPTIONAL_LAYERS.filter(({ id }) => ids.includes(id))
|
return OPTIONAL_LAYERS.filter(({ id }) => ids.includes(id))
|
||||||
.flatMap(({ layers }) => layers)
|
.flatMap(({ layers, id }) =>
|
||||||
.flatMap(([, code]) =>
|
layers.map(([, code]) => [code, opacity[id] / 100])
|
||||||
|
)
|
||||||
|
.flatMap(([code, opacity]) =>
|
||||||
code === 'CADASTRE'
|
code === 'CADASTRE'
|
||||||
? cadastreLayers
|
? cadastreLayers
|
||||||
: [rasterLayer(code.toLowerCase().replace(/\./g, '-'))]
|
: [rasterLayer(getLayerCode(code), opacity)]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const NBS = ' ';
|
||||||
|
|
||||||
export function getLayerName(layer) {
|
export function getLayerName(layer) {
|
||||||
return OPTIONAL_LAYERS.find(({ id }) => id == layer).label.replace(
|
return OPTIONAL_LAYERS.find(({ id }) => id == layer).label.replace(
|
||||||
/\s/g,
|
/\s/g,
|
||||||
' '
|
NBS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLayerCode(code) {
|
||||||
|
return code.toLowerCase().replace(/\./g, '-');
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
version: 8,
|
version: 8,
|
||||||
metadat: {
|
metadat: {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import baseStyle, { buildOptionalLayers, getLayerName } from './base';
|
import baseStyle, { buildOptionalLayers, getLayerName, NBS } from './base';
|
||||||
import orthoStyle from './layers/ortho';
|
import orthoStyle from './layers/ortho';
|
||||||
import vectorStyle from './layers/vector';
|
import vectorStyle from './layers/vector';
|
||||||
import ignLayers from './layers/ign';
|
import ignLayers from './layers/ign';
|
||||||
|
|
||||||
export { getLayerName };
|
export { getLayerName, NBS };
|
||||||
|
|
||||||
export function getMapStyle(id, optionalLayers) {
|
export function getMapStyle(id, layers, opacity) {
|
||||||
const style = { ...baseStyle, id };
|
const style = { ...baseStyle, id };
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
@ -23,7 +23,7 @@ export function getMapStyle(id, optionalLayers) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
style.layers = style.layers.concat(buildOptionalLayers(optionalLayers));
|
style.layers = style.layers.concat(buildOptionalLayers(layers, opacity));
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue