Skip to content

Latest commit

 

History

History
251 lines (200 loc) · 6.03 KB

README.md

File metadata and controls

251 lines (200 loc) · 6.03 KB

VEM

Vuejs Easy Maps

Easy but powerful maps for Vuejs2+ with OpenLayers.

Minimal Example

import Vue from 'vue'
import VEM from 'vem'

Vue.use(VEM)

new Vue({
  el: '#app',
  template: '<vem-map><tile-layer /></vem-map>'
})

This creates a map with default controls and an OSM layer.

GeoJSON

The following Vue SFC renders GeoJSON data on top of an OSM layer.

<template>
  <vem-map>
    <tile-layer />
    <vector-layer :source="jsonData" :format="GeoJSON" :fitMapToThisLayer="true" />
  </vem-map>
</template>

<script>
import GeoJSON from 'ol/format/geojson'
import jsonData from './src/assets/data.json'

export default {
  data () {
    return { jsonData }
  }
}
</script>

Notice the fitMapToThisLayer attribute. This sets the center and zoom of the map to exactly fit the extent of the given data in. It should (obviously) only be used once and is only supported on layers with an actual size. VEM tries to nicely abstract away the difference between TileLayer and VectorLayer by automatically deciding which type is needed depending on the given source. Only VectorLayers have an actual size ('extent'), which VEM can automatically fit into the viewport for you.

Raw vs OpenLayers data objects

If a raw data source is given, the format needs to be set via the format attribute. This attribute is not necessary if the object given via source is already an OpenLayers format object:

<template>
  <vem-map>
    <tile-layer />
    <vector-layer :source="features" :fitMapToThisLayer="true" />
  </vem-map>
</template>

<script>
import GeoJSON from 'ol/format/geojson'
import jsonData from './src/assets/data.json'

export default {
  data () {
    return {
      // this might give strange results if your data isn't EPSG:4326 projected
      features: new GeoJSON().readFeatures(jsonData)
    }
  }
}
</script>

It is usually more convenient to use the format parameter because VEM handles the projection for you. If your data is not EPSG:3857 (aka WSG84, aka what you usually have on web-based maps) projected, you can tell VEM using the projection attribute. The default should work in most cases though.

Map click

The map component emits click events:

<template>
  <vem-map @click="onMapClick">
    <tile-layer />
    <vector-layer :source="jsonData" :format="GeoJSON" :fitMapToThisLayer="true" />
  </vem-map>
</template>

<script>
import GeoJSON from 'ol/format/geojson'
import jsonData from './src/assets/data.json'

export default {
  data () {
    return { jsonData }
  },
  methods: {
    onMapClick (ev) {
      console.log('clicked on map', ev)
    }
  }
}
</script>

The emitted object has the following form:

{
  pixel: Array,  // pixel coordinates of click, eg [23.5, 42]
  lonlat: Array, // map coordinates of click, eg [13.5, 52.45]
  pointerEvent: ol.pointer.PointerEvent, // original PointerEvent from OpenLayers
  originalEvent: ol.MapBrowserPointerEvent, // originally emitted event
  feature: ol.Feature // clicked map feature (on vector maps)
}

Zoom state

The map component also supports a temporary zoom state. It is possible to set the zoomToExtent or zoomToFeature attributes to define the area to zoom to. Typical usage would be to zoom on a clicked feature:

<template>
  <vem-map @click="onMapClick" :zoomToFeature="highlightedFeature">
    <tile-layer />
    <vector-layer :source="jsonData" :format="GeoJSON" :fitMapToThisLayer="true" />
  </vem-map>
</template>

<script>
import GeoJSON from 'ol/format/geojson'
import jsonData from './src/assets/data.json'

export default {
  data () {
    return {
      jsonData,
      highlightedFeature: null
    }
  },
  methods: {
    onMapClick (ev) {
      console.log('clicked on map', ev)
      
      if (this.highlightedFeature === ev.feature) {
        this.highlightedFeature = null
      } else {
        this.highlightedFeature = ev.feature
      }
    }
  }
}
</script>

Markers

Markers can be added to the map, using the <map-marker /> component:

<template>
  <vem-map>
    <tile-layer />
    <map-marker name="somewhere-in-berlin" :lon="13.5" :lat="52.5" />
  </vem-map>
</template>

<script>
export default {
  data () {
    return {
    }
  }
}
</script>

All fields are optional. name defaults to "Marker" and the coordinates default to 0.0, 0.0.

Markers are static and not draggable by default, but this can be changed easily:

<template>
  <vem-map>
    <tile-layer />
    <map-marker :lon.sync="longitude" :lat.sync="latitude" :draggable="true" />
  </vem-map>
</template>

<script>
export default {
  data () {
    return {
      // will be kept in sync with the marker position
      longitude: 13.5,
      latitude: 52.5
    }
  }
}
</script>

Resolution boundaries

Markers and VectorLayers can be set to be invisible outside certain resolution or zoom level boundaries:

<template>
  <vem-map>
    <tile-layer />
    <map-marker name="somewhere-in-berlin" :lon="13.5" :lat="52.5" :maxResolution="100" />
  </vem-map>
</template>

<script>
export default {
  data () {
    return {
    }
  }
}
</script>

This marker only becomes visible when the map is zoomed pretty close to Berlin already, somewhere between zoom level 10 and 11.

Because resolution values might not be very obvious. It is also possible to use the zoom value:

<template>
  <vem-map>
    <tile-layer />
    <map-marker name="somewhere-in-berlin" :lon="13.5" :lat="52.5" :minZoom="11" />
  </vem-map>
</template>

<script>
export default {
  data () {
    return {
    }
  }
}
</script>

This hides the marker at zoom levels smaller than 11.

To see this in action, run npm run dev in the source folder and go to http://localhost:4000 .