GithubHelp home page GithubHelp logo

phegman / vue-mapbox-gl Goto Github PK

View Code? Open in Web Editor NEW
268.0 9.0 33.0 1022 KB

A Vue.js component for Mapbox GL JS

License: GNU General Public License v3.0

HTML 4.70% JavaScript 21.59% Vue 60.22% TypeScript 13.49%
vue mapbox-gl-js vuejs2 vue2 javascript

vue-mapbox-gl's Introduction

Mapbox GL JS Vue.js

A simple lightweight (9kb/3kb gzipped) Mapbox GL JS Vue component.

Installation

Yarn

yarn add mapbox-gl-vue

NPM

npm install mapbox-gl-vue --save

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

vue-mapbox-gl's People

Contributors

androidfanatic avatar brianbancroft avatar dannyfeliz avatar lkajan avatar shanligang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-mapbox-gl's Issues

Vue-mapbox-gl and Nuxt?

I'm trying to get this wrapper to work with Nuxt.js. If I try to import mapbox-gl I get a Reference error: self is not defined, because Nuxt.js is trying to render it server-side (as described here: mapbox/mapbox-gl-js#4463). There they solved it by using require in a createMap method and by making a plugin so it doesn't get server side rendered. But none of these solutions seems to be working for this wrapper. Does anyone have any idea?

Better documentation for webpack configuration

I found the documentation to be lacking for including mapbox-gl as a global with Webpack or other transpilers. The suggestion to use window.mapboxgl = require('mapbox-gl') doesn't really work for people using ES6 modules, because it must be included before importing vue-mapbox-gl. Including it in the root js file may work, but I have another suggestion:

I think the cleanest solution is to use shimming, as documented here https://webpack.js.org/guides/shimming/. Maybe a link to this in the docs would make it easier for others using ES6 modules who aren't satisfied binding to window.mapboxgl in their root js file.

I'd be happy to submit a PR, if you'd like. Thanks!

map.fly to

hello,
I'm having some trouble getting the map to center on new coordinates. I can't just map.flyto like the mapbox tutorials say and when I try modifying the prop I pass down it doesn't update the map. How would I go about changing the coords and zoom?
thanks so much,
Royce B.

map-click error

component:

<template lang="html">
  <f7-page>
    <mapbox @map-click="mapClicked"
      access-token="TOKEN"
      :map-options="{
      	style: 'mapbox://styles/mapbox/light-v9',
      	center: [-96, 37.8],
      	zoom: 15
      }">
    </mapbox>
  </f7-page>

</template>

<script>
export default {
  methods: {
    mapClicked(event) {
        // TODO: click is bugged https://github.com/mapbox/mapbox-gl-js/issues/4791
      console.log(event)
    }
  }
}
</script>

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

console.log:

Uncaught TypeError: Cannot read property 'x' of null
    at Point.equals (mapbox-gl.js:53)
    at HTMLDivElement.s (mapbox-gl.js:353)
    at sendClick (framework7.js:9904)
    at HTMLDocument.handleTouchEnd (framework7.js:10090)

Multiple map instances

I tried to create multiple map instances, but vue-mapbox-gl don't display anything when changing the id attribute of the component. The events (onMapLoaded, ..) get called on the first map too, is it possible somehow to have multiple maps at the same time?

Support for not using style:// and/or mapbox servers

I currently use mapbox gl js in a project where we do not use mapbox's servers at all. We use a private tile and glyph font server. Using regular mapbox-gl js a sample config might look like this:

var map = new mapboxgl.Map({
  container: 'map',
  style: {
    glyphs: 'https://myglyphs.cloudfront.net/{fontstack}/{range}.pbf',
    version: 8,
    sources: {
      'osm-tiles': {
        type: 'raster',
        tiles: [
          'https://a.tile.mytiles.com/{z}/{x}/{y}.png',
          'https://b.tile.mytiles.com/{z}/{x}/{y}.png'
        ],
        tileSize: 256
      }
    },
    layers: [{
      id: 'osm-tiles',
      type: 'raster',
      source: 'osm-tiles',
      minzoom: 0,
      maxzoom: 22
    }]
  },
  center: [-122.937613, 50.099706], // starting position
  zoom: 12, // starting zoom
  bearing: 150
});

