添加图层时,Mapbox样式会在缩放时更改/中断

时间:2018-06-12 19:19:40

标签: javascript vue.js mapbox mapbox-marker

我有一个mapbox地图,用outdoors-v9样式初始化(​​尝试了其他样式,相同的行为)。当我向地图添加图层 - 标记或geojson源并缩放地图,样式更改或中断时,我不确定哪一个。

这是缩放前的地图 enter image description here

和缩放后 enter image description here

这是启动地图和添加标记的功能

mapboxgl.accessToken = "pk.*******";


buildMap: function() {
  const _self = this;
  _self.map = new mapboxgl.Map({
    container: "map",
    style: "mapbox://styles/mapbox/outdoors-v9",
    center: [-95.712891, 37.09024],
    zoom: 3
  });

  _self.map.on('load', function() {
    _self.map.addSource('route', {
      'type': 'geojson',
      'data': {
            "type": "FeatureCollection",
            "features": []
      } 
    });

    _self.map.addLayer({
        'id': 'route',
        'source': 'route',
        'type': 'line',
        'layout': {
          'line-join': 'round',
          'line-cap': 'round'
        },
        'paint': {
          'line-color': '#47576A',
          'line-width': 3
        }
      });
  });
}

...

const coords = [addressData.longitude, addressData.latitude];

const marker = new mapboxgl.Marker().setLngLat(coords).addTo(this.map);

我正在使用Vue.js来渲染地图。 Mapbox版本v0.45.0

非常感谢任何帮助或潜在客户

6 个答案:

答案 0 :(得分:1)

似乎问题与我将标记实例推送到observable(vuejs数据字段)的事实有关。将标记实例推送到数组后,问题就消失了。这个评论并没有真正回答为什么会发生这种情况,但希望它可以帮助其他可能面临同样问题的人

答案 1 :(得分:1)

Vue的data()属性是反应性的,它们分别具有getterssetters,因此,在加载地图对象或添加矢量切片图层(geojson)时,Vue会尝试将getter和setter添加到mapmap.layers会导致vue和vue-dev-tools崩溃并弄乱地图。

如果启用任何栅格图层,则将成功运行,因为栅格图块是通过mapbox.css加载的,而矢量图块是geojson,则已添加到map对象中。

最简单的解决方案是在vue中定义一个非反应变量,然后在各处重复使用它。

答案 2 :(得分:1)

我只是面对这个问题,并且意识到我并没有完全按照所描述的文档进行操作(跳过了正确的阅读而直接进入了编码)。并且文档说:

存储地图对象

请注意,通常添加到Vuex或组件的 除了原始类型和普通对象之外,任何数据都可以。 Vue添加吸气剂 和每个属性的设置器,所以如果您将Map对象添加到Vuex商店 或组件数据,可能会导致奇怪的错误。如果要存储地图 对象,将其存储为非反应性属性,如下例所示。

问题是我还在Vue组件的“数据”对象内注册了“地图”。但是在示例代码中,它没有在数据中声明,仅在“创建”函数中声明。

https://soal.github.io/vue-mapbox/guide/basemap.html#map-loading

答案 3 :(得分:0)

我有同样的错误。 如果您将地图或标记放在反应性vue.js实例上,则会发生这种情况。

答案 4 :(得分:0)

花了几个小时解决这个问题之后,这是我可以从商店访问地图实例的有效解决方案(感谢https://github.com/vuejs/vue/issues/2637#issuecomment-331913620):

const state = reactive({
  map: Object.freeze({ wrapper: /* PUT THE MAP INSTANCE HERE */ });
});

以下是Vue Composition Api的示例:

index.js

import { reactive, computed } from "@vue/composition-api";

export const state = reactive({
  map: null
});

export const setMap = (map) => {
  state.map = Object.freeze({ wrapper: map});
};

export const getMap = computed(() => state.map.wrapper);

export const initMap = (event) => {
  setMap(event.map);

  // now you can access to map instance from the "getMap" getter!
  getMap.value.addSource("satellite-source", {
    type: "raster",
    url: "mapbox://mapbox.satellite",
  }); 
  getMap.value.addLayer({
    id: "satellite-layer",
    type: "raster",
    source: "satellite-source"
  });
};

App.vue

<template>
  <MglMap :accessToken="..." :mapStyle="..." @load="onMapLoaded" />
</template>


<script>
import { defineComponent } from "@vue/composition-api";
import { MglMap } from "vue-mapbox";
import { initMap } from "./index.js";

export default defineComponent({
  components: {
    MglMap
  },
  setup() {
    const onMapLoaded = (event) => {
      initMap(event);
    }

    return { onMapLoaded };
  }
});
</script>

答案 5 :(得分:0)

简短而快速的回答。

解释类似于@mlb 的回答。因此,您冻结对象以防止地图迷失方向,并且对于对地图执行的任何操作,请使用额外的对象键回调数据,以防万一是“包装器”。

<template><MglMap :accessToken="..." :mapStyle="..." @load="onMapLoaded" /></template>
    
<script>  
methods: {  
 onMapLoaded(event) {
   this.mapboxEvent = Object.freeze({wrapper: event.map});
 },
 panMap(event) {
   this.mapboxEvent.wrapper.panTo([lng, lat], {duration: 1000, zoom: 14});
 }
}
</script>