I'm working on project with your library and this is what I got
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);
As you can see I'm trying to maximally zoom the map to show two points based on their coordinates
What is a problem, when you click on 2 the zooming work properly, but on 1 the map is zoomed to far - I'm trying to figure out what is wrong witch my calculation that it work only in some cases.
As you can see in function calcZoom I'm calculating zoom based on centroid of this two coordinates and bbox.
I'm basically trying to port this d3 example to react-simple-maps https://medium.com/@andybarefoot/making-a-map-using-d3-js-8aa3637304ee
If someone can help be would be greatfull.
Best!