Переключение видимости слоев карты из другого компонента - PullRequest
0 голосов
/ 22 мая 2018

Прежде всего, я студент-дизайнер и использую Vue.js для создания прототипа моего старшего проекта.Так что это не настоящий рабочий проект.Просто прототип некоторого приложения для дневников.

Моя проблема в том, что я строю компонент карты с помощью Vue2Leaflet , который имеет слой листов.

В слое листов я рендерил файл GeoJSONкоторый имеет два объекта координат.

У меня также есть компонент datepicker, который выдает значения с помощью EventBus.

Моя цель: когда datepicker выдает определенное значение, отключение <l-geo-json> ивключите другой <l-geo-json>.

<l-geo-json> имеет параметр :visible для отображения или скрытия.:visible получает параметр из объекта GeoJSON.datepicker выдает некоторое логическое значение для изменения параметра GeoJSON.Параметр GeoJSON изменяется, но он не отображается на карте.

Я думаю, это из-за не повторного рендеринга компонента карты.

Мой компонент карты имеет вид:

<template>
  <div v-if="refresh" id="MapView2">
    <i class="material-icons geoLocate" v-on:click="geoLoc">location_searching</i>
    <l-map :zoom="zoom" :options="{ zoomControl: false }" class="map" :center="center">
      <l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
      <l-geo-json :visible="yesterday.day" :geojson="bus.geojson" :options="bus.options"></l-geo-json>
      <l-geo-json :visible="today.day" :geojson="today.geojson" :options="today.options"></l-geo-json>
    </l-map>
  </div>
</template>

<script>
import Vue from 'vue';
import Leaflet from 'leaflet';
import L from 'leaflet';
import { LMap, LTileLayer, LGeoJson } from 'vue2-leaflet';
import PopupContent from './GeoJson2Popup';
import { data, EventBus2 } from '../assets/geojson/sample-geojson.js';


export default {
  name: 'MapView2',
  components: {
    LMap,
    LTileLayer,
    LGeoJson,
  },
  data(){
    return {
      zoom: 13,
      center: {
        lat: '',
        lng: '',
      },
      url:'https://api.mapbox.com/styles/v1/mapbox/light-v9/tiles/256/{z}/{x}/{y}?access_token=...',
      attribution: '',
      yesterday: {
        geojson: data.yesterday,
        day: data.yesterday.visible,
        options: {
          onEachFeature: onEachFeature,
          color: "#45B8FF",
          fillOpacity: 0.8
        }
      },
      today: {
        geojson: data.today,
        day: data.today.visible,
        options: {
          onEachFeature: onEachFeature,
          color: "#45B8FF",
          fillOpacity: 0.8
        }
      },
    }
  },
  methods: {
    geoLoc() {
      navigator.geolocation.getCurrentPosition(position => {
        this.position = position.coords;
        this.center.lat = position.coords.latitude
        this.center.lng = position.coords.longitude
        this.zoom = 25
        console.log(position.coords)
      })
    }
  },
  beforeCreate() {
    if(navigator.geolocation){
      navigator.geolocation.getCurrentPosition(position => {
        this.isLoading = false
        this.position = position.coords;
        this.center.lat = position.coords.latitude
        this.center.lng = position.coords.longitude
        console.log(position.coords)
      })
    }
  },
  mounted() {
    EventBus2.$on('mapDay', pickerValue => {
      switch (pickerValue) {
        case data.today.id:
        data.yesterday.visible = true;
        data.today.visible = false;
        break;
        case data.yesterday.id:
        data.yesterday.visible = false;
        data.today.visible = true;
        break;
      }
    });
  },
};
</script>

А также мой файл geojson.js похож на

    import Vue from 'vue';
    export const EventBus2 = new Vue();
    export const data = {
      today: {
        "type": "FeatureCollection",
        "id": "0520",
        "visible": false,
        "features": [ // geojson features and coordinates ]
      },

      yesterday: {
        "type": "FeatureCollection",
        "id": "0520",
        "visible": false,
        "features": [ // geojson features and coordinates ]
      }
  }

Как видите, средство выбора даты выдает какое-то значение в формате MMDD.Оператор Switch проверяет значение в данных GeoJSON по id.Если оно совпадает, измените свойство visible.На самом деле он изменяется, когда генерируется указатель даты.

Но он не отображается на карте (слои GeoJSON не меняют видимость соответственно).

Как я могу это сделать?Должен ли я использовать watch или что-то подобное?Если это так, как я могу это использовать?

1 Ответ

0 голосов
/ 22 мая 2018

Вы должны просто напрямую изменить свой экземпляр data.

Для ясности я сделаю так, как если бы вы импортировали из файла geojson.js как data2.Вызов одного и того же может быть причиной вашего замешательства.

import { data as data2, EventBus2 } from '../assets/geojson/sample-geojson.js';

Причина, по которой видимость слоев GeoJSON не изменяется динамически, заключается в том, что вы правильно инициализируете свои свойства экземпляра data и day, используя информациюот вашего data2, но это не связывает их динамически с будущими модификациями в data2.

Поэтому самый простой подход - переключить свойства вашего экземпляра data и day в ваших "mapDay"прослушиватель событий вместо информации в data2.

EventBus2.$on('mapDay', pickerValue => {
  switch (pickerValue) {
    case data2.today.id:
      this.yesterday.day = true;
      this.today.day = false;
    break;
    case data2.dun.id:
      this.yesterday.day = false;
      this.today.day = true;
    break;
  }
});

Вы также можете переключать свои data и data2, если вы хотите, чтобы data2 также синхронизировались, например, если выиспользуйте его в другом компоненте.Обратите внимание, что такая стратегия была бы хрупкой, поскольку изменение data2 в этом другом компоненте не имело бы здесь никакого эффекта.

С другой стороны, вы могли бы упростить логику переключения видимости, просто сохранив свой pickerValue вваш экземпляр data и сравните его с вашим geojson.id в :visible выражении привязки атрибута: :visible="pickerValue === yesterday.geojson.id"

Пример кода:

Vue.component('map-view-2', {
  template: '#map-view-2',
  components: {
    'l-map': Vue2Leaflet.LMap,
    'l-tile-layer': Vue2Leaflet.LTileLayer,
    'l-geo-json': Vue2Leaflet.LGeoJson,
  },
  data() {
    return {
      pickerValue: '0520',
      url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
      yesterday: {
        geojson: data2.yesterday,
      },
      today: {
        geojson: data2.today,
      },
    };
  },
  mounted() {
    this.$root.$on('mapDay', pickerValue => {
      this.pickerValue = pickerValue;
    });
  },
});

// Dummy DatePicker component for the sake of the demo.
Vue.component('date-picker', {
  template: '#datepicker',
  methods: {
    handleInputChange(event) {
      this.$root.$emit('mapDay', event.target.value);
    },
  },
});

const data2 = {
  today: {
    "type": "FeatureCollection",
    "id": "0520",
    "features": [{
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [2.34, 48.86] // Left
      },
    }],
  },
  yesterday: {
    "type": "FeatureCollection",
    "id": "0519",
    "features": [{
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [2.35, 48.86] // Right
      },
    }],
  },
};