We are hopefully transitioning to Vue2 and doing something like this:

        <mapbox
          :map-options="{
            style: {
              glyphs: 'https://myglyphs.cloudfront.net/{fontstack}/{range}.pbf',
              version: 8,
              sources: {
                'osm-tiles': {
                  type: 'raster',
                  tiles: [
                    'https://a.tile.mytiles.org/{z}/{x}/{y}.png',
                    'https://b.tile.mytiles.org/{z}/{x}/{y}.png'
                  ],
                  tileSize: 256
                }
              }
            },
            center: [-122.937613, 50.099706],
            zoom: 12,
            bearing: 150
          }"
          :geolocate-control="{
            show: true, 
            position: 'top-right'
          }">
        </mapbox>

The results is a blank page and [Vue warn]: Missing required prop: "accessToken" in the console. Any idea if this is supported and I'm doing it incorrectly, or if there's any chance of support in the near future? I tried keeping a valid access token, but the same config as above, and get a blank page with no errors in the console.

"Missing Mapbox GL JS CSS" when using with Vue-Cli 3

Hi there, and thanks for putting something nice like this together.

I've got an issue where the css isn't loading properly, and I receive the following error:

image

The main difference between how I was able to use this library and the docs is that I use the map in a nested component instead of declaring it in the main object in main.js. Instead, from within a MainBody component, I have the Mapbox component defined from within the export default statement. To be clear, the intent is to have the map cover the entire region that is coloured #aaa, but not the part that is white. (Resolved, but the message persists)

From MainBody.vue:

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

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

Is there something else that I require to do to make the warning message go away, and to allow the map to take the entire right-hand of the screen (as in the screencap)?

ReferenceError: mapboxgl is not defined

Hi,

I followed the steps to setup the component but get a reference error whenever it's mounted.

[Vue warn]: Error in mounted hook:
(found in )

vue.esm.js?65d7:1447 ReferenceError: mapboxgl is not defined
at VueComponent.mapInit (eval at (app.js:2504), :69:4)
at VueComponent.boundFn [as mapInit] (eval at (app.js:727), :126:12)
at VueComponent.mounted (eval at (app.js:2504), :58:20)
at callHook (eval at (app.js:727), :2274:21)
at Object.insert (eval at (app.js:727), :2953:7)
at invokeInsertHook (eval at (app.js:727), :4959:28)
at Vue$3.patch [as patch] (eval at (app.js:727), :5123:5)
at Vue$3.Vue._update (eval at (app.js:727), :2034:19)
at Vue$3.updateComponent (eval at (app.js:727), :2157:10)
at Watcher.get (eval at (app.js:727), :2468:25)

Any idea what could be causing the issue?

I'm using the webpack template from vue-cli.

Thanks,

Pyt

Certain Maki icons not working

I'm attempting to use icons from here but some of them (like parking-garage are not working). Others like harbor work perfectly. Why is that? I'm literally just using the example code in the README (the code right before this) but simply substituting out the icon name.

Accessing map object inside a component method or watcher

I have a menu bar with some check boxes to toggle layers on/off (in App.vue). App.vue has a <router-view/> that renders a component, which is the map view. I am initializing vue-mapbox-gl in this mapview component. I have a watcher setup to watch the state of the check boxes and can fire a function when it changes. I am unable to fire a map.setLayoutProperties, for example, directly from the watcher function. I also tried creating a function inside of MapLoaded (map) {} to call map.setLayoutProperty, but I can't access that function from the watcher, either. I'm sure I'm conceptualizing this wrong, but how can I call map.setLayoutProperty('sat-2014-40cm-tiles', 'visibility', 'none') from a completely different component, watcher or method?

<template>
  <div id="container">
    <div id="map"></div>
    <mapbox
      access-token=''
      :map-options="{
        style: {
          glyphs: 'https://fakefontserver.net/{fontstack}/{range}.pbf',
          version: 8,
          sources: {
            'osm-tiles': {
              type: 'raster',
              tiles: [
              'https://faketileserver.net/{z}/{x}/{y}.png',
              'https://faketileserver.net/{z}/{x}/{y}.png'
              ],
              tileSize: 256
            }
          },
          layers: [{
            id: 'osm-tiles',
            type: 'raster',
            source: 'osm-tiles',
            minzoom: 0,
            maxzoom: 22
          }]
        },
        center: [-122.937613, 50.099706],
        zoom: 12,
        bearing: 150
      }"
      :geolocate-control="{
        show: true, 
        position: 'top-right'
      }"
      @map-load="mapLoaded"
      @map-init="mapInitialized">>
    </mapbox>
  </div>
