Starting to implement avatars for locations (WIP).
This commit is contained in:
parent
6954c473ee
commit
d1da0a110d
|
@ -0,0 +1,49 @@
|
|||
import React from 'react';
|
||||
|
||||
import { useSelector } from 'react-redux';
|
||||
import { geoPoint, lat2tile, lon2tile, Point } from '../../lib/geo';
|
||||
|
||||
import { MapState } from '../../store/map';
|
||||
import { tileProviders } from './tile';
|
||||
|
||||
interface AvatarForLocationProps {
|
||||
location: geoPoint;
|
||||
zoom?: number;
|
||||
tileProvider?: string;
|
||||
size?: number;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
const AvatarForLocation: React.FC<AvatarForLocationProps> = (
|
||||
props: AvatarForLocationProps
|
||||
) => {
|
||||
const size = props.size ? props.size : 42;
|
||||
const zoom = props.zoom ? Math.round(props.zoom) : 16;
|
||||
const tileProvider = props.tileProvider ? props.tileProvider : 'osm';
|
||||
const location = props.location;
|
||||
const name = props.name ? props.name : '???';
|
||||
|
||||
const tilesLocation: Point = {
|
||||
x: lon2tile(location.lon, zoom),
|
||||
y: lat2tile(location.lat, zoom),
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<svg width={size} height={size}>
|
||||
<defs>
|
||||
<clipPath id='cut-off'>
|
||||
<circle cx={size / 2} cy={size / 2} r={size / 2} />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path='url(#cut-off)'>
|
||||
<image href={tileProviders[tileProvider].getTileUrl(zoom, Math.floor(tilesLocation.x), Math.floor(tilesLocation.y))} />
|
||||
<text x='2' y={size / 2 + 5}>
|
||||
{name}
|
||||
</text>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default AvatarForLocation;
|
|
@ -32,6 +32,8 @@ import { useSelector } from 'react-redux';
|
|||
import i18n from '../../i18n';
|
||||
import { geoPoint } from '../../lib/geo';
|
||||
import { MapState } from '../../store/map';
|
||||
import AvatarForLocation from './AvatarForLocation';
|
||||
import { round } from 'lodash';
|
||||
|
||||
const LocationInfo: React.FC<{}> = () => {
|
||||
const scope = useSelector((state: { map: MapState }) => state.map.scope);
|
||||
|
@ -134,17 +136,15 @@ const LocationInfo: React.FC<{}> = () => {
|
|||
const distDark = (255 * distance) / 3000;
|
||||
const distLight = 1 - distDark;
|
||||
return (
|
||||
<Avatar
|
||||
src={AvatarInitial.initialAvatar({
|
||||
size: 100,
|
||||
initials: Math.round(distance),
|
||||
initial_fg: `rgb(${distLight},0,${distLight}`,
|
||||
initial_bg: `rgb(0,${distDark}, 0`,
|
||||
initial_size: 33, // Defaults to height / 2
|
||||
initial_weight: 1000,
|
||||
initial_font_family: "'Lato', 'Lato-Regular', 'Helvetica Neue'",
|
||||
})}
|
||||
/>
|
||||
<Avatar>
|
||||
<AvatarForLocation
|
||||
location={{
|
||||
lon: props.feature.geometry.coordinates[0],
|
||||
lat: props.feature.geometry.coordinates[1],
|
||||
}}
|
||||
name={Math.round(distance).toString()}
|
||||
/>
|
||||
</Avatar>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,18 @@ import {
|
|||
import i18n from '../../i18n';
|
||||
import eventBus from '../../lib/pubsub';
|
||||
|
||||
export const getSTile = (lat: number, zoom: number) => {
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
return (40075016.686 * Math.cos((lat * Math.PI) / 180)) / 2 ** zoom;
|
||||
};
|
||||
|
||||
const Reticle: React.FC<{}> = () => {
|
||||
const windowState = useSelector(
|
||||
(state: { map: MapState }) => state.map.window
|
||||
|
@ -26,18 +38,7 @@ const Reticle: React.FC<{}> = () => {
|
|||
y: windowState.height / 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 sTile = getSTile(scope.center.lat, scope.zoom);
|
||||
|
||||
const radiusMeters = (sTile * radius) / 256;
|
||||
const radiusOrder = Math.floor(Math.log10(radiusMeters));
|
||||
|
|
Loading…
Reference in New Issue