new Vue({
  el: '#app',
});
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet-src.js"></script>
<script src="https://unpkg.com/vue2-leaflet@1.0.2/dist/vue2-leaflet.js"></script>

<template id="map-view-2">
  <div id="MapView2">
    <l-map :zoom="11" style="height: 100px;" :center="[48.86, 2.35]">
      <l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
      <l-geo-json :visible="pickerValue === yesterday.geojson.id" :geojson="yesterday.geojson"></l-geo-json>
      <l-geo-json :visible="pickerValue === today.geojson.id" :geojson="today.geojson"></l-geo-json>
    </l-map>
  </div>
</template>

<template id="datepicker">
  <fieldset @change="handleInputChange">
    <legend>Choose a date</legend>
    <input type="radio" name="date" value="0520" id="today" checked />
    <label for="today">Today 0520</label>
    <input type="radio" name="date" value="0519" id="yesterday" />
    <label for="yesterday">Yesterday 0519</label>
    <input type="radio" name="date" value="none" id="none" />
    <label for="none">None</label>
  </fieldset>
</template>

<div id="app">
  <map-view-2></map-view-2>
  <date-picker></date-picker>
</div>

Более модульный подход будет представлять данные pickerValue как prop, так что вы будете изменять их непосредственно на уровне родительского (например, приложения),вместо того, чтобы слушать ваше "mapDay" событие:

Vue.component('map-view-2', {
  template: '#map-view-2',
  components: {
    'l-map': Vue2Leaflet.LMap,
    'l-tile-layer': Vue2Leaflet.LTileLayer,
    'l-geo-json': Vue2Leaflet.LGeoJson,
  },
  props: {
    // Receive the value directly from parent component / App.
    pickerValue: {
      type: String,
      default: '0520',
    },
  },
  data() {
    return {
      url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
      yesterday: {
        geojson: data2.yesterday,
      },
      today: {
        geojson: data2.today,
      },
    };
  },
});

// Dummy DatePicker component for the sake of the demo.
Vue.component('date-picker', {
  template: '#datepicker',
  props: {
    value: {
      type: String,
      default: '0520',
    },
  },
  methods: {
    handleInputChange(event) {
      // https://vuejs.org/v2/guide/components-custom-events.html#Customizing-Component-v-model
      this.$emit('input', event.target.value);
    },
  },
});

const data2 = {
  today: {
    "type": "FeatureCollection",
    "id": "0520",
    "features": [{
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [2.34, 48.86] // Left
      },
    }],
  },
  yesterday: {
    "type": "FeatureCollection",
    "id": "0519",
    "features": [{
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [2.35, 48.86] // Right
      },
    }],
  },
};

new Vue({
  el: '#app',
  data() {
    return {
      pickerValue: '0519', // This value rules child components default value.
    };
  },
});
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet-src.js"></script>
<script src="https://unpkg.com/vue2-leaflet@1.0.2/dist/vue2-leaflet.js"></script>

<template id="map-view-2">
  <div id="MapView2">
    <l-map :zoom="11" style="height: 100px;" :center="[48.86, 2.35]">
      <l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
      <l-geo-json :visible="pickerValue === yesterday.geojson.id" :geojson="yesterday.geojson"></l-geo-json>
      <l-geo-json :visible="pickerValue === today.geojson.id" :geojson="today.geojson"></l-geo-json>
    </l-map>
  </div>
</template>

<template id="datepicker">
  <fieldset @change="handleInputChange">
    <legend>Choose a date</legend>
    <input type="radio" name="date" value="0520" id="today" :checked="value === '0520'" />
    <label for="today">Today 0520</label>
    <input type="radio" name="date" value="0519" id="yesterday" :checked="value === '0519'" />
    <label for="yesterday">Yesterday 0519</label>
    <input type="radio" name="date" value="none" id="none" :checked="value === 'none'" />
    <label for="none">None</label>
  </fieldset>
</template>

<div id="app">
  <map-view-2 :picker-value="pickerValue"></map-view-2>
  <date-picker v-model="pickerValue"></date-picker>
</div>

Все это, как говорится, если ваша работа только для прототипа дизайна, даже не демонстрируя свои навыки программирования, то даже Vue, хотя уже довольно простой,может быть излишним для вашей задачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...