</template>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
#container {
  width: 100%;
  height: 100vh;
}
#map {
  width: 100%;
  height: 100vh;
}
</style>
<script>
  export default {
    methods: {
      mapInitialized (map) {
        this.map = map
      },
      mapLoaded (map) {
        map.addSource('sat-2014-40cm-tiles', {
          type: 'raster',
          tiles: ['https://otherfaketileserver.net/{z}/{x}/{y}.png'],
          tileSize: 256
        })

        map.addLayer({
          id: 'sat-2014-40cm-tiles',
          type: 'raster',
          source: 'sat-2014-40cm-tiles'
        })
      }
    },
    watch: {
      '$store.state.toggle.imagry.summer_2014_40cm': function (newValue, oldValue) {
        if (newValue === true) {
          map.setLayoutProperty('sat-2014-40cm-tiles', 'visibility', 'visible') // THIS IS NOT WORKING
        } else {
          map.setLayoutProperty('sat-2014-40cm-tiles', 'visibility', 'none') // THIS IS NOT WORKING
        }
      }
    }
  }
</script>

Thanks again for any help you can provide.

router event in PopUp components

I would like to make a router event with a button in the popup component as described here.

With $router:

<template>
  <button @click="$router.push('home')">Go home!</button>
</template>

<script>
export default {
  name: 'PopupContent'
}
</script>

return:

TypeError: _vm.$router is undefined

FullscreenControl

New botton for full screen control.

//Fullscreen Control -- old version
if (this.fullscreenControl.show) {
const fullscreen = new mapboxgl.FullscreenControl();
map.addControl(fullscreen, this.fullscreenControl.position);
}

//Fullscreen Control -- new version
if (this.fullscreenControl.show) {
map.addControl(new mapboxgl.FullscreenControl());
}

Multiple maps in one component or view

The hard coded ID property with the value map (both in the template and the code) makes it impossible to use multiple <mapbox> components in the same parent component or at the same time, e.g. Sample.vue:

<template>
  <div class="sample">
    <mapbox ...></mapbox>
    <mapbox ...></mapbox>
  </div>
</template>

<script>
...
</script>

<style>
...
</style>

The same issue arises when there are multiple maps from different components visible in the same view.

I tried to get it to work with some this._uid-hackery, but that made me do my own component in the end and didn't seem to work well with Mapbox anyways.

'MapboxDraw' is not defined

Im getting 'MapboxDraw' is not defined when using the code snippet provided. Any ideas where I may be going wrong?

`import Mapbox from 'mapbox-gl-vue';
const app = new Vue({
el: '#app',
components: { Mapbox },
methods: {
mapInitialized(map) {
const Draw = new MapboxDraw();

  map.addControl(Draw);
}

}
});`

map.setStyle(...)

Hi,

I've got everything working thus far with your module (fly-to's, searching, pop-ups). I wanted to give users the option of switching from street view to satellite view. I have all the controls working for this, but am running into an issue with the setStyle request.

I saved the map object during init so that I can access it from a button click.

I'm using:

this.map.setStyle("{style: 'mapbox://styles/mapbox/satellite-v9', center: [-96, 37.8], zoom: 3}")

If I set this style as my starting style for the map via :map-options, it works perfectly. When I try and use the above code though, it appears that the style above is being passed directly to our host, when it obviously can't be resolved. Here is the console response in the browser:

ajax.js:81 GET http://my_host_name/%7Bstyle:%20'mapbox://styles/mapbox/satellite-v9',%20center:%20[-96,%2037.8],%20zoom:%203%7D net::ERR_EMPTY_RESPONSE
exports.getJSON @ ajax.js:81
r.loadURL @ style.js:160
e.setStyle @ map.js:919
styleChange @ Map.vue?54d3:99
boundFn @ vue.esm.js?efeb:191
click @ Map.vue?3249:74
invoker @ vue.esm.js?efeb:2004
fn._withTask.fn._withTask @ vue.esm.js?efeb:1802
08:23:23.779 

