Merge pull request #6316 from tchak/carto-layers

Make IGN layers opacity configurable
This commit is contained in:
Paul Chavard 2021-07-06 11:17:46 +02:00 committed by GitHub
commit 50ebd6d17a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 32 deletions

View file

@ -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;

View file

@ -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}

View file

@ -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 lopacité de la couche «${NBS}${name}${NBS}»`}
getAriaLabel={() =>
`Réglage de lopacité de la couche «${NBS}${name}${NBS}»`
}
getAriaValueText={(value) =>
`Lopacité de la couche «${NBS}${name}${NBS}» est à ${value}${NBS}%`
}
/>
</li>
)
)}
</ul> </ul>
) : null} ) : null}
</Popover.Panel> </Popover.Panel>

View file

@ -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: {

View file

@ -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;
} }