Drawing a circle with the radius in miles/meters with Mapbox GL JS

后端 未结 4 1613
自闭症患者
自闭症患者 2020-12-08 00:15

I\'m in the process of converting a map from using mapbox.js to mapbox-gl.js, and am having trouble drawing a circle that uses miles or met

4条回答
  •  没有蜡笔的小新
    2020-12-08 01:14

    Elaborating on Lucas' answer, I've come up with a way of estimating the parameters in order to draw a circle based on a certain metric size.

    The map supports zoom levels between 0 and 20. Let's say we define the radius as follows:

    "circle-radius": {
      stops: [
        [0, 0],
        [20, RADIUS]
      ],
      base: 2
    }
    

    The map is going to render the circle at all zoom levels since we defined a value for the smallest zoom level (0) and the largest (20). For all zoom levels in between it results in a radius of (approximately) RADIUS/2^(20-zoom). Thus, if we set RADIUS to the correct pixel size that matches our metric value, we get the correct radius for all zoom levels.

    So we're basically after a conversion factor that transforms meters to a pixel size at zoom level 20. Of course this factor depends on the latitude. If we measure the length of a horizontal line at the equator at the max zoom level 20 and divide by the number of pixels that this line spans, we get a factor ~0.075m/px (meters per pixel). Applying the mercator latitude scaling factor of 1 / cos(phi), we obtain the correct meter to pixel ratio for any latitude:

    const metersToPixelsAtMaxZoom = (meters, latitude) =>
      meters / 0.075 / Math.cos(latitude * Math.PI / 180)
    

    Thus, setting RADIUS to metersToPixelsAtMaxZoom(radiusInMeters, latitude) gets us a circle with the correct size:

    "circle-radius": {
      stops: [
        [0, 0],
        [20, metersToPixelsAtMaxZoom(radiusInMeters, latitude)]
      ],
      base: 2
    }
    

提交回复
热议问题