Still playing with the reticle...
This commit is contained in:
parent
77f5ab3996
commit
27305c4b21
|
@ -1,26 +1,78 @@
|
|||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Point } from '../../lib/geo';
|
||||
import { MapState } from '../../store/map';
|
||||
import '../../theme/map.css';
|
||||
|
||||
const Reticle: React.FC<{}> = () => {
|
||||
|
||||
const windowState = useSelector(
|
||||
(state: { map: MapState }) => state.map.window
|
||||
);
|
||||
const scope = useSelector((state: { map: MapState }) => state.map.scope);
|
||||
const radius = Math.min(windowState.width, windowState.height) / 4;
|
||||
const center: Point = {
|
||||
x: windowState.width / 2,
|
||||
y: windowState.height / 2,
|
||||
};
|
||||
|
||||
const center: Point = { x: windowState.width / 2, y: windowState.height / 2 };
|
||||
const radius = Math.min(windowState.width, windowState.height) / 6;
|
||||
/**
|
||||
* The horizontal distance represented by each square tile, measured along the parallel at a given latitude, is given by:
|
||||
* Stile = C ∙ cos(latitude) / 2 zoomlevel
|
||||
* As tiles are 256-pixels wide, the horizontal distance represented by one pixel is:
|
||||
* Spixel = Stile / 256 = C ∙ cos(latitude) / 2 (zoomlevel + 8)
|
||||
* where C means the equatorial circumference of the Earth (40 075 016.686 m ≈ 2π ∙ 6 378 137.000 m for the reference geoid used by OpenStreetMap).
|
||||
* see https://wiki.openstreetmap.org/wiki/Zoom_levels
|
||||
*/
|
||||
|
||||
const sTile =
|
||||
(40075016.686 * Math.cos((scope.center.lat * Math.PI) / 180)) /
|
||||
2 ** scope.zoom;
|
||||
|
||||
const radiusMeters = (sTile * radius) / 256;
|
||||
const radiusOrder = Math.floor(Math.log10(radiusMeters));
|
||||
const radiusRoughUnit = radiusMeters / 10 ** radiusOrder;
|
||||
var radiusBaseUnit, radiusBaseSubUnit;
|
||||
if (radiusRoughUnit <= 2) {
|
||||
radiusBaseUnit = 1;
|
||||
radiusBaseSubUnit = 0.2;
|
||||
} else if (radiusRoughUnit <= 5) {
|
||||
radiusBaseUnit = 2;
|
||||
radiusBaseSubUnit = 0.5;
|
||||
} else {
|
||||
radiusBaseUnit = 5;
|
||||
radiusBaseSubUnit = 1;
|
||||
}
|
||||
|
||||
const nbSubUnits = Math.floor(
|
||||
radiusMeters / (radiusBaseSubUnit * 10 ** radiusOrder)
|
||||
);
|
||||
const nbUnits = Math.floor(
|
||||
radiusMeters / (radiusBaseUnit * 10 ** radiusOrder)
|
||||
);
|
||||
|
||||
const radiusUnit = radiusOrder < 3 ? 'm' : 'km';
|
||||
const radiusUnitValue =
|
||||
radiusOrder < 3
|
||||
? radiusBaseUnit * 10 ** radiusOrder
|
||||
: radiusBaseUnit * 10 ** (radiusOrder - 3);
|
||||
|
||||
const subUnitPxStep = ((radiusBaseSubUnit * 10 ** radiusOrder) / sTile) * 256;
|
||||
const unitPxStep = ((radiusBaseUnit * 10 ** radiusOrder) / sTile) * 256;
|
||||
|
||||
console.log(
|
||||
`radiusMeters: ${radiusMeters}, radiusOrder: ${radiusOrder}, radiusUnit: ${radiusBaseUnit}, radiusSubUnit: ${radiusBaseSubUnit}, nbSubUnits: ${nbSubUnits}`
|
||||
);
|
||||
|
||||
return (
|
||||
<g>
|
||||
<g className='reticle'>
|
||||
<circle
|
||||
cx={center.x}
|
||||
cy={center.y}
|
||||
r={radius}
|
||||
fill='transparent'
|
||||
stroke='black'
|
||||
strokeWidth={2}
|
||||
strokeWidth={1}
|
||||
/>
|
||||
<path
|
||||
d={`M ${center.x - radius},${center.y}
|
||||
|
@ -31,9 +83,39 @@ const Reticle: React.FC<{}> = () => {
|
|||
v ${radius - 3}
|
||||
m 0,${6}
|
||||
v ${radius - 3}`}
|
||||
strokeWidth={1}
|
||||
stroke='red'
|
||||
strokeWidth={0.5}
|
||||
/>
|
||||
<g id='reticle-east'>
|
||||
<path stroke='red' className='reticle'
|
||||
strokeWidth={0.5}
|
||||
d={_.range(1, nbSubUnits + 1)
|
||||
.map(
|
||||
(i) => `M ${center.x + i * subUnitPxStep},${center.y - 10} v 20`
|
||||
)
|
||||
.join(' ')}
|
||||
/>
|
||||
<path stroke='red' className='reticle'
|
||||
d={_.range(1, nbUnits + 1)
|
||||
.map((i) => `M ${center.x + i * unitPxStep},${center.y - 20} v 40`)
|
||||
.join(' ')}
|
||||
strokeWidth={0.5}
|
||||
/>
|
||||
</g>
|
||||
<use stroke='red' className='reticle'
|
||||
href='#reticle-east'
|
||||
transform={`rotate(90, ${center.x}, ${center.y})`}
|
||||
/>
|
||||
<use className='reticle'
|
||||
href='#reticle-east'
|
||||
transform={`rotate(180, ${center.x}, ${center.y})`}
|
||||
/>
|
||||
<use className='reticle'
|
||||
href='#reticle-east'
|
||||
transform={`rotate(-90, ${center.x}, ${center.y})`}
|
||||
/>
|
||||
<text x={center.x + unitPxStep - 15} y={center.y - 20}>
|
||||
{`${radiusUnitValue} ${radiusUnit}`}
|
||||
</text>
|
||||
</g>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -43,6 +43,17 @@ path.current {
|
|||
stroke: rgba(2, 71, 20, 0.8);
|
||||
}
|
||||
|
||||
.reticle path,
|
||||
path.reticle,
|
||||
use.reticle,
|
||||
.reticle use {
|
||||
stroke: red;
|
||||
}
|
||||
|
||||
.reticle text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
ion-modal {
|
||||
--height: 50%;
|
||||
--border-radius: 16px;
|
||||
|
@ -60,14 +71,13 @@ ion-modal.full-height {
|
|||
} */
|
||||
|
||||
ion-modal ion-toolbar {
|
||||
--background: rgba(14,116,144, .7);
|
||||
--background: rgba(14, 116, 144, 0.7);
|
||||
--color: white;
|
||||
}
|
||||
|
||||
ion-modal.full-height ion-toolbar {
|
||||
--background: rgba(14,116,144, 1);
|
||||
}
|
||||
|
||||
--background: rgba(14, 116, 144, 1);
|
||||
}
|
||||
|
||||
ion-modal ion-toolbar.secondary {
|
||||
--background: inherit;
|
||||
|
@ -75,10 +85,9 @@ ion-modal ion-toolbar.secondary {
|
|||
}
|
||||
|
||||
ion-modal ion-content {
|
||||
background-color: rgba(255,255,255,.7)
|
||||
;
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue