From 2fa6199979c30a815d5b299f5c392c1e32f41fcc Mon Sep 17 00:00:00 2001 From: evlist Date: Wed, 23 Nov 2022 18:25:23 +0100 Subject: [PATCH] ShowLocation component. --- .../get-location/GetLocation.module.css | 4 +- src/components/get-location/GetLocation.tsx | 4 + src/components/map/Map.tsx | 80 +++++++++++++++++-- src/components/show-location/ShowLocation.tsx | 29 +++++++ src/components/show-location/index.ts | 1 + 5 files changed, 107 insertions(+), 11 deletions(-) create mode 100644 src/components/show-location/ShowLocation.tsx create mode 100644 src/components/show-location/index.ts diff --git a/src/components/get-location/GetLocation.module.css b/src/components/get-location/GetLocation.module.css index b83dd6f..81afee6 100644 --- a/src/components/get-location/GetLocation.module.css +++ b/src/components/get-location/GetLocation.module.css @@ -3,7 +3,5 @@ --ion-background-color: white; margin-left: calc(50% - 20px); position: fixed; - bottom: 6px - ; + bottom: 6px; } - diff --git a/src/components/get-location/GetLocation.tsx b/src/components/get-location/GetLocation.tsx index 541bc31..f278e57 100644 --- a/src/components/get-location/GetLocation.tsx +++ b/src/components/get-location/GetLocation.tsx @@ -7,12 +7,15 @@ import { IonButton, IonIcon } from '@ionic/react'; import { locateOutline } from 'ionicons/icons'; import { useAtom } from 'jotai'; import { stateAtom } from '../map'; +import { locationAtom } from '../show-location'; // import { locationAtom } from '../map/CurrentLocation'; const GetLocation: React.FC<{}> = () => { const [state, setState] = useAtom(stateAtom); + const [, setLocation] = useAtom(locationAtom); + const onClickHandler = (event: any) => { console.log('Click handler'); Geolocation.getCurrentPosition().then((position) => { @@ -22,6 +25,7 @@ const GetLocation: React.FC<{}> = () => { rotation: state.rotation, center: [position.coords.longitude, position.coords.latitude], }); + setLocation([position.coords.longitude, position.coords.latitude]); }); }; diff --git a/src/components/map/Map.tsx b/src/components/map/Map.tsx index a7c6109..40e2b13 100644 --- a/src/components/map/Map.tsx +++ b/src/components/map/Map.tsx @@ -6,6 +6,9 @@ import { atomWithHash } from 'jotai-location'; import OlMap from 'ol/Map'; import View from 'ol/View'; import TileLayer from 'ol/layer/Tile'; +import VectorLayer from 'ol/layer/Vector'; +import VectorSource from 'ol/source/Vector'; +import Feature from 'ol/Feature'; import Attribution from 'ol/control/Attribution'; import Rotate from 'ol/control/Rotate'; import ScaleLine from 'ol/control/ScaleLine'; @@ -17,13 +20,17 @@ import { isEqual } from 'lodash'; import './Map.css'; import Collection from 'ol/Collection'; +import { Circle, Fill, Stroke, Style, Icon } from 'ol/style'; import GetLocation from '../get-location'; +import ShowLocation, { locationAtom } from '../show-location'; +import { Point } from 'ol/geom'; export interface MapProperties {} olUseGeographic(); const mapAtom = atom(null); +const sourceAtom = atom(null); export const stateAtom = atomWithHash('map', null); //atom( @@ -47,24 +54,69 @@ export const stateAtom = atomWithHash('map', null); export const Map: React.FC = (props: MapProperties) => { const [map, setMap] = useAtom(mapAtom); + const [source, setSource] = useAtom(sourceAtom); const [state, setState] = useAtom(stateAtom); + const [location] = useAtom(locationAtom); const target = useRef(null); const getLocation = useRef(null); + const showLocation = useRef(null); const previousState = useRef(null); if (state && map) { if (!isEqual(state, previousState.current)) { - console.log({ caller: 'Map / updateView', state }); + console.log({ caller: 'Map / updateView', state, map }); previousState.current = state; - map.getView().animate(state); + const view = map.getView(); + // view.beginInteraction(); + // const view = new View(state); + // map.setView(view); + // map.renderSync(); + // view.setCenter(state.center); + // view.setZoom(state.zoom); + // view.setRotation(state.rotation); + // view.resolveConstraints(); + // view.endInteraction(); + // map.setView(view); + // map.getView().animate(state); + // view.endInteraction(); + view.animate({ ...state, duration: 500 }); } - // const view = map.getView(); - // view.setCenter(state.center); - // view.setZoom(state.zoom); - // view.setRotation(state.rotation); - // map.renderSync(); + } + + if (source && location && showLocation.current) { + console.log({ caller: 'Map / updateLocation', location, source, map }); + source.clear(true); + const point = new Point(location); + const style = new Style({ + image: new Icon({ + // size: [20, 20], + imgSize: [24, 24], + declutterMode: 'declutter', + src: `data:image/svg+xml;utf8,${encodeURI( + showLocation.current.outerHTML + )}`, + }), + }); + const feature = new Feature({ + geometry: point, + // labelPoint: point, + // name: 'current location', + style: style, + }); + feature.setStyle(style); + source.addFeature(feature); +// source.changed(); + console.log({ + caller: 'Map / updateLocation', + location, + source, + map, + style, + feature, + showLocation: showLocation.current, + }); } useEffect(() => { @@ -93,6 +145,8 @@ export const Map: React.FC = (props: MapProperties) => { new ScaleLine({ bar: true }), new Control({ element: getLocation.current ?? undefined }), ]); + const newSource = new VectorSource(); + setSource(newSource); const olMap = new OlMap({ view: new View( state ?? { @@ -104,11 +158,12 @@ export const Map: React.FC = (props: MapProperties) => { new TileLayer({ source: new OSM(), }), + new VectorLayer({ source: newSource }), ], target: target.current ?? undefined, controls, }); - olMap.on(['change', 'moveend'], changeListener); + olMap.on(['moveend'], changeListener); setMap(olMap); }, []); @@ -117,6 +172,15 @@ export const Map: React.FC = (props: MapProperties) => {
+ + +
); diff --git a/src/components/show-location/ShowLocation.tsx b/src/components/show-location/ShowLocation.tsx new file mode 100644 index 0000000..87120a4 --- /dev/null +++ b/src/components/show-location/ShowLocation.tsx @@ -0,0 +1,29 @@ +import { atom, useAtom } from 'jotai'; +import react from 'react'; + +export interface ShowLocationProperties {} + +const initialLocation: number[] | null = null; +export const locationAtom = atom(initialLocation); + +export const ShowLocation: react.FC = ( + props: ShowLocationProperties +) => { + const [location] = useAtom(locationAtom); + console.log({ caller: 'ShowLocation', location }); + + return location !== null ? ( + + ) : null; +}; + +export default ShowLocation; diff --git a/src/components/show-location/index.ts b/src/components/show-location/index.ts new file mode 100644 index 0000000..d528e2e --- /dev/null +++ b/src/components/show-location/index.ts @@ -0,0 +1 @@ +export { default, locationAtom } from './ShowLocation';