如何调整下面的代码,以便在调整浏览器/屏幕大小时调整地图大小?(第一次在没有高级开发人员帮助的情况下使用 Mapbox)。
根据我自己的研究,有一些代码库可以在地图容器上添加事件侦听器并侦听该事件侦听器以调整大小,然后我可以以编程方式调用 map.resize() 。但是,我想知道最佳实践是什么,因为这种方式感觉有点老套。
代码
const applyToArray = (func, array) => func.apply(Math, array)
const getBoundsForPoints = (points) => {
console.log('Points:', points)
// Calculate corner values of bounds
const pointsLong = points.map(point => point.geometry.coordinates[0])
const pointsLat = points.map(point => point.geometry.coordinates[1])
const cornersLongLat = [
[applyToArray(Math.min, pointsLong), applyToArray(Math.min, pointsLat)],
[applyToArray(Math.max, pointsLong), applyToArray(Math.max, pointsLat)]
]
// Use WebMercatorViewport to get center longitude/latitude and zoom
const viewport = new WebMercatorViewport({ width: 600, height: 600 })
// @ts-ignore
.fitBounds(cornersLongLat, { padding: {top:20, bottom: 90, left:20, right:20} })
const { longitude, latitude, zoom } = viewport
return { longitude, latitude, zoom }
}
const myMap = () => {
const bounds = getBoundsForPoints(parkData.features);
const [viewport, setViewport] = useState({
width: "100%",
height: "600px",
...bounds
});
const [selectedPark, setSelectedPark] = useState(null);
return (
<div>
<ReactMapGL
{...viewport}
mapboxApiAccessToken="pk.eyJ1IjoiYmVubmtpbmd5IiwiYSI6ImNrY2ozMnJ5dzBrZ28ycnA1b2Vqb2I0bXgifQ.ZOaVtzsDQOrAovh9Orh13Q"
mapStyle="mapbox://styles/mapbox/streets-v11"
onViewportChange={viewport => {
setViewport(viewport);
}}
>
{parkData.features.map(park => (
<Marker
key={park.properties.ID}
latitude={park.geometry.coordinates[1]}
longitude={park.geometry.coordinates[0]}
>
<button
className="marker-btn"
onClick={e => {
e.preventDefault();
setSelectedPark(park);
}}
>
<img src={mapIcon} alt="Map Pointer Icon" />
</button>
</Marker>
))}
</ReactMapGL>
{selectedPark ? (
<div className={ styles.officeInfo }>
<div className={ styles.officeInfoImage }>
<img src={selectedPark.properties.IMAGE} />
</div>
<div className={ styles.officeInfoContent }>
<h3>{selectedPark.properties.NAME}</h3>
<p>{selectedPark.properties.DESCRIPTION}</p>
<button onClick={e => {
e.preventDefault();
setSelectedPark(null);
}}>X</button>
</div>
</div>
) : null}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
代码演示 https://codesandbox.io/s/immutable-glitter-hokq6?file=/src/App.js
我会合法地请你喝一两杯咖啡来帮助<3
在广泛使用过 mapbox 后,我可以告诉您,map.resize()必须在某个时刻调用它,无论是由您调用,还是由内部的 React-map-gl 绑定调用。
因此,您需要首先创建一个调整大小处理程序,我更喜欢在钩子中执行此操作:
const useResize = (handler) => {
useEffect(() => {
window.addEventListener("resize", handler);
return () => {
window.removeEventListener("resize", handler);
};
}, [handler]);
};
Run Code Online (Sandbox Code Playgroud)
然后你可以在你的组件中使用它:
const onResize = useCallback(() => {
setViewport({ ...viewport });
}, []);
useResize(onResize);
Run Code Online (Sandbox Code Playgroud)
由于您更新了视口对象,react-map-gl 会将其识别为状态更改并相应地更新视口(可能是通过map.resize()内部调用)。
这是一个沙箱:https://codesandbox.io/s/upbeat-tdd-o8vn3 ?file=/src/App.js
另一种(可以说更好)的解决方案是简单地给map.resize()自己打电话。为此,只需捕获map加载时的对象即可:
<ReactMapGL
{...viewport}
onLoad={({ map }) => setMap(map)}
>
Run Code Online (Sandbox Code Playgroud)
然后调用map.resize()你的调整大小处理程序:
<ReactMapGL
{...viewport}
onLoad={({ map }) => setMap(map)}
>
Run Code Online (Sandbox Code Playgroud)
该解决方案将具有更好的性能,因为它更接近金属并且不需要克隆当前视口对象。
这是此解决方案的沙箱:https://codesandbox.io/s/optimistic-kalam-8p8jo ?file=/src/App.js