Coder Social home page Coder Social logo

vue-mapbox-gl's Introduction

Mapbox GL JS Vue.js

A Vue.js Mapbox component.

Installation

NPM

npm install mapbox-gl-vue --save

Yarn

yarn add mapbox-gl-vue

Including Mapbox GL JS

This package does not include the Mapbox GL JS and CSS files. See Mapbox GL JS quickstart guide here: https://www.mapbox.com/mapbox-gl-js/api/

Importing Mapbox GL JS with Webpack

If you decide to include Mapbox GL JS by importing it with Webpack you should use Shimming for it to work correctly. Add the below to your webpack.config.js file:

plugins: [
  new webpack.ProvidePlugin({
    mapboxgl: 'mapbox-gl'
  })
]

Usage

Setup

In the file you will be including the component:

import Mapbox from 'mapbox-gl-vue';
const app = new Vue({
  el: '#app',
  components: { Mapbox },
]);

In your HTML file:

<!-- #app -->
<div id="app">
  <mapbox></mapbox>
</div>

CSS

CSS needs to be added for the map to show up. The #map container needs a height and a width. Example:

#map {
  width: 100%;
  height: 500px;
}

Props

Vue.js Documentation https://vuejs.org/v2/guide/components.html#Props

access-token
Type: String
Required: True

Your access token is required for Mapbox to work. It can be obtained in the Mapbox Studio dashboard


map-options
Type: Object
Required: True

Overview of available Mapbox options can be found here: https://www.mapbox.com/mapbox-gl-js/api/#map

mapOptions.container will default to 'map' (giving the container and id of 'map'). If you want to change this or use multiple map components on the same page simply set mapOptions.container.


nav-control
Type: Object
Required: False
Default: { show: true, position: 'top-right' }

More information about navigation control here: https://www.mapbox.com/mapbox-gl-js/api/#navigationcontrol


geolocate-control
Type: Object
Required: False
Default: { show: false, position: 'top-left', options: {} }

More information about geolocate control here: https://www.mapbox.com/mapbox-gl-js/api/#geolocatecontrol


scale-control
Type: Object
Required: False
Default: { show: false, position: 'top-left', options: {} }

More information about scale control here: https://www.mapbox.com/mapbox-gl-js/api/#scalecontrol


fullscreen-control
Type: Object
Required: False
Default: { show: false, position: 'top-right' }

More information about full screen control here: https://www.mapbox.com/mapbox-gl-js/api/#fullscreencontrol

Example

<mapbox 
access-token="your access token"
:map-options="{
  style: 'mapbox://styles/mapbox/light-v9',
  center: [-96, 37.8],
  zoom: 3
}"
:geolocate-control="{
  show: true, 
  position: 'top-left'
}"
:scale-control="{
  show: true,
  position: 'top-left'
}"
:fullscreen-control="{
  show: true,
  position: 'top-left'
}">
</mapbox>

Events

All Mapbox GL JS events are available for use. For a list of events look here: https://www.mapbox.com/mapbox-gl-js/api/#map.event:resize

Events can be used by prepending map- to the beginning of the Mapbox event. For example for the Mapbox click event @map-click can be used.

All events are passed the map object and the event if it has one.

Example:

HTML File:

<!-- #app -->
<div id="app">
  <mapbox
    @map-load="mapLoaded"
    @map-click="mapClicked"
  >
  </mapbox>
</div>

Main js file:

const app = new Vue({
  el: '#app',
  components: { Mapbox },
  methods: {
    mapLoaded(map) {
      map.addLayer({
        'id': 'points',
        'type': 'symbol',
        'source': {
          'type': 'geojson',
          'data': {
            'type': 'FeatureCollection',
            'features': [{
              'type': 'Feature',
              'geometry': {
                'type': 'Point',
                'coordinates': [-77.03238901390978, 38.913188059745586]
              },
              'properties': {
                'title': 'Mapbox DC',
                'icon': 'monument'
              }
            }, {
              'type': 'Feature',
              'geometry': {
                'type': 'Point',
                'coordinates': [-122.414, 37.776]
              },
              'properties': {
                'title': 'Mapbox SF',
                'icon': 'harbor'
              }
            }]
          }
        },
        'layout': {
          'icon-image': '{icon}-15',
          'text-field': '{title}',
          'text-font': ['Open Sans Semibold', 'Arial Unicode MS Bold'],
          'text-offset': [0, 0.6],
          'text-anchor': 'top'
        }
      });
    },
    mapClicked(map, e) {
      alert('Map Clicked!');
    },
  }
]);

