如何将 vanilla JS 与 React 组件一起使用(在加载反应 mapbox gl 时缩放到边界)

How to use vanilla JS with React component (zoom to bounds on load react mapbox gl)

我希望在安装组件时能够缩放到边界。

我知道这个 vanilla JS 代码可以实现缩放到边界,但不确定如何将其添加到下面的 React 代码中(我认为需要一个 REF?):

var bounds = new mapboxgl.LngLatBounds();

parkDate.features.forEach(function(feature) { 
    bounds.extend(feature.geometry.coordinates);
});

map.fitBounds(bounds, {
    padding: {top: 20, bottom:20, left: 20, right: 20}
})

分量:

import React, { useState } from "react";
import ReactMapGL, { Marker } from "react-map-gl";
import * as parkDate from "./data.json";
const mapIcon: any = require('../images/mapIcon.png');

export default function App() {

  const [viewport, setViewport] = useState({
    latitude: 45.4211,
    longitude: -75.6903,
    width: "100%",
    height: "400px",
    zoom: 10
  });
  const [selectedPark, setSelectedPark] = useState(null);

  return (
    <div>
      <ReactMapGL
        {...viewport}
        mapboxApiAccessToken="pk.eyJ1IjoiYmVubmtpbmd5IiwiYSI6ImNrY2ozMnJ5dzBrZ28ycnA1b2Vqb2I0bXgifQ.ZOaVtzsDQOrAovh9Orh13Q"
        mapStyle="mapbox://styles/mapbox/streets-v11"
        onViewportChange={viewport => {
          setViewport(viewport);
        }}
      >
        {parkDate.features.map(park => (
          <Marker
            key={park.properties.PARK_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>
          <h2>{selectedPark.properties.NAME}</h2>
          <p>{selectedPark.properties.DESCRIPTIO}</p>
          <button onClick={e => {
                e.preventDefault();
                setSelectedPark(null);
              }}>X</button>
        </div>
      ) : null}
    </div>
  );
}

得到这样的效果:

import React, { useState } from "react";
import ReactMapGL, { Marker, WebMercatorViewport } from "react-map-gl";
import * as parkData from "./data.json";
const mapIcon: any = require('../images/mapIcon.png');

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:150, bottom:200, left:100, right:150} }) 
  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.PARK_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>
          <h2>{selectedPark.properties.NAME}</h2>
          <p>{selectedPark.properties.DESCRIPTIO}</p>
          <button onClick={e => {
                e.preventDefault();
                setSelectedPark(null);
              }}>X</button>
        </div>
      ) : null}
    </div>
  );
}

export default myMap;