Any idea what I'm doing wrong?

Thanks

vue-hot-reload-api error

Using this package in https://github.com/meteor-vue/vue-meteor-demo
throws this error while app live-reloads:

"vue-hot-reload-api" in
/Users/igal/work/mapme-story-viewer/node_modules/mapbox-gl-vue/dist/Mapbox.js
(web.browser.legacy)

If you notice problems related to these missing modules, consider running:

meteor npm install --save vue-hot-reload-api

Any idea whats the issue and/or how to fix?

RTL text not supported

Hi, I'm having issues with RTL languages display. Mapbox docs say I should use mapbox-gl-rtl-text.js plugin, which is initialized like this:

mapboxgl.accessToken = 'xxx';
mapboxgl.setRTLTextPlugin('https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.0/mapbox-gl-rtl-text.js');

var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v9',
    center: [44.3763, 33.2788],
    zoom: 11
});

Can you please help me initialize this via vue-mapbox-gl?
thanks!

Layers disappear when style is changed

I have a vue button to change the style, not fully sure if this is the correct way to implement. But the problem is that my layers disappear when the style is changed.

the script toggles the baseMapStyle value with a watch function:

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

var baseMapStyles = [
  { label: 'light', value: 'mapbox://styles/mapbox/light-v9' },
  { label: 'dark', value: 'mapbox://styles/mapbox/dark-v9' },
  { label: 'streets', value: 'mapbox://styles/mapbox/streets-v9' }
]

export default {
  components: { Mapbox },
  data () {
    return {
      baseMapStyles: baseMapStyles,
      baseMapStyle: baseMapStyles[0].value,
      mapOptions: {
        center: [4.3666706, 51.9991184],
        zoom: 12
      }
    }
  },
  methods: {
    mapLoaded (map) {
      map.addLayer({
        'id': 'points',
        'type': 'symbol',
        'source': {
          'type': 'geojson',
          'data': ...
        }
      })
    },
    mapInitialized (map) {
      map.setStyle(this.baseMapStyle)
      this.map = map
    }
  },
  watch: {
    baseMapStyle: function (val) {
      this.map.setStyle(val)
    }
  }
}
</script>

Question: Accessing vue/vuex functions/methods inside of mapbox events

I am having some trouble calling a vue method or a vuex mutation from within a mapbox event. For example, this.$store shows up in the console when the map loads, but is undefined after the map moves.

<template>
  <v-content>
    <div id="map"/>
    <mapbox
      ...
      @map-load="mapLoaded"
      @map-init="mapInitialized">
    </mapbox>
  </v-content>
</template>
<script>
  import Mapbox from 'mapbox-gl-vue'
  import 'mapbox-gl/dist/mapbox-gl.css'

  export default {
    name: 'mapComponent',
    components: { Mapbox },
    methods: {
      mapInitialized (map) {
        this.map = map
      },
      mapLoaded (map) {
        console.log(this.$store)
        map.on('moveend', function () {
          console.log(this.$store)
        })
      }
    }
  }
</script>

Map canvas renders on only 50% of the width of the container!

I am trying MapBox with Vue 2 and I cannot make the map take the full width of the container. It only renders on 50% width of the container.

I have included the files in the head of my index.html as follows:

<script src='https://api.mapbox.com/mapbox-gl-js/v0.40.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v0.40.0/mapbox-gl.css' rel='stylesheet' />

I want the map in a component (Map.vue, I am using vue-router), so here is the code in Map.vue:

Script:
import Mapbox from 'mapbox-gl-vue';

export default {
  components: {
     'mapbox': Mapbox
  }
}

Template:

    <mapbox access-token="pk.eyJ1Ijoic3BlZW5pY3Q....."
    :map-options="{
      style: 'mapbox://styles/mapbox/streets-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>

Style:

#map {
 width: 100%;
 height: 600px;
 position: absolute;
 margin:0;
 z-index:1;
}

I tried everything in the CSS id but it only renders the map in the right half of the width of the container, in the left one only the logo and the controls are displayed while the rest of the area is empty.