map-init : This event is fired when the map is initialized. It can be used to integrate plugins such as Mapbox Draw.

Plugins

The "User Interface" plugins (https://www.mapbox.com/mapbox-gl-js/plugins/) can be integrated using the map-init event that is fired when Mapbox is initialized. Below is an example:

<mapbox
  access-token="your access token"
  :map-options="{
      style: 'mapbox://styles/mapbox/light-v9',
      center: [-96, 37.8],
      zoom: 3
  }"
  :geolocate-control="{
      show: true, 
      position: 'top-left'
  }"
  :scale-control="{
      show: true,
      position: 'top-left'
  }"
  :fullscreen-control="{
      show: true,
      position: 'top-left'
  }"
  @map-init="mapInitialized">
</mapbox>
import Mapbox from 'mapbox-gl-vue';
const app = new Vue({
  el: '#app',
  components: { Mapbox },
  methods: {
    mapInitialized(map) {
      const Draw = new MapboxDraw();

      map.addControl(Draw);
    }
  }
]);

Popups

Popups can be a little tricky if you are trying to use Vue directives inside the popup content. This is because the popups are added to the DOM by Mapbox and not compiled by Vue. To get around this you can extend Vue to create a new Component and then mount that to the popup. Below is an example:

Main js file:

const app = new Vue({
  el: '#app',
  components: { Mapbox },
  methods: {
    mapLoaded(map) {
      map.addLayer({
        'id': 'points',
        'type': 'symbol',
        'source': {
          'type': 'geojson',
          'data': {
            'type': 'FeatureCollection',
            'features': [{
              'type': 'Feature',
              'geometry': {
                'type': 'Point',
                'coordinates': [-77.03238901390978, 38.913188059745586]
              },
              'properties': {
                'title': 'Mapbox DC',
                'icon': 'monument'
              }
            }, {
              'type': 'Feature',
              'geometry': {
                'type': 'Point',
                'coordinates': [-122.414, 37.776]
              },
              'properties': {
                'title': 'Mapbox SF',
                'icon': 'harbor'
              }
            }]
          }
        },
        'layout': {
          'icon-image': '{icon}-15',
          'text-field': '{title}',
          'text-font': ['Open Sans Semibold', 'Arial Unicode MS Bold'],
          'text-offset': [0, 0.6],
          'text-anchor': 'top'
        }
      });
    },
    mapClicked(map, e) {
      this.addPopUp(map, e);
    },
    mapMouseMoved(map, e) {
      const features = map.queryRenderedFeatures(e.point, {
        layers: ['points']
      });
      map.getCanvas().style.cursor = (features.length) ? 'pointer' : '';
    },
    addPopUp(map, e) {
      const features = map.queryRenderedFeatures(e.point, {
        layers: ['points']
      });
      if (!features.length) {
        return;
      }

      const feature = features[0];

      const popupContent = Vue.extend({
        template: '<button @click="popupClicked">Click Me!</button>',
        methods: {
          popupClicked() {
            alert('Popup Clicked!');
          },
        }
      });

      // Populate the popup and set its coordinates
      // based on the feature found.
      const popup = new mapboxgl.Popup()
        .setLngLat(feature.geometry.coordinates)
        .setHTML('<div id="vue-popup-content"></div>')
        .addTo(map);

      new popupContent().$mount('#vue-popup-content');
    }
  }
});

The popupContent component can also be extracted to a separate .vue file to clean things up.

Support

Please open an issue for support.

Contributing

Please contribute using Github Flow. Create a branch, add commits, and open a pull request.

vue-mapbox-gl's People

Contributors

dannyfeliz avatar

Watchers

James Cloos avatar Mathieu de Gouville avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.