我正在与您的图书馆合作项目,这就是我得到的
import React, { useState, useRef, useEffect } from "react";
import { Spring, config, animated } from "react-spring";
import ReactDOM from "react-dom";
import {
ComposableMap,
Geographies,
Geography,
ZoomableGroup,
Line,
Point,
Marker
} from "react-simple-maps";
const geoUrl =
"https://raw.githubusercontent.com/zcreativelabs/react-simple-maps/master/topojson-maps/world-110m.json";
const MAX_ZOOM = 8;
const MIN_ZOOM = 1;
const calcZoom = (box, paddingPerc, width, height) => {
const minXY = box[0];
const maxXY = box[1];
console.log(box);
// find size of map area defined
let zoomWidth = Math.abs(minXY[0] - maxXY[0]);
let zoomHeight = Math.abs(minXY[1] - maxXY[1]);
// increase map area to include padding
zoomWidth = zoomWidth * (1 + paddingPerc / 100);
zoomHeight = zoomHeight * (1 + paddingPerc / 100);
// find scale required for area to fill svg
const maxXscale = width / zoomWidth;
const maxYscale = height / zoomHeight;
const zoomScale = Math.min(maxXscale, maxYscale);
// handle some edge cases
// limit to max zoom (handles tiny countries)
// zoomScale = Math.min(zoomScale, MAX_ZOOM);
// // limit to min zoom (handles large countries and countries that span the date line)
// zoomScale = Math.max(zoomScale, MIN_ZOOM);
return zoomScale;
};
const AnimatedZoomableGroup = animated((props) => {
return (
<ZoomableGroup center={[props.lon, props.lat]} {...props}>
{props.children}
</ZoomableGroup>
);
});
export const MapWidget = ({ from, to, width, height }) => {
const [lat, setLat] = useState(0);
const [lon, setLon] = useState(0);
const [zoom, setZoom] = useState(1);
useEffect(() => {
if (
from[0] !== null &&
to[0] !== null &&
from[1] !== null &&
to[1] !== null
) {
// [lon, lat]
console.log(from, to);
// const xMid = (from[0] + to[0]) / 2;
const xMid = (to[0] - from[0]) / 2 + from[0];
const yMid = (to[1] - from[1]) / 2 + from[1];
// const yMid = (from[1] + to[1]) / 2;
const minLon = Math.min(from[0], to[0]);
const maxLon = Math.max(from[0], to[0]);
const minLat = Math.min(from[1], to[1]);
const maxLat = Math.max(from[1], to[1]);
const bbox = [
[minLon, maxLon],
[minLat, maxLat]
];
// setCenter(centroid);
setLat(yMid);
setLon(xMid);
setZoom(calcZoom(bbox, 30, width, height));
}
}, [from, to]);
return (
<div style={{ width, height }}>
<ComposableMap>
<Spring
from={{ animatedZoom: MIN_ZOOM, lat: 0, lon: 0 }}
to={{ animatedZoom: zoom, lat: lat, lon: lon }}
config={{ ...config.slow }}
>
{({ animatedZoom, lat, lon }) => (
<AnimatedZoomableGroup
maxZoom={MAX_ZOOM}
minZoom={MIN_ZOOM}
zoom={animatedZoom}
lat={lat}
lon={lon}
>
<Geographies
geography={geoUrl}
fill="#D6D6DA"
stroke="#FFFFFF"
strokeWidth={0.5}
>
{({ geographies }) =>
geographies.map((geo) => (
<Geography key={geo.rsmKey} geography={geo} />
))
}
</Geographies>
{from[0] && to[0] && (
<Line
from={from}
to={to}
stroke="#FF5533"
strokeWidth={6 / zoom}
strokeLinecap="round"
/>
)}
{from && from[0] !== null && from[1] && (
<Marker coordinates={from}>
<circle r={10 / zoom} fill="#F00" />
</Marker>
)}
{to && to[0] !== null && to[1] && (
<Marker coordinates={to}>
<circle r={10 / zoom} fill="#F00" />
</Marker>
)}
</AnimatedZoomableGroup>
)}
</Spring>
</ComposableMap>
</div>
);
};
const App = () => {
const [from, setFrom] = useState([null, null]);
const [to, setTo] = useState([null, null]);
return (
<div style={{ display: "flex" }}>
<MapWidget from={from} to={to} width={400} height={200} />
<button
onClick={() => {
setFrom([16.909270516076127, 52.41050505]);
setTo([-54.9347238, -34.9391291]);
}}
>
1
</button>
<button
onClick={() => {
setFrom([16.909270516076127, 52.41050505]);
setTo([-5.6842457, 43.4545162]);
}}
>
2
</button>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
如您所见,我正在尝试最大程度地缩放地图以根据坐标显示两个点
有什么问题,当您单击 2 时,缩放工作正常,但在 1 上,地图被放大到很远 - 我试图找出问题所在,因为我的计算仅在某些情况下有效。
正如您在函数 calcZoom 中看到的那样,我正在根据这两个坐标和 bbox 的质心计算缩放。
我基本上是在尝试将此 d3 示例移植到 react-simple-maps https://medium.com/@andybarefoot/making-a-map-using-d3-js-8aa3637304ee
如果有人可以提供帮助,那就太好了。
最好的!