我正在尝试制作一个包含世界地图的交互式页面,当您单击某个位置时,它会创建一个标记并保存坐标。关于如何实现这一目标的任何想法?
问问题
600 次
1 回答
0
在花了一个周末寻找解决方案之后,这应该可以解决问题。也适用于大多数事件,而不仅仅是点击。
import React, { useState } from "react";
import {
ComposableMap,
Geographies,
Geography,
Marker,
ZoomableGroup
} from "react-simple-maps";
import { geoPath } from "d3-geo";
const geoUrl =
"https://raw.githubusercontent.com/zcreativelabs/react-simple-maps/master/topojson-maps/world-110m.json";
const markersBegin = [
{
markerOffset: -30,
name: "Buenos Aires",
coordinates: [-58.3816, -34.6037]
}
];
const MapChart = () => {
const [scale, setSclae] = useState(1);
const [markers, setMarkers] = useState(markersBegin);
return (
<ComposableMap projection="geoMercator">
<ZoomableGroup zoom={1} onMoveEnd={({ zoom }) => setSclae(zoom)}>
<Geographies geography={geoUrl}>
{({ geographies, projection }) =>
geographies
.filter((d) => d.properties.REGION_UN === "Americas")
.map((geo) => {
const onGeoEventFactory = (handleCoordinates) => {
const gPath = geoPath().projection(projection);
return (evt) => {
const dim = evt.target.getBoundingClientRect();
const cx = evt.clientX - dim.left;
const cy = evt.clientY - dim.top;
const [geoX, geoY] = gPath.bounds(geo)[0];
//we need root SVG element of our map
const svg = evt.nativeEvent.path[4];
//adjust for SVG width on the page / internal rendering width
const adjustScale =
scale * (svg.clientWidth / svg.viewBox.baseVal.width);
// these are the coords in SVG coordinate system
const clickCoordsInsideSvg = [
geoX + (cx / adjustScale),
geoY + (cy / adjustScale)
];
// 'unproject' the SVG coords to get lat and long
handleCoordinates(projection.invert(clickCoordsInsideSvg));
};
};
return (
<Geography
key={geo.rsmKey}
geography={geo}
fill="#EAEAEC"
stroke="#D6D6DA"
onClick={onGeoEventFactory((coordinates) => {
const newMarkers = [
...markers,
{
markerOffset: -30,
name: "Marker",
coordinates
}
];
setMarkers(newMarkers);
})}
/>
);
})
}
</Geographies>
{markers.map(({ name, coordinates, markerOffset }) => (
<Marker key={name} coordinates={coordinates}>
<g
fill="none"
stroke="#FF5533"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
transform="translate(-12, -24)"
>
<circle cx="12" cy="10" r="3" />
<path d="M12 21.7C17.3 17 20 13 20 10a8 8 0 1 0-16 0c0 3 2.7 6.9 8 11.7z" />
</g>
<text
textAnchor="middle"
y={markerOffset}
style={{ fontFamily: "system-ui", fill: "#5D5A6D" }}
>
{name}
</text>
</Marker>
))}
</ZoomableGroup>
</ComposableMap>
);
};
export default MapChart;
于 2021-08-29T22:00:59.497 回答