Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
262 views
in Technique[技术] by (71.8m points)

reactjs - Bounding Box around GeoJson object with React Leaflet in Gatsby

I have a GeoJSON array for which i have calculated a bounding box using the following method:

function bbox(route) {
  var result = [Infinity, Infinity, -Infinity, -Infinity];
  route.geometry.coordinates.forEach(coord => {
      if (result[0] > coord[0]) {
          result[0] = coord[0];
      }
      if (result[1] > coord[1]) {
          result[1] = coord[1];
      }
      if (result[2] < coord[0]) {
          result[2] = coord[0];
      }
      if (result[3] < coord[1]) {
          result[3] = coord[1];
      }
  });
  return result;
}

this returns the following array

0: Array [ -1.2434230651706457, 52.8960251994431 ]
1: Array [ -1.1970718950033188, 52.922518802806735 ]
length: 2

I'm using the gatsby-starter-leaflet project as my template and pass in the bounds to my map settings in the following way and see the failure:

import React , { useRef } from "react"
import { graphql } from "gatsby"
import { Marker, GeoJSON, } from 'react-leaflet';
import { Helmet } from "react-helmet"

import Layout from 'components/Layout';
import Map from 'components/Map';

const DEFAULT_ZOOM = 15;

function bbox(route) {
  var result = [[Infinity, Infinity], [-Infinity, -Infinity]];
  route.geometry.coordinates.forEach(coord => {
      if (result[0][0] > coord[0]) {
          result[0][0] = coord[0];
      }
      if (result[0][1] > coord[1]) {
          result[0][1] = coord[1];
      }
      if (result[1][0] < coord[0]) {
          result[1][0] = coord[0];
      }
      if (result[1][1] < coord[1]) {
          result[1][1] = coord[1];
      }
  });
  return result;
}


export default function Template({ data }) {
  const { markdownRemark: post } = data // data.markdownRemark holds your post data
  const { gpx: route } = data // data.gpxFileData holds the GPX information to plot

  const markerRef = useRef();

  var bounds = bbox(route.geojson._0)

  const CENTER = [52.92038678191602,-1.2134187016636133];
  
  const mapSettings = {
    bounds: {bounds},
    defaultBaseMap: 'OpenStreetMap',
  };

  return (
    <Layout pageName="home">
    <Helmet>
      <title>Home Page</title>
    </Helmet>

    <h1>{route.geojson._0.geometry.type}</h1>

    <Map {...mapSettings}>
      <Marker ref={markerRef} position={CENTER} />
       <GeoJSON data={route.geojson._0} 
      style={() => ({
        color: '#F72A2A',
        weight: 2,
        fillColor: "#F72A2A",
        fillOpacity: 1,
      })}/>
    </Map>
    </Layout>
  )
}

export const pageQuery = graphql`
  query BlogPostByPath($path: String!, $gpxFile: String) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        path
        title
        gpxFile
      }
    }

    gpx(name: {eq: $gpxFile}) {
      geojson {
        _0 {
          type
          geometry {
            type
            coordinates
          }
  
          properties {
            _gpxType
            coordTimes
            name
            time
            type
          }
        }
      }
    }
  }
`

I debugged the leaflet library and found the failure point occurs on line 1123 of leaflet-src.js

  /*
   * @class LatLngBounds
   * @aka L.LatLngBounds
   *
   * Represents a rectangular geographical area on a map.
   *
   * @example
   *
   * ```js
   * var corner1 = L.latLng(40.712, -74.227),
   * corner2 = L.latLng(40.774, -74.125),
   * bounds = L.latLngBounds(corner1, corner2);
   * ```
   *
   * All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:
   *
   * ```js
   * map.fitBounds([
   *    [40.712, -74.227],
   *    [40.774, -74.125]
   * ]);
   * ```
   *
   * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range.
   *
   * Note that `LatLngBounds` does not inherit from Leaflet's `Class` object,
   * which means new classes can't inherit from it, and new methods
   * can't be added to it with the `include` function.
   */

  function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[])
    if (!corner1) { return; }

    var latlngs = corner2 ? [corner1, corner2] : corner1;

    for (var i = 0, len = latlngs.length; i < len; i++) {
        this.extend(latlngs[i]);
    }
  }

When my simple array is passed into LatLngBounds it tries to count the length but gets undefined, becuase the bounds array is embedded in an object?

{…}
bounds: (2) […]
0: Array [ -1.2434230651706457, 52.8960251994431 ]
1: Array [ -1.1970718950033188, 52.922518802806735 ]
length: 2

I'm not sure... the comments for that function and all the documentation for leaflet suggest that passing a simple array should be acceptable for latlngbounds so I cannot work out why this is failing?

Any help would be appreciated.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...