screen shot 2017-09-14 at 1 33 21 pm

streets v8 base layer appears to be incompatible now?

The latest updated styles available on Studio do not work with vue-mapbox-gl now. Steps to reproduce:

  • Clone this git
  • Insert your token
  • Load and test map light v9 working
  • Change map style to any of the new styles on Studio, load up, fail with two errors on Safari:

Error: : property expressions not supported
TypeError: undefined is not an object (evaluating 'l.type')

How to bind markers to vue components

How can I use computed properties, or store with mounted components bound to mapbox markers?

I am mounting components to markers in a forEach loop, but I cannot change their content dynamically after mounting.

  const makerContent = Vue.extend(Marker)

  features.forEach(function(feature, index) {
    var parent = document.createElement('div')
        parent.classList.add("mapboxgl-marker")
    var child = document.createElement('div')
        child.classList.add("marker")
    parent.appendChild(child)
     const marker = new mapboxgl.Marker(parent)
     .setLngLat(feature.geometry.coordinates)
     .addTo(self.map)

    new makerContent({
      store: store,
      propsData: {
        feature: feature, 
      }
    }).$mount(child); 
  })

Any suggestions?

extension in single-component files

I'm curious how we may do the pop-up examples in single-component files setting instead of in a global main.js. An example would be much appreciated.

Using vue-cli 3.0 with vue.config.js

I am getting a error trying to install mapbox-gl using webpack. vue-cli 3.0 has changed the webpack structure. How do I get mapbox-gl installed?
The extended question is how do I install other mapbox plugins?

// vue.config.js
module.exports = {
  chainWebpack: config => {
    config
      .plugin('mapboxgl')
      .use(require('mapbox-gl'))
  }
}

ReferenceError: self is not defined
at Object.254 (/home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:509:29)
at s (/home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:1:684)
at /home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:1:735
at Object.252../window (/home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:505:25)
at s (/home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:1:684)
at /home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:1:735
at Object.73.../package.json (/home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:146:75)
at s (/home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:1:684)
at e (/home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:1:855)
at /home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:1:873
at i (/home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:1:150)
at Object. (/home/ubuntu/map1/node_modules/mapbox-gl/dist/mapbox-gl.js:1:386)
at Module._compile (module.js:660:30)
at Object.Module._extensions..js (module.js:671:10)
at Module.load (module.js:573:32)
at tryModuleLoad (module.js:513:12)

fails on laravel 5.4

Hi,

I've been trying to implement this on laravel 5.4, and following the instructions carefully. However, I can't seem to pull it off. When I compile using webpack, it does not seem to go through.

Any workaround for this?

Container 'Map' Not Found

I'm receiving the container 'map' not found error. CSS styles are included in the head. Am I missing something?

image

<script>
  import Mapbox from 'mapbox-gl-vue';
  const mapboxgl = require('mapbox-gl');

  export default {
    props: {
      accessToken: {
        Type: String,
        Required: true
      },
      mapOptions: {
        Type: Object,
        Required: true
      },
    },
    components: {
      'mapbox': Mapbox
    }
  }
</script>

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

map-mouse-move is never run

The popup shown here works excelent! But running the exact code, the mouse-over does not work.

<mapbox 
    id="map"
    ref="map"
    access-token="pk.eyJ1Ijoiandkb2JrZW4iLCJhIjoiY2ppMDZvNDZxMDRueDNxcWJuamltZzRvdCJ9.bERPBWM1BXJmMwHI0Uv5-w"
    :map-options="mapOptions"
    @map-mouse-move="mapMouseMoved">
