最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Scale MapBox GL map to fit set of markers - Stack Overflow

programmeradmin6浏览0评论

Say I have the following code for a mapbox map:

mapboxgl.accessToken = '<token>';
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/satellite-v9',
    center: [-96, 37.8],
    zoom: 2,
    interactive: true
});

var geojson = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-77.03238901390978, 38.913188059745586]
            },
            "properties": {
                "id": 1,
                "color": "#007cbf",
                "text": "1"
            }
        }, 
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-78.03238901390978, 39.913188059745586]
            },
            "properties": {
                "id": 2,
                "color": "red",
                "text": "2"
            }
        }
    ]
}

map.on('style.load', function (e) {
    map.addSource('markers', {
        "type": "geojson",
        "data": geojson
    });
    geojson.features.forEach(function(marker){
        map.addLayer({
            "id": String(marker.properties.id)+'-circle',
            "source": "markers",
            "type": "circle",
            "paint": {
                "circle-radius": 20,
                "circle-color": marker.properties.color,
                "circle-opacity": 0.8,
                "circle-stroke-width": 0,
            },
            "filter": ["==", "id", marker.properties.id],
        });
        map.addLayer({
            "id": String(marker.properties.id)+'-text',
            "source": "markers",
            "type": "symbol",
            "layout": {
                'text-field': marker.properties.text,
                'text-size': 20
            },
            "filter": ["==", "id", marker.properties.id]
        })
    });
});

How would I scale the map to fit a set of points on a map? I can't find any solutions for mapboxgl. Also, I'm not 100% sure that I should be creating a separate layer for each marker, but I couldn't find a way to put all the makers into one layer. Thanks in advance.

Say I have the following code for a mapbox map:

mapboxgl.accessToken = '<token>';
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/satellite-v9',
    center: [-96, 37.8],
    zoom: 2,
    interactive: true
});

var geojson = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-77.03238901390978, 38.913188059745586]
            },
            "properties": {
                "id": 1,
                "color": "#007cbf",
                "text": "1"
            }
        }, 
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-78.03238901390978, 39.913188059745586]
            },
            "properties": {
                "id": 2,
                "color": "red",
                "text": "2"
            }
        }
    ]
}

map.on('style.load', function (e) {
    map.addSource('markers', {
        "type": "geojson",
        "data": geojson
    });
    geojson.features.forEach(function(marker){
        map.addLayer({
            "id": String(marker.properties.id)+'-circle',
            "source": "markers",
            "type": "circle",
            "paint": {
                "circle-radius": 20,
                "circle-color": marker.properties.color,
                "circle-opacity": 0.8,
                "circle-stroke-width": 0,
            },
            "filter": ["==", "id", marker.properties.id],
        });
        map.addLayer({
            "id": String(marker.properties.id)+'-text',
            "source": "markers",
            "type": "symbol",
            "layout": {
                'text-field': marker.properties.text,
                'text-size': 20
            },
            "filter": ["==", "id", marker.properties.id]
        })
    });
});

How would I scale the map to fit a set of points on a map? I can't find any solutions for mapboxgl. Also, I'm not 100% sure that I should be creating a separate layer for each marker, but I couldn't find a way to put all the makers into one layer. Thanks in advance.

Share Improve this question asked Jul 16, 2020 at 16:33 CircuitSaculCircuitSacul 1,85015 silver badges35 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

I think what you are looking for is map.fitBounds that will create a bounding box to adapt map view to a list of coordinates.

map.fitBounds([
  [-77.03238901390978, 38.913188059745586],
  [-78.03238901390978, 39.913188059745586]
]);

But if you could have a bunch of points in a source as it seems based in your code, then you need to first push all the coordinates of each marker to an array, and then use coordinates.reduce

var coordinates = coords;

var bounds = coordinates.reduce(function(bounds, coord) {
  return bounds.extend(coord);
}, new mapboxgl.LngLatBounds(coordinates[0], coordinates[0]));

map.fitBounds(bounds, {
  padding: 20
});

I have created a fiddle for you with this solution, how to fit mapbox bounds to a list of coords, it works your using your own code and coords.

Regarding the creation of a layer for each marker, definitely you should try to avoid that practice and create a single layer only to host all the markers.

To use Mapbox GL JS map.fitBounds(bounds, options?) you can also use an array of [lng, lat] pairs which represent the most southwestern and most northeastern corners of the specified geographical bounds.

Always keep in mind:
lng (lon): longitude (London = 0, Bern = 7.45, New York = -74)
→ the lower, the more western

lat: latitude (Equator = 0, Bern = 46.95, Capetown = -33.9)
→ the lower, the more southern

To calculate these I created the following functions to get the most southwestern and most northeastern corners of a collection of coordinates and merge them into an array:

getSWCoordinates(coordinatesCollection) {
  const lowestLng = Math.min(
    ...coordinatesCollection.map((coordinates) => coordinates[0])
  );
  const lowestLat = Math.min(
    ...coordinatesCollection.map((coordinates) => coordinates[1])
  );

  return [lowestLng, lowestLat];
}

getNECoordinates(coordinatesCollection) {
  const highestLng = Math.max(
    ...coordinatesCollection.map((coordinates) => coordinates[0])
  );
  const highestLat = Math.max(
    ...coordinatesCollection.map((coordinates) => coordinates[1])
  );

  return [highestLng, highestLat];
}

calcBoundsFromCoordinates(coordinatesCollection) {
  return [
    getSWCoordinates(coordinatesCollection),
    getNECoordinates(coordinatesCollection),
  ];
}

To use the function, you can just call calcBoundsFromCoordinates and enter an array containing all your markers coordinates:

calcBoundsFromCoordinates([
  [8.03287, 46.62789],
  [7.53077, 46.63439],
  [7.57724, 46.63914],
  [7.76408, 46.55193],
  [7.74324, 46.7384]
])

// returns [[7.53077, 46.55193], [8.03287, 46.7384]]
发布评论

评论列表(0)

  1. 暂无评论