reactjs - 如何在更改浏览器宽度时调整 mapbox 的大小

标签 reactjs mapbox

如何调整下面的代码,以便在我调整浏览器/屏幕大小时调整 map 大小? (第一次在没有高级开发人员帮助的情况下使用 Mapbox)。

根据我自己的研究,有一些代码库可以在 map 容器上添加一个事件监听器并监听它以调整大小,然后我可以以编程方式调用 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>
  );
}

代码演示 https://codesandbox.io/s/immutable-glitter-hokq6?file=/src/App.js

我会合法地请你喝一两杯咖啡来帮助你<3

最佳答案

在广泛使用 mapbox 之后,我可以告诉您 map.resize() 必须在某个时候调用,由您调用,或者由内部的 react-map-gl 绑定(bind)调用.

因此,您需要先创建一个调整大小处理程序,我更喜欢在钩子(Hook)中执行此操作:

const useResize = (handler) => {
  useEffect(() => {
    window.addEventListener("resize", handler);

    return () => {
      window.removeEventListener("resize", handler);
    };
  }, [handler]);
};

然后你可以在你的组件中使用它:

const onResize = useCallback(() => {
  setViewport({ ...viewport });
}, []);

useResize(onResize);

由于您更新了视口(viewport)对象,react-map-gl 会将此识别为状态更改并相应地更新视口(viewport),可能是通过在内部调用 map.resize()

这是一个沙箱:https://codesandbox.io/s/upbeat-tdd-o8vn3?file=/src/App.js

另一个(可以说是更好的)解决方案 是简单地自己调用 map.resize()。为此,只需在加载时捕获 map 对象:

<ReactMapGL
 {...viewport}
 onLoad={({ map }) => setMap(map)}
>

然后在调整大小处理程序中调用 map.resize():

const onResize = useCallback(() => {
  if (map) {
    map.resize();
  }
}, [map]);

此解决方案将具有更好的性能,因为它更接近金属并且不需要克隆当前视口(viewport)对象。

这是此解决方案的沙箱:https://codesandbox.io/s/optimistic-kalam-8p8jo?file=/src/App.js

关于reactjs - 如何在更改浏览器宽度时调整 mapbox 的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70352188/

相关文章:

performance - Mapbox 性能 - 单独图层、setData 和过滤器

mapbox - 调整 map 的不透明度

javascript - 从本地geojson文件mapbox/leaflet创建var

javascript - 将 props 传递给子组件时避免组件重新渲染

javascript - 在 Mapbox 中搜索国家

reactjs - 为什么控制台日志中的值未显示在 ReactJS 中

javascript - 检查数组的值是否存在于不同数组中的对象中

传单 divIcon 未显示在 map 上

javascript - CSS 文本颜色过渡到多个值

angular - 多个 observable 协同工作