IGN layers on maps can now be disabled by the user

This commit is contained in:
Paul Chavard 2021-06-30 10:28:02 +02:00
parent a29e1761f4
commit fc966a2761
11 changed files with 245 additions and 48 deletions

View file

@ -1,35 +1,23 @@
import React, { useMemo, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Popover, RadioGroup } from '@headlessui/react';
import { usePopper } from 'react-popper';
import { MapIcon } from '@heroicons/react/outline';
import { getMapStyle } from './styles';
import ortho from './styles/images/preview-ortho.png';
import vector from './styles/images/preview-vector.png';
import { getMapStyle, getLayerName } from './styles';
const STYLES = {
ortho: {
title: 'Satellite',
preview: ortho,
color: '#fff'
},
vector: {
title: 'Vectoriel',
preview: vector,
color: '#000'
},
ign: {
title: 'Carte IGN',
preview: vector,
color: '#000'
}
ortho: 'Satellite',
vector: 'Vectoriel',
ign: 'Carte IGN'
};
function getNextStyle(style) {
const styleNames = Object.keys(STYLES);
const index = styleNames.indexOf(style) + 1;
if (index === styleNames.length) {
return styleNames[0];
}
return styleNames[index];
function optionalLayersMap(optionalLayers) {
return Object.fromEntries(
optionalLayers
.filter((layer) => layer != 'cadastres')
.map((layer) => [layer, { enabled: true, opacity: 100 }])
);
}
export function useMapStyle(
@ -37,33 +25,119 @@ export function useMapStyle(
{ onStyleChange, cadastreEnabled }
) {
const [styleId, setStyle] = useState('ortho');
const style = useMemo(() => getMapStyle(styleId, optionalLayers), [
styleId,
optionalLayers
]);
const [layers, setLayers] = useState(() => optionalLayersMap(optionalLayers));
const setLayerEnabled = (layer, enabled) =>
setLayers((optionalLayers) => {
optionalLayers[layer].enabled = enabled;
return { ...optionalLayers };
});
const setLayerOpacity = (layer, opacity) =>
setLayers((optionalLayers) => {
optionalLayers[layer].opacity = opacity;
return { ...optionalLayers };
});
const enabledLayers = Object.entries(layers).filter(
([, { enabled }]) => enabled
);
const style = useMemo(
() =>
getMapStyle(
styleId,
enabledLayers.map(([layer]) => layer)
),
[
styleId,
enabledLayers.map(([layer, { opacity }]) => `${layer}-${opacity}`)
]
);
useEffect(() => onStyleChange(), [styleId, cadastreEnabled]);
return [style, setStyle];
return { style, layers, setStyle, setLayerEnabled, setLayerOpacity };
}
function MapStyleControl({ style, setStyle }) {
const nextStyle = getNextStyle(style);
const { title, preview, color } = STYLES[nextStyle];
function MapStyleControl({ style, layers, setStyle, setLayerEnabled }) {
const [buttonElement, setButtonElement] = useState();
const [panelElement, setPanelElement] = useState();
const { styles, attributes } = usePopper(buttonElement, panelElement, {
placement: 'bottom-end'
});
return (
<div className="map-style-control">
<button type="button" onClick={() => setStyle(nextStyle)}>
<img alt={title} src={preview} />
<div style={{ color }}>{title}</div>
</button>
<div className="form map-style-control mapboxgl-ctrl-group">
<Popover>
<Popover.Button
ref={setButtonElement}
className="map-style-button"
title="Sélectionner les couches cartographiques"
>
<MapIcon className="icon-size" />
</Popover.Button>
<Popover.Panel
className="flex map-style-panel mapboxgl-ctrl-group"
ref={setPanelElement}
style={styles.popper}
{...attributes.popper}
>
<RadioGroup
value={style}
onChange={setStyle}
className="styles-list"
as="ul"
>
{Object.entries(STYLES).map(([style, title]) => (
<RadioGroup.Option
key={style}
value={style}
as="li"
className="flex"
>
{({ checked }) => (
<>
<input
type="radio"
key={`${style}-${checked}`}
defaultChecked={checked}
name="map-style"
className="m-0 p-0 mr-1"
/>
<RadioGroup.Label>
{title.replace(/\s/g, ' ')}
</RadioGroup.Label>
</>
)}
</RadioGroup.Option>
))}
</RadioGroup>
{Object.keys(layers).length ? (
<ul className="layers-list">
{Object.entries(layers).map(([layer, { enabled }]) => (
<li key={layer} className="flex">
<input
className="m-0 p-0 mr-1"
type="checkbox"
checked={enabled}
onChange={(event) => {
setLayerEnabled(layer, event.target.checked);
}}
/>
<label>{getLayerName(layer)}</label>
</li>
))}
</ul>
) : null}
</Popover.Panel>
</Popover>
</div>
);
}
MapStyleControl.propTypes = {
style: PropTypes.string,
setStyle: PropTypes.func
layers: PropTypes.object,
setStyle: PropTypes.func,
setLayerEnabled: PropTypes.func,
setLayerOpacity: PropTypes.func
};
export default MapStyleControl;

View file

@ -157,6 +157,13 @@ export function buildOptionalLayers(ids) {
);
}
export function getLayerName(layer) {
return OPTIONAL_LAYERS.find(({ id }) => id == layer).label.replace(
/\s/g,
' '
);
}
export default {
version: 8,
metadat: {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -1,8 +1,10 @@
import baseStyle, { buildOptionalLayers } from './base';
import baseStyle, { buildOptionalLayers, getLayerName } from './base';
import orthoStyle from './layers/ortho';
import vectorStyle from './layers/vector';
import ignLayers from './layers/ign';
export { getLayerName };
export function getMapStyle(id, optionalLayers) {
const style = { ...baseStyle, id };