我基于https://github.com/tuupola/php_google_maps中的Mercator数学原理创建了以下内容
关键函数是mercatorDegreeDeltas(latitude, longitude, width, height, zoom)
,它会返回指定纬度/经度中心点、地图尺寸和缩放级别(1-20)的{ latitudeDelta, longitudeDelta }
。
import React from 'react';
import { useWindowDimensions } from 'react-native';
import MapView from 'react-native-maps';
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
import { useHeaderHeight } from '@react-navigation/elements';
const MERCATOR_OFFSET = Math.pow(2, 28);
const MERCATOR_RADIUS = MERCATOR_OFFSET / Math.PI;
function mercatorLatitudeToY(latitude) {
return Math.round(
MERCATOR_OFFSET -
(
(
MERCATOR_RADIUS *
Math.log(
(1 + Math.sin(latitude * (Math.PI / 180))) /
(1 - Math.sin(latitude * (Math.PI / 180)))
)
) / 2
)
);
}
function mercatorLongitudeToX(longitude) {
return Math.round(
MERCATOR_OFFSET +
(
(
(MERCATOR_RADIUS * longitude) * Math.PI
) / 180
)
);
}
function mercatorXToLongitude(x) {
return (
(
(x - MERCATOR_OFFSET) / MERCATOR_RADIUS
) * 180
) / Math.PI;
}
function mercatorYToLatitude(y) {
return (
(
(
Math.PI / 2
) -
(2 * Math.atan(
Math.exp(
(
y - MERCATOR_OFFSET
) / MERCATOR_RADIUS
)
)
)
) * 180
) / Math.PI;
}
function mercatorAdjustLatitudeByOffsetAndZoom(latitude, offset, zoom) {
return mercatorYToLatitude(mercatorLatitudeToY(latitude) + (offset << (21 - zoom)));
}
function mercatorAdjustLongitudeByOffsetAndZoom(longitude, offset, zoom) {
return mercatorXToLongitude(mercatorLongitudeToX(longitude) + (offset << (21 - zoom)));
}
function mercatorDegreeDeltas(latitude, longitude, width, height, zoom) {
if (!zoom) {
zoom = 20;
}
const deltaX = width / 2;
const deltaY = height / 2;
const northLatitude = mercatorAdjustLatitudeByOffsetAndZoom(latitude, deltaY * -1, zoom);
const westLongitude = mercatorAdjustLongitudeByOffsetAndZoom(longitude, deltaX * -1, zoom);
const southLatitude = mercatorAdjustLatitudeByOffsetAndZoom(latitude, deltaY, zoom);
const eastLongitude = mercatorAdjustLongitudeByOffsetAndZoom(longitude, deltaY, zoom);
const latitudeDelta = Math.abs(northLatitude - southLatitude);
const longitudeDelta = Math.abs(eastLongitude - westLongitude);
return { latitudeDelta, longitudeDelta };
}
const CENTER_UNITED_STATES = {
latitude: 37.24435373025407,
longitude: -95.70234410503208,
};
export default function MapViewWrapper() {
const { width, height } = useWindowDimensions();
const tabBarHeight = useBottomTabBarHeight();
const headerHeight = useHeaderHeight();
const initialRegion = React.useRef(null);
const availableHeight = height - tabBarHeight - headerHeight;
if (!initialRegion.current) {
const { latitudeDelta, longitudeDelta } = mercatorDegreeDeltas(
CENTER_UNITED_STATES.latitude,
CENTER_UNITED_STATES.longitude,
width,
availableHeight,
4,
);
initialRegion.current = {
latitude: CENTER_UNITED_STATES.latitude,
longitude: CENTER_UNITED_STATES.longitude,
latitudeDelta: latitudeDelta,
longitudeDelta: longitudeDelta,
};
}
return (
<MapView
initialRegion={initialRegion.current}
style={{ width: width, height: availableHeight }}
/>
);
}
至少存在一个问题:如果你将缩放从4
更改为3
,它不会正确居中,但更大的缩放值可以正常工作。我现在不需要较低的缩放值,因此我没有进一步研究过数学(也许是某种溢出?)。