根据多个标记Lng,Lat设置地图范围

时间:2018-11-16 01:31:03

标签: javascript vuejs2 mapbox-gl-js

我正在使用vue,并安装了位于以下位置的vue-mapbox组件:https://soal.github.io/vue-mapbox/#/quickstart

我已经将js和css更新为最新版本,并且也添加到了index.html中:

      <tr *ngFor="let product of products">
        <td>
          <a>{{ product.productName }}</a>
        </td>
        <td>{{ product.productCode }}</td>
        <td>{{ product.releaseDate }}</td>
        <td>{{ product.price | currency:"USD":"symbol":"1.2-2" }}</td>
      </tr>

我正在尝试利用此组件通过将<!-- Mapbox GL CSS --> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.css" rel="stylesheet" /> <!-- Mapbox GL JS --> <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.js"></script> centerbounds设置为Lng,Lat坐标列表来设置地图边界的默认视图。那么,基本上,如何插入lng,lat坐标并使地图默认将这些坐标居中放置在容器内部?

这是我创建的一个名为fitBounds的组件,旨在使用上面列出的组件Map输出地图框:

vue-mapbox

因此,我正在尝试在此处使用<template> <b-row id="map" class="d-flex justify-content-center align-items-center my-2"> <b-col cols="24" id="map-holder" v-bind:class="getMapType"> <mgl-map id="map-obj" :accessToken="accessToken" :mapStyle.sync="mapStyle" :zoom="zoom" :center="center" container="map-holder" :interactive="interactive" @load="loadMap" ref="mapbox" /> </b-col> </b-row> </template> <script> import { MglMap } from 'vue-mapbox' export default { components: { MglMap }, data () { return { accessToken: 'pk.eyJ1Ijoic29sb2dob3N0IiwiYSI6ImNqb2htbmpwNjA0aG8zcWxjc3IzOGI1ejcifQ.nGL4NwbJYffJpjOiBL-Zpg', mapStyle: 'mapbox://styles/mapbox/streets-v9', // options: basic-v9, streets-v9, bright-v9, light-v9, dark-v9, satellite-v9 zoom: 9, map: {}, // Holds the Map... fitBounds: [[-79, 43], [-73, 45]] } }, props: { interactive: { default: true }, resizeMap: { default: false }, mapType: { default: '' }, center: { type: Array, default: function () { return [4.899, 52.372] } } }, computed: { getMapType () { let classes = 'inner-map' if (this.mapType !== '') { classes += ' map-' + this.mapType } return classes } }, watch: { resizeMap (val) { if (val) { this.$nextTick(() => this.$refs.mapbox.resize()) } }, fitBounds (val) { if (this.fitBounds.length) { this.MoveMapCoords() } } }, methods: { loadMap () { if (this.map === null) { this.map = event.map // store the map object in here... } }, MoveMapCoords () { this.$refs.mapbox.fitBounds(this.fitBounds) } } } </script> <style lang="scss" scoped> @import '../../styles/custom.scss'; #map { #map-obj { text-align: justify; width: 100%; } #map-holder { &.map-modal { #map-obj { height: 340px; } } &.map-large { #map-obj { height: 500px; } } } .mapboxgl-map { border: 2px solid lightgray; } } </style> 方法来使地图初始化为在此处2 Lng,Lat坐标的中心:fitBounds

该怎么做呢?好的,我想我的代码可能有点错误,所以我认为[[-79, 43], [-73, 45]]应该看起来像这样:

fitBounds

无论如何,在最困难的时间内将地图框的初始位置设置为在2个或更多坐标上居中。有人成功做到了吗?

好吧,所以我结束了创建一个过滤器的过程,以便为bbox添加空间,如下所示:

fitBounds: () => {
  return { bounds: [[-79, 43], [-73, 45]] }
}

目前看来已经足够了。比像这样使用它:

Vue.filter('addSpaceToBBoxBounds', function (value) {
  if (value && value.length) {
    var boxArea = []
    for (var b = 0, len = value.length; b < len; b++) {
      boxArea.push(b > 1 ? value[b] + 2 : value[b] - 2)
    }
    return boxArea
  }
  return value
})

2 个答案:

答案 0 :(得分:2)

  

将地图的初始位置设置为居中于2或   更多坐标

您可以使用Turf.js计算所有点要素的边界框,并使用bounds地图选项使用此bbox初始化地图:

http://turfjs.org/docs#bbox

https://www.mapbox.com/mapbox-gl-js/api/#map

答案 1 :(得分:0)

如果您不想再使用另一个库来执行此任务,我想出了一种简单的方法来获取边界框,这里是简化的vue组件。

在将地图对象存储在vue组件上时也要小心,不要使它成为反应性的,因为它会破坏mapboxgl这样做

import mapboxgl from "mapbox-gl";

export default {
    data() {
        return {
            points: [
                {
                    lat: 43.775433,
                    lng: -0.434319
                },
                {
                    lat: 44.775433,
                    lng: 0.564319
                },
                // Etc...
            ]
        }
    },
    computed: {
        boundingBox() {
            if (!Array.isArray(this.points) || !this.points.length) {
                return undefined;
            }

            let w, s, e, n;

            // Calculate the bounding box with a simple min, max of all latitudes and longitudes
            this.points.forEach((point) => {
                if (w === undefined) {
                    n = s = point.lat;
                    w = e = point.lng;
                }

                if (point.lat > n) {
                    n = point.lat;
                } else if (point.lat < s) {
                    s = point.lat;
                }
                if (point.lng > e) {
                    e = point.lng;
                } else if (point.lng < w) {
                    w = point.lng;
                }
            });
            return [
                [w, s],
                [e, n]
            ]
        },
    },
    watch: {
        // Automatically fit to bounding box when it changes
        boundingBox(bb) {
            if (bb !== undefined) {
                const cb = () => {
                    this.$options.map.fitBounds(bb, {padding: 20});
                };
                if (!this.$options.map) {
                    this.$once('map-loaded', cb);
                } else {
                    cb();
                }
            }
        },
        // Watch the points to add the markers
        points: {
            immediate: true, // Run handler on mount (not needed if you fetch the array of points after it's mounted)
            handler(points, prevPoints) {
                // Remove the previous markers
                if (Array.isArray(prevPoints)) {
                    prevPoints.forEach((point) => {
                        point.marker.remove();
                    });
                }

                //Add the new markers
                const cb = () => {
                    points.forEach((point) => {

                        // create a HTML element for each feature
                        const el = document.createElement('div');
                        el.className = 'marker';
                        el.addEventListener('click', () => {
                            // Marker clicked
                        });
                        el.addEventListener('mouseenter', () => {
                            point.hover = true;
                        });
                        el.addEventListener('mouseleave', () => {
                            point.hover = false;
                        });

                        // make a marker for each point and add to the map
                        point.marker = new mapboxgl.Marker(el)
                            .setLngLat([point.lng, point.lat])
                            .addTo(this.$options.map);
                    });
                };
                if (!this.$options.map) {
                    this.$once('map-loaded', cb);
                } else {
                    cb();
                }
            }
        }
    },
    map: null, // This is important to store the map without reactivity
    methods: {
        mapLoaded(map) {
            this.$options.map = map;
            this.$emit('map-loaded');
        },
    },
}

只要您的点不在经纬度介于180°和-180°之间的太平洋中间(如果有的话),它应该就可以正常工作,只需添加一个检查点即可在纬度的返回中反转东西方向边界框应该可以解决问题