npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mapbox-gl-vue

v2.0.4

Published

A Vue.js component for Mapbox GL js

Downloads

4,316

Readme

Mapbox GL JS Vue.js

A simple lightweight (9kb/3kb gzipped) Mapbox GL JS Vue component. Great for quick prototyping or smaller projects. For larger projects VueMapbox may be a better fit.

Demo

Installation

Yarn

yarn add mapbox-gl-vue

NPM

npm install mapbox-gl-vue --save

Vue CDN

Download latest vue-mapbox-gl.min.js from https://github.com/phegman/vue-mapbox-gl/releases

Include using a <script> tag

<script src="vue-mapbox-gl.min.js"></script>

Including Mapbox GL JS

This package does not include the Mapbox GL JS and CSS files. See Mapbox GL JS installation guide here: https://www.mapbox.com/install/js/

Importing Mapbox GL JS with Webpack

If you decide to include Mapbox GL JS by installing it with Yarn/NPM you should use Shimming for it to work correctly.

webpack.config.js

const webpack = require('webpack')

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

Projects setup with Vue CLI 3:

vue.config.js

const webpack = require('webpack')

module.exports = {
  configureWebpack: {
    plugins: [
      new webpack.ProvidePlugin({
        mapboxgl: 'mapbox-gl',
      }),
    ],
  },
}

Setup

In the file you will be including the component:

<script>
import Mapbox from 'mapbox-gl-vue'

export default {
  components: { Mapbox },
}
</script>

In your template block:

<template>
  <div id="app">
    <mapbox
      access-token="your access token"
      :map-options="{
        style: 'mapbox://styles/mapbox/light-v9',
        center: [-96, 37.8],
        zoom: 3,
      }"
    />
  </div>
</template>

CSS

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

<style>
#map {
  width: 100%;
  height: 500px;
}
</style>

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: MapboxOptions
Required: true

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

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


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

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


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

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


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

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


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

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


attribution-control
Type: AttributionControlOptions
Required: false
Default: { show: false, position: 'top-right' }

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

Example

<template>
  <div id="app">
    <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',
      }"
    />
  </div>
</template>

Map Events

@map-init : This event is fired when the map is initialized. It can be used to integrate plugins.

All Mapbox GL JS events are available for use. List of events here: https://docs.mapbox.com/mapbox-gl-js/api/#map.event:resize

Map events can be used by adding the @map- prefix to the beginning of the Mapbox event name. For example for the click event @map-click can be used. All events are passed the mapboxgl Map instance as the first parameter and, if the event has one, the MapboxEvent as the second parameter.

For events that support specifying a layerId as documented here https://docs.mapbox.com/mapbox-gl-js/api/#map#on the layerId can be specified by using a colon to separate the event from the layerId. For example if you have a layer with an id of points the click event can be registered like so: @map-click:points

Geolocation Events

Geolocation events are available for use by adding the @geolocate- prefix to the beginning of the Mapbox event name. A list of Geolocation events can be found here: https://docs.mapbox.com/mapbox-gl-js/api/#geolocatecontrol.event:geolocate

Example

App.vue

<template>
  <div id="app">
    <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',
      }"
      @map-load="loaded"
      @map-zoomend="zoomend"
      @map-click:points="clicked"
      @geolocate-error="geolocateError"
      @geolocate-geolocate="geolocate"
    />
  </div>
</template>

<script>
import Mapbox from 'mapbox-gl-vue'

export default {
  components: { Mapbox },
  methods: {
    loaded(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',
        },
      })
    },
    zoomend(map, e) {
      console.log('Map zoomed')
    },
    clicked(map, e) {
      const title = e.features[0].properties.title
      console.log(title)
    },
    geolocateError(control, positionError) {
      console.log(positionError)
    },
    geolocate(control, position) {
      console.log(
        `User position: ${position.coords.latitude}, ${position.coords.longitude}`
      )
    },
  },
}
</script>

<style>
#map {
  width: 100%;
  height: 500px;
}
</style>

Plugins

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:

<template>
  <div id="app">
    <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"
    />
  </div>
</template>

<script>
import Mapbox from 'mapbox-gl-vue'

export default {
  components: { Mapbox },
  methods: {
    initialized(map) {
      const Draw = new MapboxDraw()
      map.addControl(Draw)
    },
  },
}
</script>

<style>
#map {
  width: 100%;
  height: 500px;
}
</style>

Popups

Popups can be a bit 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. See below for one approach to solving this problem.

App.vue

<template>
  <div id="app">
    <mapbox
      access-token="your access token"
      :map-options="{
        style: 'mapbox://styles/mapbox/light-v9',
        center: [-96, 37.8],
        zoom: 3,
      }"
      @map-load="loaded"
      @map-click:points="clicked"
      @map-mouseenter:points="mouseEntered"
      @map-mouseleave:points="mouseLeft"
    />
  </div>
</template>

<script>
import Mapbox from 'mapbox-gl-vue'
import PopupContent from './PopupContent.vue'

export default {
  components: { Mapbox },
  methods: {
    loaded(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',
        },
      })
    },
    clicked(map, e) {
      if (e.features) {
        const coordinates = e.features[0].geometry.coordinates.slice()

        // Ensure that if the map is zoomed out such that multiple
        // copies of the feature are visible, the popup appears
        // over the copy being pointed to.
        while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
          coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360
        }

        new mapboxgl.Popup()
          .setLngLat({ lng: coordinates[0], lat: coordinates[1] })
          .setHTML('<div id="vue-popup-content"></div>')
          .addTo(map)

        new PopupContent({
          propsData: { feature: e.features[0] },
        }).$mount('#vue-popup-content')
      }
    },
    mouseEntered(map) {
      map.getCanvas().style.cursor = 'pointer'
    },
    mouseLeft(map) {
      map.getCanvas().style.cursor = ''
    },
  },
}
</script>

<style>
#map {
  width: 100%;
  height: 500px;
}
</style>

PopupContent.vue

<template>
  <div>
    <h3>{{ feature.properties.title }}</h3>
    <button @click="popupClicked">Learn more</button>
  </div>
</template>

<script>
import Vue from 'vue'
export default Vue.extend({
  props: {
    feature: {
      required: true,
      type: Object,
    },
  },
  methods: {
    popupClicked() {
      alert('Learn more clicked')
    },
  },
})
</script>

Development

Install dependencies

yarn install

Start development server

This will start a dev server with HMR at localhost:8080.

ACCESS_TOKEN=yourAccessToken yarn dev

Linting

Please make sure all your code passes linting before opening a PR.

yarn lint