Correct algorithm for centering tiles.
This commit is contained in:
parent
9e8aec244e
commit
4e26d94843
|
@ -1,55 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { PigeonProps, Point } from 'pigeon-maps';
|
|
||||||
import GPX from 'gpx-parser-builder';
|
|
||||||
import { round } from 'lodash';
|
|
||||||
|
|
||||||
const GPXFigure: React.FC<PigeonProps> = (props: PigeonProps) => {
|
|
||||||
const gpx = GPX.parse(localStorage.getItem('gpx'));
|
|
||||||
|
|
||||||
const dirtyLatLngToPixel = (point: Point) => {
|
|
||||||
if (props.mapState === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const latRange = props.mapState.bounds.ne[0] - props.mapState.bounds.sw[0];
|
|
||||||
const lonRange = props.mapState.bounds.ne[1] - props.mapState.bounds.sw[1];
|
|
||||||
const x = round(
|
|
||||||
((point[0] - props.mapState.bounds.sw[0]) * props.mapState.width) /
|
|
||||||
lonRange
|
|
||||||
);
|
|
||||||
const y = round(
|
|
||||||
((point[1] - props.mapState.bounds.sw[1]) * props.mapState.height) /
|
|
||||||
latRange
|
|
||||||
);
|
|
||||||
return [x, props.mapState.height - y];
|
|
||||||
};
|
|
||||||
|
|
||||||
const trkToPolyline = (gpxData: any) => {
|
|
||||||
const latLongs: string[] = gpxData.trk[0].trkseg[0].trkpt.map(
|
|
||||||
(trkpt: any) => {
|
|
||||||
if (props.latLngToPixel === undefined) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
const point: Point = [trkpt.$.lat, trkpt.$.lon];
|
|
||||||
const pixelPoint = dirtyLatLngToPixel(point);
|
|
||||||
if (pixelPoint === undefined) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return pixelPoint.join(' ');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
console.log('latLongs: ' + latLongs);
|
|
||||||
return latLongs.join(' ');
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<polyline
|
|
||||||
points={trkToPolyline(gpx)}
|
|
||||||
stroke='black'
|
|
||||||
strokeWidth='3'
|
|
||||||
fill='none'
|
|
||||||
></polyline>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default GPXFigure;
|
|
|
@ -1,27 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { Overlay, PigeonProps } from 'pigeon-maps';
|
|
||||||
|
|
||||||
import GPXFigure from './gpx-figure';
|
|
||||||
|
|
||||||
const GPXOverlay: React.FC<PigeonProps> = (props: PigeonProps) => {
|
|
||||||
return (
|
|
||||||
<Overlay >
|
|
||||||
{props.mapState && props.mapState.width > 0 && (
|
|
||||||
<svg
|
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
|
||||||
viewBox={'0 0 ' + props.mapState.width + ' ' + props.mapState.height}
|
|
||||||
width={props.mapState.width}
|
|
||||||
height={props.mapState.height}
|
|
||||||
>
|
|
||||||
<GPXFigure
|
|
||||||
mapState={props.mapState}
|
|
||||||
latLngToPixel={props.latLngToPixel}
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
</Overlay>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default GPXOverlay;
|
|
|
@ -1,7 +1,6 @@
|
||||||
import _, { round } from 'lodash';
|
import _, { round } from 'lodash';
|
||||||
import react, { useState, useEffect } from 'react';
|
import react, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
import GPXOverlay from './gpx-overlay';
|
|
||||||
import Tile from './tile';
|
import Tile from './tile';
|
||||||
|
|
||||||
import '../theme/map.css';
|
import '../theme/map.css';
|
||||||
|
@ -26,11 +25,11 @@ const lat2tile = (lat: number, zoom: number) => {
|
||||||
Math.pow(2, zoom);
|
Math.pow(2, zoom);
|
||||||
const floor = Math.floor(real);
|
const floor = Math.floor(real);
|
||||||
return [floor, real - floor];
|
return [floor, real - floor];
|
||||||
};
|
};
|
||||||
|
|
||||||
const Map: react.FC = () => {
|
const Map: react.FC = () => {
|
||||||
const initialCenter: [number, number] = [43.57029965, 3.94242897];
|
const initialCenter: [number, number] = [43.57029965, 3.94242897];
|
||||||
const initialZoom: number = 15;
|
const initialZoom: number = 17;
|
||||||
const [center, setCenter] = useState(initialCenter);
|
const [center, setCenter] = useState(initialCenter);
|
||||||
const [zoom, setZoom] = useState(initialZoom);
|
const [zoom, setZoom] = useState(initialZoom);
|
||||||
|
|
||||||
|
@ -51,12 +50,16 @@ const Map: react.FC = () => {
|
||||||
|
|
||||||
const nbTilesY = _.ceil(dimensions.height / tileSize) + 2;
|
const nbTilesY = _.ceil(dimensions.height / tileSize) + 2;
|
||||||
const nbTilesX = _.ceil(dimensions.width / tileSize) + 2;
|
const nbTilesX = _.ceil(dimensions.width / tileSize) + 2;
|
||||||
const [tileCenterY, deltaY] = lat2tile(center[0], zoom);
|
const [tileCenterY, reminderY] = lat2tile(center[0], zoom);
|
||||||
const [tileCenterX, deltaX] = lon2tile(center[1], zoom);
|
const [tileCenterX, reminderX] = lon2tile(center[1], zoom);
|
||||||
const firstTileY = tileCenterY - _.ceil(nbTilesY / 2);
|
const firstTileY = tileCenterY - _.ceil(nbTilesY / 2);
|
||||||
const firstTileX = tileCenterX - _.ceil(nbTilesX / 2);
|
const firstTileX = tileCenterX - _.ceil(nbTilesX / 2);
|
||||||
|
const locationY = ((tileCenterY + reminderY - firstTileY ) * tileSize) ;
|
||||||
|
const locationX = ((tileCenterX + reminderX - firstTileX ) * tileSize) ;
|
||||||
|
const targetLocationY = dimensions.height / 2;
|
||||||
|
const targetLocationX = dimensions.width / 2;
|
||||||
|
const deltaY = - targetLocationY + locationY;
|
||||||
|
const deltaX = - targetLocationX + locationX;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='tiles'>
|
<div className='tiles'>
|
||||||
|
@ -69,8 +72,8 @@ const Map: react.FC = () => {
|
||||||
ix={ix}
|
ix={ix}
|
||||||
x={firstTileX + ix}
|
x={firstTileX + ix}
|
||||||
y={firstTileY + iy}
|
y={firstTileY + iy}
|
||||||
deltaX ={deltaX}
|
deltaX={deltaX}
|
||||||
deltaY ={deltaY}
|
deltaY={deltaY}
|
||||||
zoom={zoom}
|
zoom={zoom}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -26,12 +26,18 @@ const Tile: React.FC<{
|
||||||
height: tileSize + 'px',
|
height: tileSize + 'px',
|
||||||
transform:
|
transform:
|
||||||
'translate3d(' +
|
'translate3d(' +
|
||||||
(props.ix - props.deltaX -1) * tileSize +
|
(props.ix * tileSize - props.deltaX) +
|
||||||
'px, ' +
|
'px, ' +
|
||||||
(props.iy - props.deltaY -1) * tileSize +
|
(props.iy * tileSize - props.deltaY) +
|
||||||
'px, 0px)',
|
'px, 0px)',
|
||||||
};
|
};
|
||||||
return <img src={tileProvider(props.zoom, props.x, props.y)} style={style} />;
|
return (
|
||||||
|
<img
|
||||||
|
src={tileProvider(props.zoom, props.x, props.y)}
|
||||||
|
style={style}
|
||||||
|
alt=''
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Tile;
|
export default Tile;
|
||||||
|
|
Loading…
Reference in New Issue