Implementing a SVG layout (aka whiteboard).
This commit is contained in:
parent
92700c3964
commit
7808b7db7e
|
@ -7,6 +7,7 @@ import Layer from '../slippy/layer';
|
|||
import Slippy from '../slippy/slippy';
|
||||
import TiledMap from './tiled-map';
|
||||
import GetLocation from './get-location';
|
||||
import Whiteboard from './whiteboard';
|
||||
|
||||
const Map: react.FC<{}> = (props: {}) => {
|
||||
const dispatch = useDispatch();
|
||||
|
@ -28,6 +29,7 @@ const Map: react.FC<{}> = (props: {}) => {
|
|||
<Fragment>
|
||||
<Slippy>
|
||||
<GetLocation />
|
||||
<Whiteboard />
|
||||
</Slippy>
|
||||
<Layer>
|
||||
<TiledMap />
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { MapState } from '../../store/map';
|
||||
|
||||
interface WhiteboardProps {
|
||||
children?: any;
|
||||
}
|
||||
|
||||
const Whiteboard: React.FC<WhiteboardProps> = (props: WhiteboardProps) => {
|
||||
const whiteBoardState = useSelector(
|
||||
(state: { map: MapState }) => state.map.whiteboard
|
||||
);
|
||||
|
||||
return (
|
||||
<svg width={window.innerWidth} height={window.innerHeight}>
|
||||
<g
|
||||
transform={`scale(${whiteBoardState.scale}) translate(${whiteBoardState.translation.x},${whiteBoardState.translation.y})`}
|
||||
>
|
||||
<circle
|
||||
cx='0.7154276391666667'
|
||||
cy='0.6137091783430285'
|
||||
r={10 / whiteBoardState.scale}
|
||||
fill='green'
|
||||
vector-effect='non-scaling-size'
|
||||
></circle>
|
||||
{props.children}
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default Whiteboard;
|
|
@ -4,6 +4,7 @@ import { MapState } from '../../store/map';
|
|||
|
||||
import '../../theme/layer.css';
|
||||
|
||||
|
||||
const Layer: react.FC<{
|
||||
children?: JSX.Element;
|
||||
}> = (props: { children?: JSX.Element }) => {
|
||||
|
|
|
@ -17,9 +17,9 @@ export interface MapScope {
|
|||
center: geoPoint;
|
||||
zoom: number;
|
||||
}
|
||||
const initialMapScope: MapScope = {
|
||||
var initialMapScope: MapScope = {
|
||||
center: { lat: -37.8403508, lon: 77.5539501 },
|
||||
zoom: 13,
|
||||
zoom: 4,
|
||||
};
|
||||
|
||||
// Derived properties
|
||||
|
@ -37,11 +37,18 @@ export interface SlippyState {
|
|||
translation: Point;
|
||||
}
|
||||
|
||||
// Properties needed to render the SVG whiteboard
|
||||
export interface WhiteboardState {
|
||||
scale: number;
|
||||
translation: Point;
|
||||
}
|
||||
|
||||
// Global state
|
||||
export interface MapState {
|
||||
scope: MapScope;
|
||||
tiles: TilesDescription;
|
||||
slippy: SlippyState;
|
||||
whiteboard: WhiteboardState;
|
||||
}
|
||||
/*
|
||||
|
||||
|
@ -87,6 +94,30 @@ export var initialMapState: MapState = {
|
|||
},
|
||||
zoom: 0,
|
||||
},
|
||||
whiteboard: {
|
||||
scale: 0,
|
||||
translation: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const evaluateWhiteboardViewBox = (
|
||||
state: MapState,
|
||||
visibleTileSize: number
|
||||
) => {
|
||||
// Update the whiteboard SVG viewBox
|
||||
|
||||
const scaleFactor = 2 ** state.scope.zoom;
|
||||
|
||||
state.whiteboard.scale = scaleFactor * tileSize;
|
||||
state.whiteboard.translation.x =
|
||||
(-state.tiles.first.x * visibleTileSize + state.slippy.translation.x) /
|
||||
state.whiteboard.scale;
|
||||
state.whiteboard.translation.y =
|
||||
(-state.tiles.first.y * visibleTileSize + state.slippy.translation.y) /
|
||||
state.whiteboard.scale;
|
||||
};
|
||||
|
||||
export const evaluateStateFromScope = (state: MapState) => {
|
||||
|
@ -122,6 +153,8 @@ export const evaluateStateFromScope = (state: MapState) => {
|
|||
tilesCenterTargetLocation.x - tilesCenterActualLocation.x;
|
||||
state.slippy.translation.y =
|
||||
tilesCenterTargetLocation.y - tilesCenterActualLocation.y;
|
||||
|
||||
evaluateWhiteboardViewBox(state, visibleTileSize);
|
||||
};
|
||||
|
||||
evaluateStateFromScope(initialMapState);
|
||||
|
@ -146,7 +179,8 @@ export const reevaluateState = (state: MapState) => {
|
|||
|
||||
state.scope.zoom = state.tiles.zoom + Math.log2(state.slippy.scale);
|
||||
|
||||
// TODO: zoom level
|
||||
// Check if the state must be reevaluated
|
||||
|
||||
if (
|
||||
-state.slippy.translation.x < visibleTileSize ||
|
||||
-state.slippy.translation.y < visibleTileSize ||
|
||||
|
@ -158,6 +192,8 @@ export const reevaluateState = (state: MapState) => {
|
|||
state.slippy.scale < Math.SQRT1_2
|
||||
) {
|
||||
evaluateStateFromScope(state);
|
||||
} else {
|
||||
evaluateWhiteboardViewBox(state, visibleTileSize);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue