fix(carto): show map UI before loading map styles

This commit is contained in:
Paul Chavard 2022-02-24 16:20:17 +00:00
parent 022fb04e2b
commit 2a42690388
7 changed files with 45 additions and 40 deletions

View file

@ -57,7 +57,8 @@ module.exports = {
'prettier/prettier': 'error', 'prettier/prettier': 'error',
'react-hooks/rules-of-hooks': 'error', 'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error', 'react-hooks/exhaustive-deps': 'error',
'@typescript-eslint/no-explicit-any': 'error' '@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unused-vars': 'error'
} }
} }
] ]

View file

@ -1,12 +1,9 @@
import React from 'react'; import React from 'react';
import type { Point } from 'geojson'; import { fire } from '@utils';
import ComboAdresseSearch from '../../ComboAdresseSearch'; import ComboAdresseSearch from '../../ComboAdresseSearch';
import { useFlyTo } from '../../shared/maplibre/hooks';
export function AddressInput() { export function AddressInput() {
const flyTo = useFlyTo();
return ( return (
<div <div
style={{ style={{
@ -17,9 +14,8 @@ export function AddressInput() {
className="no-margin" className="no-margin"
placeholder="Rechercher une adresse : saisissez au moins 2 caractères" placeholder="Rechercher une adresse : saisissez au moins 2 caractères"
allowInputValues={false} allowInputValues={false}
onChange={(_, result) => { onChange={(_, feature) => {
const geometry = result?.geometry as Point; fire(document, 'map:zoom', { feature });
flyTo(17, geometry.coordinates as [number, number]);
}} }}
/> />
</div> </div>

View file

@ -7,7 +7,8 @@ import { useMapLibre } from '../../shared/maplibre/MapLibre';
import { import {
useFitBounds, useFitBounds,
useEvent, useEvent,
useMapEvent useMapEvent,
useFlyTo
} from '../../shared/maplibre/hooks'; } from '../../shared/maplibre/hooks';
import { import {
filterFeatureCollection, filterFeatureCollection,
@ -116,6 +117,7 @@ function useExternalEvents(
} }
) { ) {
const fitBounds = useFitBounds(); const fitBounds = useFitBounds();
const flyTo = useFlyTo();
const onFeatureFocus = useCallback( const onFeatureFocus = useCallback(
({ detail }) => { ({ detail }) => {
@ -132,6 +134,16 @@ function useExternalEvents(
[featureCollection, fitBounds] [featureCollection, fitBounds]
); );
const onZoomFocus = useCallback(
({ detail }) => {
const { feature } = detail;
if (feature) {
flyTo(17, feature.geometry.coordinates);
}
},
[flyTo]
);
const onFeatureCreate = useCallback( const onFeatureCreate = useCallback(
({ detail }) => { ({ detail }) => {
const { geometry, properties } = detail; const { geometry, properties } = detail;
@ -181,6 +193,7 @@ function useExternalEvents(
useEvent('map:feature:create', onFeatureCreate); useEvent('map:feature:create', onFeatureCreate);
useEvent('map:feature:update', onFeatureUpdate); useEvent('map:feature:update', onFeatureUpdate);
useEvent('map:feature:delete', onFeatureDelete); useEvent('map:feature:delete', onFeatureDelete);
useEvent('map:zoom', onZoomFocus);
} }
const translations = [ const translations = [

View file

@ -5,11 +5,7 @@ import { PlusIcon, LocationMarkerIcon } from '@heroicons/react/outline';
import { useId } from '@reach/auto-id'; import { useId } from '@reach/auto-id';
import CoordinateInput from 'react-coordinate-input'; import CoordinateInput from 'react-coordinate-input';
import { useFlyTo } from '../../shared/maplibre/hooks';
export function PointInput() { export function PointInput() {
const flyTo = useFlyTo();
const inputId = useId(); const inputId = useId();
const [value, setValue] = useState(''); const [value, setValue] = useState('');
const [feature, setFeature] = useState<Feature | null>(null); const [feature, setFeature] = useState<Feature | null>(null);
@ -60,15 +56,13 @@ export function PointInput() {
setValue(value); setValue(value);
if (dd.length) { if (dd.length) {
const coordinates: [number, number] = [dd[1], dd[0]]; const coordinates: [number, number] = [dd[1], dd[0]];
setFeature({ const feature = {
type: 'Feature', type: 'Feature' as const,
geometry: { geometry: { type: 'Point' as const, coordinates },
type: 'Point',
coordinates
},
properties: {} properties: {}
}); };
flyTo(17, coordinates); setFeature(feature);
fire(document, 'map:zoom', { feature });
} else { } else {
setFeature(null); setFeature(null);
} }

View file

@ -46,19 +46,11 @@ export default function MapEditor({
</p> </p>
</div> </div>
{error && <FlashMessage message={error} level="alert" fixed={true} />} {error && <FlashMessage message={error} level="alert" fixed={true} />}
<MapLibre
layers={options.layers} <ImportFileInput featureCollection={featureCollection} {...actions} />
header={
<>
<ImportFileInput
featureCollection={featureCollection}
{...actions}
/>
<AddressInput /> <AddressInput />
</>
} <MapLibre layers={options.layers}>
footer={<PointInput />}
>
<DrawLayer <DrawLayer
featureCollection={featureCollection} featureCollection={featureCollection}
{...actions} {...actions}
@ -86,6 +78,7 @@ export default function MapEditor({
</> </>
) : null} ) : null}
</MapLibre> </MapLibre>
<PointInput />
</> </>
); );
} }

View file

@ -7,7 +7,8 @@ import {
useFitBounds, useFitBounds,
useEvent, useEvent,
EventHandler, EventHandler,
useMapEvent useMapEvent,
useFlyTo
} from '../../shared/maplibre/hooks'; } from '../../shared/maplibre/hooks';
import { import {
filterFeatureCollection, filterFeatureCollection,
@ -99,6 +100,7 @@ export function GeoJSONLayer({
function useExternalEvents(featureCollection: FeatureCollection) { function useExternalEvents(featureCollection: FeatureCollection) {
const fitBounds = useFitBounds(); const fitBounds = useFitBounds();
const flyTo = useFlyTo();
const onFeatureFocus = useCallback( const onFeatureFocus = useCallback(
({ detail }) => { ({ detail }) => {
const { id } = detail; const { id } = detail;
@ -109,6 +111,15 @@ function useExternalEvents(featureCollection: FeatureCollection) {
}, },
[featureCollection, fitBounds] [featureCollection, fitBounds]
); );
const onZoomFocus = useCallback(
({ detail }) => {
const { feature } = detail;
if (feature) {
flyTo(17, feature.geometry.coordinates);
}
},
[flyTo]
);
useEffect(() => { useEffect(() => {
fitBounds(featureCollection.bbox as LngLatBoundsLike); fitBounds(featureCollection.bbox as LngLatBoundsLike);
@ -117,6 +128,7 @@ function useExternalEvents(featureCollection: FeatureCollection) {
}, [fitBounds]); }, [fitBounds]);
useEvent('map:feature:focus', onFeatureFocus); useEvent('map:feature:focus', onFeatureFocus);
useEvent('map:zoom', onZoomFocus);
} }
function LineStringLayer({ function LineStringLayer({

View file

@ -19,8 +19,6 @@ const Context = createContext<{ map?: Map | null }>({});
type MapLibreProps = { type MapLibreProps = {
layers: string[]; layers: string[];
header?: ReactNode;
footer?: ReactNode;
children: ReactNode; children: ReactNode;
}; };
@ -30,7 +28,7 @@ export function useMapLibre() {
return context.map; return context.map;
} }
export function MapLibre({ children, header, footer, layers }: MapLibreProps) { export function MapLibre({ children, layers }: MapLibreProps) {
const isSupported = useMemo( const isSupported = useMemo(
() => maplibre.supported({ failIfMajorPerformanceCaveat: true }) && !isIE(), () => maplibre.supported({ failIfMajorPerformanceCaveat: true }) && !isIE(),
[] []
@ -90,12 +88,10 @@ export function MapLibre({ children, header, footer, layers }: MapLibreProps) {
return ( return (
<Context.Provider value={{ map }}> <Context.Provider value={{ map }}>
{map ? header : null}
<div ref={containerRef} style={{ height: '500px' }}> <div ref={containerRef} style={{ height: '500px' }}>
<StyleControl styleId={style.id} {...mapStyleProps} /> <StyleControl styleId={style.id} {...mapStyleProps} />
{map ? children : null} {map ? children : null}
</div> </div>
{map ? footer : null}
</Context.Provider> </Context.Provider>
); );
} }