IGN layers on maps can now be disabled by the user
This commit is contained in:
parent
a29e1761f4
commit
fc966a2761
11 changed files with 245 additions and 48 deletions
|
@ -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;
|
||||
|
|
|
@ -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 |
|
@ -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 };
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue