3

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

这是放大前的地图 在此处输入图像描述

并在缩放后 在此处输入图像描述

这是初始化地图和添加标记的函数

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

非常感谢任何帮助或线索

4

6 回答 6

3

Vuedata()属性是反应性的,它们具有gettersand setters,因此,当加载地图对象或添加矢量切片图层(geojson)时,Vue 会尝试向 & 添加 getter 和 setter,mapmap.layers会导致 vue 和 vue-dev-tools 崩溃并弄乱地图.

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

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

// 编辑:设置非反应性数据的正确/推荐方法:GitHub 链接

于 2019-06-26T03:00:57.813 回答
1

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

于 2018-06-16T09:47:05.167 回答
1

我刚刚遇到了这个问题,并意识到我没有完全按照文档的描述进行操作(在没有正确阅读的情况下直接进入编码)。文件说:

存储地图对象

请注意,除了原始类型和普通对象之外,向 Vuex 或组件的数据添加任何内容通常都是个坏主意。Vue 为每个属性添加了 getter 和 setter,因此如果将 Map 对象添加到 Vuex 存储或组件数据中,可能会导致奇怪的错误。如果要存储地图对象,请将其存储为非反应性属性,如下例所示。

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

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

于 2020-02-07T20:40:40.037 回答
1

在这个问题上花费了几个小时后,这是我从商店访问地图实例的工作解决方案(感谢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"
  });
};

应用程序.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>

于 2020-07-23T12:33:27.773 回答
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>
于 2021-02-24T19:16:35.360 回答
0

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

于 2019-01-14T14:09:12.507 回答