...
methods: {
  ...
  mapMouseMoved(map, e) {
    console.log('moved!')
  },
  ...

I included the @map-mouse-move="mapMouseMoved" in the mapbox component but the method mapMouseMoved is never run.

insert popup failed - vue as module

I got this warning on popup. I used the module bundler way, not the cdn link.

You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

I tried to extract the popupcontent component in .vue component but failed to insert it into dom.
It should be possible since you wrote it in doc.

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

Could you show this way ? thanks for help

Marker popups on mouseover.

Although there is API documentation for Popup On Hover, it is unclear how to make this happen when you don't use that particular technique to create layers, etc.

As it stands, I use the following to create markers with related popups and trigger events:

...
const popup = new mapboxgl.Popup({...})

const marker = new mapboxgl.Marker()
            .setPopup(popup)
            .setLngLat({lng: custom_longitude, lat: custom_latitude})
            .addTo(map)

          marker.getElement().addEventListener('mouseenter',(e)=>{
            if(!marker.getPopup().isOpen()){
              marker.togglePopup()
            }
          })

          marker.getElement().addEventListener('mouseleave',(e)=>{
            if(marker.getPopup().isOpen()){
              marker.togglePopup()
            }
          })

However, there is a great deal of intermittent flicker and the popups (understandably) don't stick around to be clicked (in the event that they contain URLs) because hovering over them doesn't counteract mouseleave. I would imagine that there would/should be an option for popupOnHover or something like that without having to write any code. What am I missing? πŸ€”

Unspected behaviour on @map-load

Hello.
First of all thanks for the component its been very useful ;)

But i've come against a weird bug to say the least.
My code is the following.

<template>
  <div id="map" class="map">
        <mapbox
          access-token=""
          :map-options="{
            style: 'mapbox://styles/mapbox/streets-v9',
            center: [-96, 37.8],
            zoom: 9
          }"
          @map-load="mapLoaded"></mapbox>
      <button @click="flyTo">Center</button>
  </div>
</template>

<script>

export default {
  data () {
    return {
      map: {}
    }
  },
  methods: {
    mapLoaded (map) {
      this.map = map
    },
    flyTo () {
      this.map.flyTo({
        center: [4.498558399999999, 51.9220879]
      })
    }
  }
}
</script

Nothing special. But when interacting with the map it does this:
https://youtu.be/cY-Br7KLVAA

If I remove the @map-load event it works correctly.
I think that making map a vue data key is adding the reactivity ?
Any ideas?

Thanks.

Problem using Shimming/Universal Import

Hello,
The instructions say to add the plugin to webpack.config.js, but I am using Vuetify/webpack-advanced and this file doesn't exist. Does this import need to be in the dev.conf.js and prod.conf.js in this case? I've been experimenting, but nothing I have tried has worked. Let me know if this makes sense or if you need more information. Thanks.

Passing the map object to a click method outside of the map scope

I would like to trigger a popup on the map from a click event on an element that is not the map. Inside my setView method I would like to call this.addPopUp(map, e); but i have no access to the map object here.

ul
   li(:class="{ 'is-active': view === 'progress' }")
     a(@click="setView('progress')")
     span Progress

warning using vue-mapbox-gl on Quasar Framework

I'm imported vue-mapbox-gl and when see debug console a message appears, I can ommit it or have to do something? the map is visible and seems to work well.

thanks.

Message:

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

found in

--->
at src\components\Lista.vue

at src\App.vue

<mapbox></mapbox> must be room element of template

The <mapbox> tag must be the root element of a template, which makes overlaying other elements (buttons, images, etc) nearly impossible. This does not work, for example.

<template>
  <div>
    <mapbox .... >
    </mapbox>
    <button class="absolute_btm_right">A button!</button>
  </div>
</template>

How to add markers to the map

Hello, I noticed in one of the closed issues, it was possible to add markers which are connected to the Vue data field. I'm working with an app that only needs static markers created when the map loads, but I couldn't find the method to actually create these elements in the documentation for this module or through research online. Could you possibly direct me to a source that covers this process?

Vue popups - undefined parent

In one of the given examples you're opening a Vue component (by extending) from a popup. I'm trying to open a modal in the main window (through this https://www.npmjs.com/package/vue-js-modal) through a popup done as your example. Thought it could be done either by emitting an event (like this https://jsfiddle.net/dangvanthanh/3m6s54qx/) or by finding the parent of the Vue popup component. However, it seems like the popup component has no parent and somehow is standing totally by itself. Why is that? What is the relationship between the map component, the popup component and the "larger" component (i.e. the actual view component that export default {} "talks" to)? Sorry if my lingo is a bit weird.
Seems like it can't by done by doing a new Vue({}) or Vue.component({}) either instead of a Vue.extend({}). What Vue component is it that you're extending through this example?

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.