mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 11:06:40 +07:00
added editable route
This commit is contained in:
parent
5664291c92
commit
fca52df9f5
17 changed files with 282 additions and 11 deletions
|
@ -19,6 +19,9 @@ import { IStickerPack } from "$constants/stickers";
|
|||
import { IDialogs } from "$constants/dialogs";
|
||||
import { IModes } from "$constants/modes";
|
||||
|
||||
import { Map } from "$containers/map/Map"
|
||||
import { TileLayer } from '$containers/map/TileLayer';
|
||||
|
||||
type Props = {
|
||||
sticker: string,
|
||||
renderer_active: boolean,
|
||||
|
@ -49,6 +52,8 @@ const Component = (props: Props) => (
|
|||
setDialogActive={props.setDialogActive}
|
||||
/>
|
||||
|
||||
<Map />
|
||||
|
||||
{ props.renderer_active &&
|
||||
<Renderer onClick={props.hideRenderer} />
|
||||
}
|
||||
|
|
46
src/containers/map/Map/index.tsx
Normal file
46
src/containers/map/Map/index.tsx
Normal file
|
@ -0,0 +1,46 @@
|
|||
import { Map as MapInterface, map } from "leaflet";
|
||||
import * as React from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { MapContext } from "$utils/context.ts";
|
||||
import { TileLayer } from "$containers/map/TileLayer";
|
||||
import { Route } from "$containers/map/Route";
|
||||
import { selectMapProvider, selectMapRoute } from "$redux/map/selectors";
|
||||
import { connect } from "react-redux";
|
||||
import * as MAP_ACTIONS from "$redux/map/actions";
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
provider: selectMapProvider(state),
|
||||
route: selectMapRoute(state)
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
mapSetRoute: MAP_ACTIONS.mapSetRoute
|
||||
};
|
||||
|
||||
type IProps = React.HTMLAttributes<HTMLDivElement> &
|
||||
ReturnType<typeof mapStateToProps> &
|
||||
typeof mapDispatchToProps & {};
|
||||
|
||||
const MapUnconnected: React.FC<IProps> = ({ provider, route, mapSetRoute }) => {
|
||||
const ref = React.useRef(null);
|
||||
const [maps, setMaps] = React.useState<MapInterface>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!ref.current) return;
|
||||
|
||||
setMaps(map(ref.current).setView([55.0153275, 82.9071235], 13));
|
||||
}, [ref]);
|
||||
|
||||
return createPortal(
|
||||
<div ref={ref}>
|
||||
<MapContext.Provider value={maps}>
|
||||
<TileLayer provider={provider} />
|
||||
<Route route={route} mapSetRoute={mapSetRoute} is_editing />
|
||||
</MapContext.Provider>
|
||||
</div>,
|
||||
document.getElementById("canvas")
|
||||
);
|
||||
};
|
||||
|
||||
const Map = connect(mapStateToProps, mapDispatchToProps)(MapUnconnected);
|
||||
export { Map };
|
80
src/containers/map/Route/index.tsx
Normal file
80
src/containers/map/Route/index.tsx
Normal file
|
@ -0,0 +1,80 @@
|
|||
import React, {
|
||||
FC,
|
||||
useEffect,
|
||||
memo,
|
||||
useContext,
|
||||
useState,
|
||||
useCallback
|
||||
} from "react";
|
||||
import { IMapRoute, ILatLng } from "../../../redux/map/types";
|
||||
import { MapContext } from "$utils/context";
|
||||
import { InteractivePoly } from "$modules/InteractivePoly";
|
||||
import { isMobile } from "$utils/window";
|
||||
import { LatLng } from "leaflet";
|
||||
|
||||
interface IProps {
|
||||
route: IMapRoute;
|
||||
is_editing: boolean;
|
||||
mapSetRoute: (latlngs: ILatLng[]) => void;
|
||||
}
|
||||
|
||||
const Route: FC<IProps> = memo(({ route, is_editing, mapSetRoute }) => {
|
||||
const [layer, setLayer] = useState<InteractivePoly>(null);
|
||||
const map = useContext(MapContext);
|
||||
|
||||
const onRouteChanged = useCallback(
|
||||
({ latlngs }) => {
|
||||
// mapSetRoute(latlngs)
|
||||
},
|
||||
[mapSetRoute]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!layer) return;
|
||||
|
||||
layer.on("latlngschange", onRouteChanged);
|
||||
|
||||
return () => layer.off("latlngschange", onRouteChanged);
|
||||
}, [layer, onRouteChanged]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!map) return;
|
||||
|
||||
setLayer(
|
||||
new InteractivePoly([], {
|
||||
color: "url(#activePathGradient)",
|
||||
weight: 6,
|
||||
maxMarkers: isMobile() ? 20 : 100,
|
||||
smoothFactor: 3,
|
||||
updateself: false,
|
||||
})
|
||||
.addTo(map)
|
||||
.on("distancechange", console.log)
|
||||
.on("allvertexhide", console.log)
|
||||
.on("allvertexshow", console.log)
|
||||
// .on("latlngschange", console.log)
|
||||
);
|
||||
}, [map]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!layer) return;
|
||||
|
||||
const points = (route && route.length > 0 && route) || [];
|
||||
|
||||
layer.setPoints(points as LatLng[]); // TODO: refactor this
|
||||
}, [route, layer]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!layer) return;
|
||||
|
||||
if (is_editing) {
|
||||
layer.editor.enable();
|
||||
} else {
|
||||
layer.editor.disable();
|
||||
}
|
||||
}, [is_editing, layer]);
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
export { Route };
|
40
src/containers/map/TileLayer/index.tsx
Normal file
40
src/containers/map/TileLayer/index.tsx
Normal file
|
@ -0,0 +1,40 @@
|
|||
import * as React from "react";
|
||||
import { MapContext, TileContext } from "../../../utils/context";
|
||||
import { TileLayer as TileLayerInterface, tileLayer } from "leaflet";
|
||||
import { DEFAULT_PROVIDER, PROVIDERS } from "$constants/providers";
|
||||
import { IMapReducer } from "$redux/map";
|
||||
|
||||
type IProps = React.HTMLAttributes<HTMLDivElement> & {
|
||||
provider: IMapReducer['provider'],
|
||||
};
|
||||
|
||||
const TileLayer: React.FC<IProps> = ({ children, provider }) => {
|
||||
const [layer, setLayer] = React.useState<TileLayerInterface>(null);
|
||||
const map = React.useContext(MapContext);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!map) return;
|
||||
|
||||
setLayer(
|
||||
tileLayer(PROVIDERS[DEFAULT_PROVIDER].url, {
|
||||
attribution: "Независимое Велосообщество",
|
||||
maxNativeZoom: 18,
|
||||
maxZoom: 18
|
||||
}).addTo(map)
|
||||
);
|
||||
}, [map]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!layer || !provider) return;
|
||||
|
||||
const { url } =
|
||||
(provider && PROVIDERS[provider] && PROVIDERS[provider]) ||
|
||||
PROVIDERS[DEFAULT_PROVIDER];
|
||||
|
||||
layer.setUrl(url);
|
||||
}, [layer, provider]);
|
||||
|
||||
return <TileContext.Provider value={layer}>{children}</TileContext.Provider>;
|
||||
};
|
||||
|
||||
export { TileLayer };
|
Loading…
Add table
Add a link
Reference in a new issue