ShowLocation component.
This commit is contained in:
parent
1555c00fe8
commit
2fa6199979
|
@ -3,7 +3,5 @@
|
||||||
--ion-background-color: white;
|
--ion-background-color: white;
|
||||||
margin-left: calc(50% - 20px);
|
margin-left: calc(50% - 20px);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 6px
|
bottom: 6px;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,15 @@ import { IonButton, IonIcon } from '@ionic/react';
|
||||||
import { locateOutline } from 'ionicons/icons';
|
import { locateOutline } from 'ionicons/icons';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { stateAtom } from '../map';
|
import { stateAtom } from '../map';
|
||||||
|
import { locationAtom } from '../show-location';
|
||||||
|
|
||||||
// import { locationAtom } from '../map/CurrentLocation';
|
// import { locationAtom } from '../map/CurrentLocation';
|
||||||
|
|
||||||
const GetLocation: React.FC<{}> = () => {
|
const GetLocation: React.FC<{}> = () => {
|
||||||
const [state, setState] = useAtom(stateAtom);
|
const [state, setState] = useAtom(stateAtom);
|
||||||
|
|
||||||
|
const [, setLocation] = useAtom(locationAtom);
|
||||||
|
|
||||||
const onClickHandler = (event: any) => {
|
const onClickHandler = (event: any) => {
|
||||||
console.log('Click handler');
|
console.log('Click handler');
|
||||||
Geolocation.getCurrentPosition().then((position) => {
|
Geolocation.getCurrentPosition().then((position) => {
|
||||||
|
@ -22,6 +25,7 @@ const GetLocation: React.FC<{}> = () => {
|
||||||
rotation: state.rotation,
|
rotation: state.rotation,
|
||||||
center: [position.coords.longitude, position.coords.latitude],
|
center: [position.coords.longitude, position.coords.latitude],
|
||||||
});
|
});
|
||||||
|
setLocation([position.coords.longitude, position.coords.latitude]);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@ import { atomWithHash } from 'jotai-location';
|
||||||
import OlMap from 'ol/Map';
|
import OlMap from 'ol/Map';
|
||||||
import View from 'ol/View';
|
import View from 'ol/View';
|
||||||
import TileLayer from 'ol/layer/Tile';
|
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 Attribution from 'ol/control/Attribution';
|
||||||
import Rotate from 'ol/control/Rotate';
|
import Rotate from 'ol/control/Rotate';
|
||||||
import ScaleLine from 'ol/control/ScaleLine';
|
import ScaleLine from 'ol/control/ScaleLine';
|
||||||
|
@ -17,13 +20,17 @@ import { isEqual } from 'lodash';
|
||||||
|
|
||||||
import './Map.css';
|
import './Map.css';
|
||||||
import Collection from 'ol/Collection';
|
import Collection from 'ol/Collection';
|
||||||
|
import { Circle, Fill, Stroke, Style, Icon } from 'ol/style';
|
||||||
import GetLocation from '../get-location';
|
import GetLocation from '../get-location';
|
||||||
|
import ShowLocation, { locationAtom } from '../show-location';
|
||||||
|
import { Point } from 'ol/geom';
|
||||||
|
|
||||||
export interface MapProperties {}
|
export interface MapProperties {}
|
||||||
|
|
||||||
olUseGeographic();
|
olUseGeographic();
|
||||||
|
|
||||||
const mapAtom = atom<OlMap | null>(null);
|
const mapAtom = atom<OlMap | null>(null);
|
||||||
|
const sourceAtom = atom<VectorSource | null>(null);
|
||||||
|
|
||||||
export const stateAtom = atomWithHash<any>('map', null);
|
export const stateAtom = atomWithHash<any>('map', null);
|
||||||
//atom(
|
//atom(
|
||||||
|
@ -47,24 +54,69 @@ export const stateAtom = atomWithHash<any>('map', null);
|
||||||
|
|
||||||
export const Map: React.FC<MapProperties> = (props: MapProperties) => {
|
export const Map: React.FC<MapProperties> = (props: MapProperties) => {
|
||||||
const [map, setMap] = useAtom(mapAtom);
|
const [map, setMap] = useAtom(mapAtom);
|
||||||
|
const [source, setSource] = useAtom(sourceAtom);
|
||||||
const [state, setState] = useAtom(stateAtom);
|
const [state, setState] = useAtom(stateAtom);
|
||||||
|
const [location] = useAtom(locationAtom);
|
||||||
|
|
||||||
const target = useRef<HTMLDivElement>(null);
|
const target = useRef<HTMLDivElement>(null);
|
||||||
const getLocation = useRef<HTMLDivElement>(null);
|
const getLocation = useRef<HTMLDivElement>(null);
|
||||||
|
const showLocation = useRef<SVGSVGElement>(null);
|
||||||
|
|
||||||
const previousState = useRef<any>(null);
|
const previousState = useRef<any>(null);
|
||||||
|
|
||||||
if (state && map) {
|
if (state && map) {
|
||||||
if (!isEqual(state, previousState.current)) {
|
if (!isEqual(state, previousState.current)) {
|
||||||
console.log({ caller: 'Map / updateView', state });
|
console.log({ caller: 'Map / updateView', state, map });
|
||||||
previousState.current = state;
|
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);
|
if (source && location && showLocation.current) {
|
||||||
// view.setRotation(state.rotation);
|
console.log({ caller: 'Map / updateLocation', location, source, map });
|
||||||
// map.renderSync();
|
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(() => {
|
useEffect(() => {
|
||||||
|
@ -93,6 +145,8 @@ export const Map: React.FC<MapProperties> = (props: MapProperties) => {
|
||||||
new ScaleLine({ bar: true }),
|
new ScaleLine({ bar: true }),
|
||||||
new Control({ element: getLocation.current ?? undefined }),
|
new Control({ element: getLocation.current ?? undefined }),
|
||||||
]);
|
]);
|
||||||
|
const newSource = new VectorSource();
|
||||||
|
setSource(newSource);
|
||||||
const olMap = new OlMap({
|
const olMap = new OlMap({
|
||||||
view: new View(
|
view: new View(
|
||||||
state ?? {
|
state ?? {
|
||||||
|
@ -104,11 +158,12 @@ export const Map: React.FC<MapProperties> = (props: MapProperties) => {
|
||||||
new TileLayer({
|
new TileLayer({
|
||||||
source: new OSM(),
|
source: new OSM(),
|
||||||
}),
|
}),
|
||||||
|
new VectorLayer({ source: newSource }),
|
||||||
],
|
],
|
||||||
target: target.current ?? undefined,
|
target: target.current ?? undefined,
|
||||||
controls,
|
controls,
|
||||||
});
|
});
|
||||||
olMap.on(['change', 'moveend'], changeListener);
|
olMap.on(['moveend'], changeListener);
|
||||||
setMap(olMap);
|
setMap(olMap);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -117,6 +172,15 @@ export const Map: React.FC<MapProperties> = (props: MapProperties) => {
|
||||||
<div ref={getLocation}>
|
<div ref={getLocation}>
|
||||||
<GetLocation />
|
<GetLocation />
|
||||||
</div>
|
</div>
|
||||||
|
<svg
|
||||||
|
ref={showLocation}
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
version='1.1'
|
||||||
|
>
|
||||||
|
<ShowLocation />
|
||||||
|
</svg>
|
||||||
<div ref={target} className='ol-map'></div>
|
<div ref={target} className='ol-map'></div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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<number[] | null>(initialLocation);
|
||||||
|
|
||||||
|
export const ShowLocation: react.FC<ShowLocationProperties> = (
|
||||||
|
props: ShowLocationProperties
|
||||||
|
) => {
|
||||||
|
const [location] = useAtom(locationAtom);
|
||||||
|
console.log({ caller: 'ShowLocation', location });
|
||||||
|
|
||||||
|
return location !== null ? (
|
||||||
|
<circle
|
||||||
|
cx={8}
|
||||||
|
cy={8}
|
||||||
|
r={8}
|
||||||
|
fill='blue'
|
||||||
|
opacity='90%'
|
||||||
|
stroke='white'
|
||||||
|
strokeWidth={3}
|
||||||
|
strokeOpacity='100%'
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ShowLocation;
|
|
@ -0,0 +1 @@
|
||||||
|
export { default, locationAtom } from './ShowLocation';
|
Loading…
Reference in New Issue