A set of composable components for easy use of Google Maps in your Vue 3 projects.

Related tags

Map vue3-google-map
Overview

vue3-google-map

Composable components for easy use of Google Maps with Vue 3

vue3-google-map offers a set of composable components for easy use of Google Maps in your Vue 3 projects.

Installation

NPM

npm install vue3-google-map
# OR
yarn add vue3-google-map

CDN

Include the following script tag in your index.html (make sure to include it after Vue 3).

<script src="https://unpkg.com/vue3-google-map">script>

Usage

Please refer to the documentation

Development Setup

Clone the repo and checkout the develop branch.

# install deps
yarn install

# build dist files
yarn build

# run develpment server and serve basic example
yarn dev

# serve docs
yarn docs

Contribution

All contributions are welcome. Before submitting a PR though it would be nice if you created an issue explaining what you want to acheive and why.

License

MIT

Comments
  • Issue when generating app with v0.7.2+

    Issue when generating app with v0.7.2+

    My application build fails with the latest release (0.7.6). Here is my build log:

     ERROR  Failed to compile with 1 error                                                            4:03:31 PM
    
     error  in ./node_modules/vue3-google-map/dist/es/index.js
    
    Module parse failed: Unexpected token (1:6510)
    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
    > import{ref as e,defineComponent as t,provide as l,onBeforeUnmount as o,onMounted as r,toRef as s,watch as i,openBlock as a,createBlock as n,createVNode as y,mergeProps as p,renderSlot as c,inject as f,Fragment as m,createCommentVNode as u,withDirectives as d,vShow as g}from"vue";var T=function e(t,l){if(t===l)return!0;if(t&&l&&"object"==typeof t&&"object"==typeof l){if(t.constructor!==l.constructor)return!1;var o,r,s;if(Array.isArray(t)){if((o=t.length)!=l.length)return!1;for(r=o;0!=r--;)if(!e(t[r],l[r]))return!1;return!0}if(t.constructor===RegExp)return t.source===l.source&&t.flags===l.flags;if(t.valueOf!==Object.prototype.valueOf)return t.valueOf()===l.valueOf();if(t.toString!==Object.prototype.toString)return t.toString()===l.toString();if((o=(s=Object.keys(t)).length)!==Object.keys(l).length)return!1;for(r=o;0!=r--;)if(!Object.prototype.hasOwnProperty.call(l,s[r]))return!1;for(r=o;0!=r--;){var i=s[r];if(!e(t[i],l[i]))return!1}return!0}return t!=t&&l!=l};class h{constructor({apiKey:e,channel:t,client:l,id:o="__googleMapsScriptId",libraries:r=[],language:s,region:i,version:a,mapIds:n,nonce:y,retries:p=3,url:c="https://maps.googleapis.com/maps/api/js"}){if(this.CALLBACK="__googleMapsCallback",this.callbacks=[],this.done=!1,this.loading=!1,this.errors=[],this.version=a,this.apiKey=e,this.channel=t,this.client=l,this.id=o||"__googleMapsScriptId",this.libraries=r,this.language=s,this.region=i,this.mapIds=n,this.nonce=y,this.retries=p,this.url=c,h.instance){if(!T(this.options,h.instance.options))throw new Error(`Loader must not be called again with different options. ${JSON.stringify(this.options)} !== ${JSON.stringify(h.instance.options)}`);return h.instance}h.instance=this}get options(){return{version:this.version,apiKey:this.apiKey,channel:this.channel,client:this.client,id:this.id,libraries:this.libraries,language:this.language,region:this.region,mapIds:this.mapIds,nonce:this.nonce,url:this.url}}createUrl(){let e=this.url;return e+=`?callback=${this.CALLBACK}`,this.apiKey&&(e+=`&key=${this.apiKey}`),this.channel&&(e+=`&channel=${this.channel}`),this.client&&(e+=`&client=${this.client}`),this.libraries.length>0&&(e+=`&libraries=${this.libraries.join(",")}`),this.language&&(e+=`&language=${this.language}`),this.region&&(e+=`&region=${this.region}`),this.version&&(e+=`&v=${this.version}`),this.mapIds&&(e+=`&map_ids=${this.mapIds.join(",")}`),e}load(){return this.loadPromise()}loadPromise(){return new Promise(((e,t)=>{this.loadCallback((l=>{l?t(l):e()}))}))}loadCallback(e){this.callbacks.push(e),this.execute()}setScript(){if(document.getElementById(this.id))return void this.callback();const e=this.createUrl(),t=document.createElement("script");t.id=this.id,t.type="text/javascript",t.src=e,t.onerror=this.loadErrorCallback.bind(this),t.defer=!0,t.async=!0,this.nonce&&(t.nonce=this.nonce),document.head.appendChild(t)}deleteScript(){const e=document.getElementById(this.id);e&&e.remove()}resetIfRetryingFailed(){const e=this.retries+1;this.done&&!this.loading&&this.errors.length>=e&&(this.deleteScript(),this.done=!1,this.loading=!1,this.errors=[],this.onerrorEvent=null)}loadErrorCallback(e){if(this.errors.push(e),this.errors.length<=this.retries){const e=this.errors.length*Math.pow(2,this.errors.length);console.log(`Failed to load Google Maps script, retrying in ${e} ms.`),setTimeout((()=>{this.deleteScript(),this.setScript()}),e)}else this.onerrorEvent=e,this.callback()}setCallback(){window.__googleMapsCallback=this.callback.bind(this)}callback(){this.done=!0,this.loading=!1,this.callbacks.forEach((e=>{e(this.onerrorEvent)})),this.callbacks=[]}execute(){window.google&&window.google.maps&&window.google.maps.version&&(console.warn("Google Maps already loaded outside @googlemaps/js-api-loader.This may result in undesirable behavior as options and script parameters may not match."),this.callback()),this.resetIfRetryingFailed(),this.done?this.callback():this.loading||(this.loading=!0,this.setCallback(),this.setScript())}}const b=Symbol("api"),v=Symbol("map"),k=e(null),C=["bounds_changed","center_changed","click","dblclick","drag","dragend","dragstart","heading_changed","idle","maptypeid_changed","mousemove","mouseout","mouseover","projection_changed","resize","rightclick","tilesloaded","tilt_changed","zoom_changed"],w=["animation_changed","click","dblclick","rightclick","dragstart","dragend","drag","mouseover","mousedown","mouseout","mouseup","draggable_changed","clickable_changed","contextmenu","cursor_changed","flat_changed","rightclick","zindex_changed","icon_changed","position_changed","shape_changed","title_changed","visible_changed"],x=["click","dblclick","drag","dragend","dragstart","mousedown","mousemove","mouseout","mouseover","mouseup","rightclick"],_=x,S=x.concat(["bounds_changed"]),O=x.concat(["center_changed","radius_changed"]);var P=t({props:{apiKey:{type:String,default:""},libraries:Array,region:String,language:String,backgroundColor:String,center:Object,clickableIcons:{type:Boolean,default:void 0},controlSize:Number,disableDefaultUi:{type:Boolean,default:void 0},disableDoubleClickZoom:{type:Boolean,default:void 0},draggable:{type:Boolean,default:void 0},draggableCursor:String,draggingCursor:String,fullscreenControl:{type:Boolean,default:void 0},fullscreenControlPosition:String,gestureHandling:String,heading:Number,keyboardShortcuts:{type:Boolean,default:void 0},mapTypeControl:{type:Boolean,default:void 0},mapTypeControlOptions:Object,mapTypeId:{type:[Number,String]},maxZoom:Number,minZoom:Number,noClear:{type:Boolean,default:void 0},panControl:{type:Boolean,default:void 0},panControlPosition:String,restriction:Object,rotateControl:{type:Boolean,default:void 0},rotateControlPosition:String,scaleControl:{type:Boolean,default:void 0},scaleControlStyle:Number,scrollwheel:{type:Boolean,default:void 0},streetView:Object,streetViewControl:{type:Boolean,default:void 0},streetViewControlPosition:String,styles:Array,tilt:Number,zoom:Number,zoomControl:{type:Boolean,default:void 0},zoomControlPosition:String},emits:C,setup(t,{emit:a}){const n=e(null),y=e(!1),p=e(null),c=e(null);l(v,p),l(b,c);const f=()=>{const e={backgroundColor:t.backgroundColor,center:t.center,clickableIcons:t.clickableIcons,controlSize:t.controlSize,disableDefaultUI:t.disableDefaultUi,disableDoubleClickZoom:t.disableDoubleClickZoom,draggable:t.draggable,draggableCursor:t.draggableCursor,draggingCursor:t.draggingCursor,fullscreenControl:t.fullscreenControl,fullscreenControlOptions:t.fullscreenControlPosition?{position:c.value?.ControlPosition[t.fullscreenControlPosition]}:{},gestureHandling:t.gestureHandling,heading:t.heading,keyboardShortcuts:t.keyboardShortcuts,mapTypeControl:t.mapTypeControl,mapTypeControlOptions:t.mapTypeControlOptions,mapTypeId:t.mapTypeId,maxZoom:t.maxZoom,minZoom:t.minZoom,noClear:t.noClear,panControl:t.panControl,panControlOptions:t.panControlPosition?{position:c.value?.ControlPosition[t.panControlPosition]}:{},restriction:t.restriction,rotateControl:t.rotateControl,rotateControlOptions:t.rotateControlPosition?{position:c.value?.ControlPosition[t.rotateControlPosition]}:{},scaleControl:t.scaleControl,scaleControlOptions:t.scaleControlStyle?{style:t.scaleControlStyle}:{},scrollwheel:t.scrollwheel,streetView:t.streetView,streetViewControl:t.streetViewControl,streetViewControlOptions:t.streetViewControlPosition?{position:c.value?.ControlPosition[t.streetViewControlPosition]}:{},styles:t.styles,tilt:t.tilt,zoom:t.zoom,zoomControl:t.zoomControl,zoomControlOptions:t.zoomControlPosition?{position:c.value?.ControlPosition[t.zoomControlPosition]}:{}};return Object.keys(e).forEach((t=>void 0===e[t]&&delete e[t])),e};return o((()=>{p.value&&c.value?.event.clearInstanceListeners(p.value)})),r((()=>{try{k.value=new h({apiKey:t.apiKey,version:"weekly",libraries:t.libraries||["places"],language:t.language,region:t.region})}catch(e){console.error(e)}finally{k.value.load().then((()=>{const{Map:e}=c.value=google.maps;p.value=new e(n.value,f()),C.forEach((e=>{p.value?.addListener(e,(t=>a(e,t)))})),y.value=!0;const l=Object.keys(t).filter((e=>!["center","zoom"].includes(e))).map((e=>s(t,e)));i([()=>t.center,()=>t.zoom,...l],(([e,t],[l,o])=>{const{center:r,zoom:s,...i}=f();p.value?.setOptions(i),void 0!==t&&t!==o&&p.value?.setZoom(t),e&&(l&&e.lng===l.lng&&e.lat===l.lat||p.value?.panTo(e))}))}))}})),{mapRef:n,ready:y,map:p,api:c}}});P.render=function(e,t,l,o,r,s){return a(),n("div",null,[y("div",p(e.$attrs,{ref:"mapRef"}),null,16),c(e.$slots,"default")])},P.__file="src/components/GoogleMap.vue";const j=(t,l,o,r)=>{let s=null;const a=e(null),n=f(v,e(null)),y=f(b,e(null));return i([n,o],((e,i,p)=>{n.value&&y.value&&(a.value=s=new y.value[t]({...o.value,map:n.value}),l.forEach((e=>{s?.addListener(e,(t=>r(e,t)))}))),p((()=>{s&&(y.value?.event.clearInstanceListeners(s),s.setMap(null))}))}),{immediate:!0}),{component:a}};var I=t({props:{options:{type:Object,required:!0}},emits:w,setup(e,{emit:t}){const l=s(e,"options");return{marker:j("Marker",w,l,t)}},render:()=>null}),z=t({props:{options:{type:Object,required:!0}},emits:x,setup(e,{emit:t}){const l=s(e,"options");return{polyline:j("Polyline",x,l,t)}},render:()=>null}),B=t({props:{options:{type:Object,required:!0}},emits:_,setup(e,{emit:t}){const l=s(e,"options");return{polygon:j("Polygon",_,l,t)}},render:()=>null}),E=t({props:{options:{type:Object,required:!0}},emits:S,setup(e,{emit:t}){const l=s(e,"options");return{rectangle:j("Rectangle",S,l,t)}},render:()=>null}),$=t({props:{options:{type:Object,required:!0}},emits:O,setup(e,{emit:t}){const l=s(e,"options");return{circle:j("Circle",O,l,t)}},render:()=>null}),M=t({props:{position:{type:String,required:!0},index:Number},emits:["content:loaded"],setup(t,{emit:l}){const o=e(null),r=f(v,e(null)),s=f(b,e(null)),a=e(!1),n=i(s,(()=>{s.value&&r.value&&(s.value.event.addListenerOnce(r.value,"tilesloaded",(()=>{a.value=!0,l("content:loaded")})),n())}));return i([r,()=>t.position,()=>t.index],((e,[l,i],a)=>{r.value&&s.value&&(t.index&&(o.value.index=t.index),o.value&&r.value.controls[s.value.ControlPosition[t.position]].push(o.value)),a((()=>{if(r.value&&s.value&&i){let e;r.value.controls[s.value.ControlPosition[i]].forEach(((t,l)=>{t===o.value&&(e=l)})),e&&r.value.controls[s.value.ControlPosition[i]].removeAt(e)}}))}),{immediate:!0}),{controlRef:o,showContent:a}}});const K={ref:"controlRef"};M.render=function(e,t,l,o,r,s){return a(),n(m,null,[u("\n    v-show must be used instead of v-if otherwise there\n    would be no rendered content pushed to the map controls\n  "),d(y("div",K,[c(e.$slots,"default")],512),[[g,e.showContent]])],2112)},M.__file="src/components/CustomControl.vue";const N=[{elementType:"geometry",stylers:[{color:"#1d2c4d"}]},{elementType:"labels.text.fill",stylers:[{color:"#8ec3b9"}]},{elementType:"labels.text.stroke",stylers:[{color:"#1a3646"}]},{featureType:"administrative.country",elementType:"geometry.stroke",stylers:[{color:"#4b6878"}]},{featureType:"administrative.land_parcel",elementType:"labels.text.fill",stylers:[{color:"#64779e"}]},{featureType:"administrative.province",elementType:"geometry.stroke",stylers:[{color:"#4b6878"}]},{featureType:"landscape.man_made",elementType:"geometry.stroke",stylers:[{color:"#334e87"}]},{featureType:"landscape.natural",elementType:"geometry",stylers:[{color:"#023e58"}]},{featureType:"poi",elementType:"geometry",stylers:[{color:"#283d6a"}]},{featureType:"poi",elementType:"labels.text.fill",stylers:[{color:"#6f9ba5"}]},{featureType:"poi",elementType:"labels.text.stroke",stylers:[{color:"#1d2c4d"}]},{featureType:"poi.park",elementType:"geometry.fill",stylers:[{color:"#023e58"}]},{featureType:"poi.park",elementType:"labels.text.fill",stylers:[{color:"#3C7680"}]},{featureType:"road",elementType:"geometry",stylers:[{color:"#304a7d"}]},{featureType:"road",elementType:"labels.text.fill",stylers:[{color:"#98a5be"}]},{featureType:"road",elementType:"labels.text.stroke",stylers:[{color:"#1d2c4d"}]},{featureType:"road.highway",elementType:"geometry",stylers:[{color:"#2c6675"}]},{featureType:"road.highway",elementType:"geometry.stroke",stylers:[{color:"#255763"}]},{featureType:"road.highway",elementType:"labels.text.fill",stylers:[{color:"#b0d5ce"}]},{featureType:"road.highway",elementType:"labels.text.stroke",stylers:[{color:"#023e58"}]},{featureType:"transit",elementType:"labels.text.fill",stylers:[{color:"#98a5be"}]},{featureType:"transit",elementType:"labels.text.stroke",stylers:[{color:"#1d2c4d"}]},{featureType:"transit.line",elementType:"geometry.fill",stylers:[{color:"#283d6a"}]},{featureType:"transit.station",elementType:"geometry",stylers:[{color:"#3a4762"}]},{featureType:"water",elementType:"geometry",stylers:[{color:"#0e1626"}]},{featureType:"water",elementType:"labels.text.fill",stylers:[{color:"#4e6d70"}]}],L=[{elementType:"geometry",stylers:[{color:"#242f3e"}]},{elementType:"labels.text.stroke",stylers:[{color:"#242f3e"}]},{elementType:"labels.text.fill",stylers:[{color:"#746855"}]},{featureType:"administrative.locality",elementType:"labels.text.fill",stylers:[{color:"#d59563"}]},{featureType:"poi",elementType:"labels.text.fill",stylers:[{color:"#d59563"}]},{featureType:"poi.park",elementType:"geometry",stylers:[{color:"#263c3f"}]},{featureType:"poi.park",elementType:"labels.text.fill",stylers:[{color:"#6b9a76"}]},{featureType:"road",elementType:"geometry",stylers:[{color:"#38414e"}]},{featureType:"road",elementType:"geometry.stroke",stylers:[{color:"#212a37"}]},{featureType:"road",elementType:"labels.text.fill",stylers:[{color:"#9ca5b3"}]},{featureType:"road.highway",elementType:"geometry",stylers:[{color:"#746855"}]},{featureType:"road.highway",elementType:"geometry.stroke",stylers:[{color:"#1f2835"}]},{featureType:"road.highway",elementType:"labels.text.fill",stylers:[{color:"#f3d19c"}]},{featureType:"transit",elementType:"geometry",stylers:[{color:"#2f3948"}]},{featureType:"transit.station",elementType:"labels.text.fill",stylers:[{color:"#d59563"}]},{featureType:"water",elementType:"geometry",stylers:[{color:"#17263c"}]},{featureType:"water",elementType:"labels.text.fill",stylers:[{color:"#515c6d"}]},{featureType:"water",elementType:"labels.text.stroke",stylers:[{color:"#17263c"}]}],V=[{featureType:"all",elementType:"labels.text.fill",stylers:[{saturation:36},{color:"#000000"},{lightness:40}]},{featureType:"all",elementType:"labels.text.stroke",stylers:[{visibility:"on"},{color:"#000000"},{lightness:16}]},{featureType:"all",elementType:"labels.icon",stylers:[{visibility:"off"}]},{featureType:"administrative",elementType:"geometry.fill",stylers:[{color:"#000000"},{lightness:20}]},{featureType:"administrative",elementType:"geometry.stroke",stylers:[{color:"#000000"},{lightness:17},{weight:1.2}]},{featureType:"landscape",elementType:"geometry",stylers:[{color:"#000000"},{lightness:20}]},{featureType:"poi",elementType:"geometry",stylers:[{color:"#000000"},{lightness:21}]},{featureType:"road.highway",elementType:"geometry.fill",stylers:[{color:"#000000"},{lightness:17}]},{featureType:"road.highway",elementType:"geometry.stroke",stylers:[{color:"#000000"},{lightness:29},{weight:.2}]},{featureType:"road.arterial",elementType:"geometry",stylers:[{color:"#000000"},{lightness:18}]},{featureType:"road.local",elementType:"geometry",stylers:[{color:"#000000"},{lightness:16}]},{featureType:"transit",elementType:"geometry",stylers:[{color:"#000000"},{lightness:19}]},{featureType:"water",elementType:"geometry",stylers:[{color:"#000000"},{lightness:17}]}],Z=[{featureType:"administrative.land_parcel",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"administrative.land_parcel",elementType:"geometry.stroke",stylers:[{visibility:"off"},{weight:7}]},{featureType:"administrative.locality",elementType:"geometry.stroke",stylers:[{visibility:"on"}]},{featureType:"administrative.locality",elementType:"labels.text.fill",stylers:[{visibility:"on"}]},{featureType:"administrative.locality",elementType:"labels.text.stroke",stylers:[{visibility:"on"}]},{featureType:"administrative.neighborhood",stylers:[{visibility:"off"}]},{featureType:"administrative.neighborhood",elementType:"geometry.fill",stylers:[{color:"#00ff28"},{visibility:"on"},{weight:2}]},{featureType:"administrative.neighborhood",elementType:"geometry.stroke",stylers:[{color:"#00ff28"},{visibility:"on"}]},{featureType:"administrative.neighborhood",elementType:"labels.icon",stylers:[{visibility:"off"}]},{featureType:"administrative.neighborhood",elementType:"labels.text.stroke",stylers:[{visibility:"off"}]},{featureType:"landscape.natural",elementType:"geometry.fill",stylers:[{visibility:"on"}]},{featureType:"poi",elementType:"labels.text",stylers:[{visibility:"off"}]},{featureType:"poi.attraction",stylers:[{visibility:"off"}]},{featureType:"poi.business",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"poi.medical",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"poi.place_of_worship",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"poi.school",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"poi.sports_complex",elementType:"geometry.fill",stylers:[{visibility:"on"}]},{featureType:"poi.sports_complex",elementType:"labels.icon",stylers:[{visibility:"off"}]},{featureType:"road",elementType:"labels.text",stylers:[{visibility:"on"},{lightness:-10},{color:"#b5b5b5"},{weight:.2}]},{featureType:"road",elementType:"labels.icon",stylers:[{visibility:"off"}]},{featureType:"road.local",elementType:"geometry.fill",stylers:[{color:"#fbfbfb"},{lightness:-15},{weight:.5}]},{featureType:"road.local",elementType:"geometry.stroke",stylers:[{visibility:"off"}]},{featureType:"transit",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"transit.station",elementType:"labels.icon",stylers:[{visibility:"off"}]},{featureType:"water",elementType:"labels.text",stylers:[{visibility:"off"}]}],A=[{elementType:"geometry",stylers:[{color:"#ebe3cd"}]},{elementType:"labels.text.fill",stylers:[{color:"#523735"}]},{elementType:"labels.text.stroke",stylers:[{color:"#f5f1e6"}]},{featureType:"administrative",elementType:"geometry.stroke",stylers:[{color:"#c9b2a6"}]},{featureType:"administrative.land_parcel",elementType:"geometry.stroke",stylers:[{color:"#dcd2be"}]},{featureType:"administrative.land_parcel",elementType:"labels.text.fill",stylers:[{color:"#ae9e90"}]},{featureType:"landscape.natural",elementType:"geometry",stylers:[{color:"#dfd2ae"}]},{featureType:"poi",elementType:"geometry",stylers:[{color:"#dfd2ae"}]},{featureType:"poi",elementType:"labels.text.fill",stylers:[{color:"#93817c"}]},{featureType:"poi.park",elementType:"geometry.fill",stylers:[{color:"#a5b076"}]},{featureType:"poi.park",elementType:"labels.text.fill",stylers:[{color:"#447530"}]},{featureType:"road",elementType:"geometry",stylers:[{color:"#f5f1e6"}]},{featureType:"road.arterial",elementType:"geometry",stylers:[{color:"#fdfcf8"}]},{featureType:"road.highway",elementType:"geometry",stylers:[{color:"#f8c967"}]},{featureType:"road.highway",elementType:"geometry.stroke",stylers:[{color:"#e9bc62"}]},{featureType:"road.highway.controlled_access",elementType:"geometry",stylers:[{color:"#e98d58"}]},{featureType:"road.highway.controlled_access",elementType:"geometry.stroke",stylers:[{color:"#db8555"}]},{featureType:"road.local",elementType:"labels.text.fill",stylers:[{color:"#806b63"}]},{featureType:"transit.line",elementType:"geometry",stylers:[{color:"#dfd2ae"}]},{featureType:"transit.line",elementType:"labels.text.fill",stylers:[{color:"#8f7d77"}]},{featureType:"transit.line",elementType:"labels.text.stroke",stylers:[{color:"#ebe3cd"}]},{featureType:"transit.station",elementType:"geometry",stylers:[{color:"#dfd2ae"}]},{featureType:"water",elementType:"geometry.fill",stylers:[{color:"#b9d3c2"}]},{featureType:"water",elementType:"labels.text.fill",stylers:[{color:"#92998d"}]}],R=[{featureType:"all",elementType:"labels",stylers:[{visibility:"on"}]},{featureType:"all",elementType:"labels.text.fill",stylers:[{saturation:36},{color:"#000000"},{lightness:40}]},{featureType:"all",elementType:"labels.text.stroke",stylers:[{visibility:"on"},{color:"#000000"},{lightness:16}]},{featureType:"all",elementType:"labels.icon",stylers:[{visibility:"off"}]},{featureType:"administrative",elementType:"geometry.fill",stylers:[{color:"#000000"},{lightness:20}]},{featureType:"administrative",elementType:"geometry.stroke",stylers:[{color:"#000000"},{lightness:17},{weight:1.2}]},{featureType:"administrative.country",elementType:"labels.text.fill",stylers:[{color:"#e5c163"}]},{featureType:"administrative.locality",elementType:"labels.text.fill",stylers:[{color:"#c4c4c4"}]},{featureType:"administrative.neighborhood",elementType:"labels.text.fill",stylers:[{color:"#e5c163"}]},{featureType:"landscape",elementType:"geometry",stylers:[{color:"#000000"},{lightness:20}]},{featureType:"poi",elementType:"geometry",stylers:[{color:"#000000"},{lightness:21},{visibility:"on"}]},{featureType:"poi.business",elementType:"geometry",stylers:[{visibility:"on"}]},{featureType:"road.highway",elementType:"geometry.fill",stylers:[{color:"#e5c163"},{lightness:0}]},{featureType:"road.highway",elementType:"geometry.stroke",stylers:[{visibility:"off"}]},{featureType:"road.highway",elementType:"labels.text.fill",stylers:[{color:"#ffffff"}]},{featureType:"road.highway",elementType:"labels.text.stroke",stylers:[{color:"#e5c163"}]},{featureType:"road.arterial",elementType:"geometry",stylers:[{color:"#000000"},{lightness:18}]},{featureType:"road.arterial",elementType:"geometry.fill",stylers:[{color:"#575757"}]},{featureType:"road.arterial",elementType:"labels.text.fill",stylers:[{color:"#ffffff"}]},{featureType:"road.arterial",elementType:"labels.text.stroke",stylers:[{color:"#2c2c2c"}]},{featureType:"road.local",elementType:"geometry",stylers:[{color:"#000000"},{lightness:16}]},{featureType:"road.local",elementType:"labels.text.fill",stylers:[{color:"#999999"}]},{featureType:"transit",elementType:"geometry",stylers:[{color:"#000000"},{lightness:19}]},{featureType:"water",elementType:"geometry",stylers:[{color:"#000000"},{lightness:17}]}],q=[...R,...Z],D=[{featureType:"water",elementType:"geometry",stylers:[{color:"#e9e9e9"},{lightness:17}]},{featureType:"landscape",elementType:"geometry",stylers:[{color:"#f5f5f5"},{lightness:20}]},{featureType:"road.highway",elementType:"geometry.fill",stylers:[{color:"#ffffff"},{lightness:17}]},{featureType:"road.highway",elementType:"geometry.stroke",stylers:[{color:"#ffffff"},{lightness:29},{weight:.2}]},{featureType:"road.arterial",elementType:"geometry",stylers:[{color:"#ffffff"},{lightness:18}]},{featureType:"road.local",elementType:"geometry",stylers:[{color:"#ffffff"},{lightness:16}]},{featureType:"poi",elementType:"geometry",stylers:[{color:"#f5f5f5"},{lightness:21}]},{featureType:"poi.park",elementType:"geometry",stylers:[{color:"#dedede"},{lightness:21}]},{elementType:"labels.text.stroke",stylers:[{visibility:"on"},{color:"#ffffff"},{lightness:16}]},{elementType:"labels.text.fill",stylers:[{saturation:36},{color:"#333333"},{lightness:40}]},{elementType:"labels.icon",stylers:[{visibility:"off"}]},{featureType:"transit",elementType:"geometry",stylers:[{color:"#f2f2f2"},{lightness:19}]},{featureType:"administrative",elementType:"geometry.fill",stylers:[{color:"#fefefe"},{lightness:20}]},{featureType:"administrative",elementType:"geometry.stroke",stylers:[{color:"#fefefe"},{lightness:17},{weight:1.2}]}];export{$ as Circle,M as CustomControl,P as GoogleMap,I as Marker,B as Polygon,z as Polyline,E as Rectangle,N as aubergine,L as dark,V as grey,Z as minimal,A as retro,R as roadways,q as roadwaysMinimal,D as ultraLight};
    | 
    
     @ ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader-v16/dist??ref--0-1!./src/App.vue?vue&type=script&lang=js 3:0-44 6:15-24
     @ ./src/App.vue?vue&type=script&lang=js
     @ ./src/App.vue
     @ ./src/main.js
     @ multi ./src/main.js
    
     ERROR  Build failed with errors.
    

    The latest vue3-google-map version that works for me is 0.7.1.

    With version 0.7.2 my app also fails to build, but the reported error is different:

     ERROR  Failed to compile with 1 error                                                            4:04:32 PM
    
     error  in ./node_modules/vue3-google-map/dist/es/index.js
    
    Module parse failed: Unexpected token (416:44)
    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
    |                 fullscreenControlOptions: props.fullscreenControlPosition
    |                     ? {
    >                         position: api.value?.ControlPosition[props.fullscreenControlPosition],
    |                     }
    |                     : {},
    
     @ ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader-v16/dist??ref--0-1!./src/App.vue?vue&type=script&lang=js 3:0-44 6:15-24
     @ ./src/App.vue?vue&type=script&lang=js
     @ ./src/App.vue
     @ ./src/main.js
     @ multi ./src/main.js
    
     ERROR  Build failed with errors.
    
    bug 
    opened by JoseGoncalves 33
  • Feature: HtmlMarkers

    Feature: HtmlMarkers

    Using a CustomOverlay it's possible to mimic the behaviour of a marker while adding the ability to render html using a slot.

    The eregnier/vue2-gmap-custom-marker plugin for diegoazh/gmap-vue has this working (demo). Unfortunately this is all written in Vue2 and not usable in Vue3.

    I've tried porting the plugin myself but my JS skills are very limited.

    Is there any chance this wonderful package will support this feature in the future?

    feature request 
    opened by daniel-de-wit 13
  • Uncaught (in promise)  Object { message:

    Uncaught (in promise) Object { message: "Map: Expected mapDiv of type HTMLElement but was passed null.",

    Hi, I am trying to use this library but I get this error:

    Uncaught (in promise) 
    Object { message: "Map: Expected mapDiv of type HTMLElement but was passed null.",....
    

    This is how I used it in my content component

    ....
    // script.js
    import { GoogleMap, Marker } from "vue3-google-map";
    
    export default {
    	name: "Content",
    	props: {
    		data: Object,
    	},
    	components: { GoogleMap, Marker },
    	data() {
    		return {
                        center: { lat: 40.689247, lng: -74.044502 },
    .....
    
    //component.vue
    ....
    <GoogleMap
    	:api-key="API_KEY"
    	style="width: 100%; height: 500px"
    	:center="center"
    	:zoom="15"
    >
    <Marker :options="{ position: center }" />
    </GoogleMap>
    ...
    

    am I doing this properly?

    opened by web-programmer-here 12
  • Add Info Window

    Add Info Window

    Adding the Info Windows feature to this repo is a feature-request for this library. We are happy to accept PR's for this work as there is not immediate demand internally for this feature but we do understand why it might be useful and it will eventually be incorporated.

    feature request 
    opened by yankeeinlondon 12
  • Examples of using v-for with <Marker>

    Examples of using v-for with

    I've tried a few ways to iterate my array to create several markers without success. Have you had to do this?

    I'm looking to confirm this would work and an example. I've tried the below ways and get some awful Vue errors, i.e. Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://n

    Option 1:

    Option 2: <Marker v-for="location in state.locations" :key="location.id" :options="{ position: { lat: location.lat, lng: location.lng } }" @click="markerClicked"/>

    opened by jasonandress 10
  • InfoWindow with slot gives insertBefore TypeError errors.

    InfoWindow with slot gives insertBefore TypeError errors.

    There seems to be an issue with removing components that use <slot />

    This will work:

    <InfoWindow v-if="open" :options="{ position: openedMarker.position }, content: 'Hello World!' }"  @closeclick="open = !open"/>
    

    This will give errors:

    <InfoWindow v-if="open" :options="{ position: openedMarker.position"  @closeclick="open = !open">
    Hello World!
    </InfoWindow>
    

    Errors:

    vue.cjs.js:11319 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'insertBefore')
        at insert (vue.cjs.js:11319:16)
        at processCommentNode (vue.cjs.js:8451:13)
        at patch (vue.cjs.js:8403:17)
        at patchBlockChildren (vue.cjs.js:8727:13)
        at processFragment (vue.cjs.js:8789:17)
        at patch (vue.cjs.js:8414:17)
        at patchBlockChildren (vue.cjs.js:8727:13)
        at patchElement (vue.cjs.js:8635:13)
        at processElement (vue.cjs.js:8501:13)
        at patch (vue.cjs.js:8418:21)
    

    Seems to be the case for CustomMarker also (gives the error when computed

    This works: <Marker v-for="m of markers" :options="m.options" :key="m.id">...</Marker> This gives errors: <CustomMarker v-for="m of markers" :options="m.options" :key="m.id">...</CustomMarker>

    bug 
    opened by ValiDrv 8
  • Where to register google maps API events listener?

    Where to register google maps API events listener?

    Where should I register maps API event listeners? I tried to add a listener to click event in mounted hooks but the component's map` property is evaluated to null at this point in a component's lifecycle. Thank you.

    opened by prasetyaputraa 8
  • Handling Language and Region Change

    Handling Language and Region Change

    I am having an issue with the language and region values, when I need to update them to present a different language or region.

    Seems like it doesn't like to be loaded again.

    Selection_735

    I understand the problem is loading the script again, not sure the best way to solve it.

    upstream 
    opened by scottix 8
  • googlemap api

    googlemap api

    i found provide https://github.com/inocan-group/vue3-google-map/blob/9ef51c45b97ac3c2d9bd72f91aed90f170a1505a/src/components/GoogleMap.vue#L79

    how to inject api on my components googlemaps api aka window.google GmapApi alternate https://github.com/xkjyeah/vue-google-maps/blob/vue2/src/main.js

    or only use ref solution https://vue3-google-map.netlify.app/advanced-usage/ ?

    feature request 
    opened by reslear 7
  • Updating `<Marker :options>` prop doesn't render markers

    Updating `` prop doesn't render markers

    Hello folks,

    Is this a bug or am I using the composition API wrong here (I'm new with it)?

    I have a BaseMap.vue component which is initially rendered the [] as the value of the prop markers and when the backend responds that prop is value is updated with a (new) populated array.

    Here's my BaseMap.vue:

    <template>
      <GoogleMap
        id="map"
        ref="googleMapCmp"
        class="base-map"
        map-type-id="hybrid"
        :api-key="GOOGLE_MAPS_CONFIG.key"
        :region="GOOGLE_MAPS_CONFIG.region"
        :language="GOOGLE_MAPS_CONFIG.language"
        :center="center"
        :zoom="zoom"
        :map-type-control="false"
        :clickable-icons="false"
      >
        <Marker
          v-for="marker in markers"
          :key="marker.title"
          :options="{
            title: marker.name,
            position: marker.position,
            clickable: true,
            icon: {
              url: require('../assets/icons/pin.svg'),
              scaledSize: { width: 50, height: 50 },
            },
          }"
          @click="() => centerMapToPosition(marker.position)"
        />
      </GoogleMap>
    </template>
    
    <script lang="ts">
    import {
      ComponentPublicInstance,
      PropType,
      Ref,
      computed,
      defineComponent,
      ref,
      watch,
    } from 'vue'
    import { GoogleMap, Marker } from 'vue3-google-map'
    
    import { GOOGLE_MAPS_CONFIG } from '../config'
    import { GMapsMarker, GMapsPosition, GPosition } from '../types'
    import { getBoundsForMarkers, getOptimalMapZoom } from '../utils'
    
    type MapComponent = ComponentPublicInstance & {
      map: { panTo: (pos: GPosition) => void }
    }
    
    export default defineComponent({
      props: {
        center: { type: Object as PropType<GMapsPosition>, required: true },
        markers: { type: Array as PropType<GMapsMarker[]>, default: [] },
        maxZoom: { type: Number, default: 16 },
      },
      components: {
        GoogleMap,
        Marker,
      },
      setup(props) {
        const googleMapCmp = ref(undefined) as Ref<ComponentPublicInstance | undefined>
        const boundedZoom = ref(7)
        const zoom = computed(() => Math.min(props.maxZoom, boundedZoom.value))
    
        function centerMapToPosition(newCenter: GPosition): void {
          ;(googleMapCmp.value as MapComponent)?.map.panTo(newCenter)
        }
    
        watch(
          () => props.markers,
          (newMarkers: GMapsMarker[]): void => {
            setTimeout(() => {
              const bounds = getBoundsForMarkers(newMarkers)
    
              if (bounds) {
                centerMapToPosition(bounds.getCenter())
    
                const googleMapEl = googleMapCmp.value?.$el as HTMLElement | undefined
    
                if (googleMapEl) {
                  boundedZoom.value = getOptimalMapZoom(
                    bounds,
                    googleMapEl.getBoundingClientRect(),
                  )
                }
              }
            }, 0)
          },
          { immediate: true },
        )
    
        return {
          googleMapCmp,
          GOOGLE_MAPS_CONFIG,
          center: props.center,
          markers: props.markers,
          zoom,
          centerMapToPosition,
        }
      },
    })
    </script>
    
    <style lang="scss" scoped>
    @import '../styles/constants/_colors.scss';
    @import '../styles/utils/_material-shadow';
    
    .base-map {
      @include material-shadow($level: 1, $background: $color-platinum);
      height: 100%;
      border-radius: 4px;
    
      :deep(.vue-map) {
        border-radius: 4px;
      }
    }
    
    #map {
      width: 100%;
      height: 100%;
    }
    </style>
    

    and the wrapping component StationsMap.vue:

    <template>
      <div class="stations-map">
        <BaseMap :center="center" :markers="markers" />
      </div>
    </template>
    
    <script lang="ts">
    import denormalize from '@weareredlight/denormalize_json_api'
    import { TYPE, useToast } from 'vue-toastification'
    import { defineComponent } from 'vue'
    
    import BaseMap from '../../../components/BaseMap.vue'
    import { fetchFromBackend } from '../../../utils'
    import { CurrentLocation, GMapsMarker, GMapsPosition, RESOURCE, Station } from '../../../types'
    
    interface StationWithCurrentLocation extends Station {
      'current-location'?: CurrentLocation
    }
    
    interface StationsMapData {
      center: GMapsPosition
      markers: GMapsMarker[]
    }
    
    const AUSTRIA_POSITION: GMapsPosition = { lat: 47.6, lng: 14 } as const
    
    export default defineComponent({
      components: { BaseMap },
      data(): StationsMapData {
        return {
          center: AUSTRIA_POSITION,
          markers: [],
        }
      },
      async created(): Promise<void> {
        try {
          const stations: StationWithCurrentLocation[] = denormalize(
            await fetchFromBackend({
              resource: RESOURCE.STATIONS,
              includedResources: [RESOURCE.CURRENT_LOCATION],
            }),
          ).data
    
          const markers: GMapsMarker[] = []
    
          stations.forEach((station) => {
            const currentLocation = station['current-location']
    
            if (currentLocation) {
              markers.push({
                name: station.name,
                position: {
                  lat: parseFloat(currentLocation.latitude),
                  lng: parseFloat(currentLocation.longitude),
                },
              })
            }
          })
    
          this.markers = markers
        } catch (error) {
          useToast()(error.message, { type: TYPE.ERROR })
        }
      },
    })
    </script>
    
    <style lang="scss" scoped>
    .stations-map {
      height: 100%;
    }
    </style>
    
    

    Expectation:

    • Changing the options prop in <Marker> renders new markers

    Actual:

    • No markers are rendered

    Additional info:

    • I know for a fact the Markers are updated inside BaseMap.vue because the map will zoom in and center around where the markers are expected to render (so the watcher triggers)
    • If I hardcode the array of markers inside the setup function instead of getting if from the props asynchronsouly the markers render as expected
    • Keeping the prop changing async, if I force a re-render and HMR of the BaseMap.vue component (note the prop already has value at this point since the wrapping component StationsMap.vue has already received the BE response) by making any irrelevant code change the markers will render as expected. Effectively this emulates the hardcoded case.
    • there's no output in console
    • I'm using [email protected] because of https://github.com/inocan-group/vue3-google-map/issues/13

    Thanks for all the help!!

    opened by maninak 7
  • <CustomMarker> throws

    throws "Failed to execute 'insertBefore' on 'Node'" when updating array

    vue: 3.2.6 and 3.2.7 vue3-google-map: 0.13.0

    I'm having an interesting issue with CustomMarkers when altering a list of them and displaying them on a map. In certain situations they will throw an error when being redrawn. In my app's case, panning the map makes a network request based on the new location, and marker data is returned from the client. The client then updates an array of locations. That array is used in a <CustomMarker v-for />.

    Here's an example of what the code looks like:

      <GoogleMap
        ref="mapRef"
        api-key="XYZ"
        style="width: 100%; height: 100%"
        :center="center"
        :disableDefaultUi="true"
        :clickableIcons="false"
        :keyboardShortcuts="false"
        :zoomControl="true"
        gestureHandling="greedy"
        :styles="styles"
        :tilt="0"
        :zoom="15"
        :maxZoom="20"
        :minZoom="8"
      >
          <CustomMarker
            v-bind:key="'bcn-mrk-' + beacon.id"
            v-for="beacon in beacons"
            :options="{
              anchorPoint: 'LEFT_CENTER',
              position: { lat: beacon.loc.lat, lng: beacon.loc.lon },
            }"
            @click="onMarkerClick(beacon.id)"
          >👮 <span class="map-label">{{ beacon.message }}</span></CustomMarker>
      </GoogleMap>
    

    In this case beacons is an array of objects with an id, message, loc.lat, and loc.lng properties.

    Here's a recording of this issue happening:

    custom-marker-error

    In this recording, two CustomMarkers are added, then they're removed, then they're added again, then one is removed, and upon trying to add the one that was removed again the error is thrown.

    Here's the content of the console:

    2022-06-23_13-09-29

    Uncaught (in promise) DOMException: Failed to execute 'insertBefore' on 'Node':
      The node before which the new node is to be inserted is not a child of this node.
        at insert (webpack-internal:///./node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js:160:16)
    

    It seems to me like something might be getting cached in Vue or in vue3-google-map. If, for example, I modify the id field of the individual beacon objects and append a random number to them (v-bind:key="'bcn-mrk-' + beacon.id + Math.random()"), then the issue goes away entirely.

    bug 
    opened by tlhunter 6
  • Question: How to move marker?

    Question: How to move marker?

    Hi, is there any way to move an existing marker to other coordinates? When changing the underlying data the marker is not updated, and there seems to be no way to call the API's setPosition function...

    Thanks

    question 
    opened by lukepower 1
  • documentation for the GoogleMap component and its events

    documentation for the GoogleMap component and its events

    Sorry if I'm blind, but somehow I can't find the docs for the GoogleMap component and its events, only the things that you can put on it, like Marker, Polyline, etc. Could you point to the docs, or add it. Thanks!

    documentation enhancement question 
    opened by andrisi 1
  • SameSite cookie complaint from chrome browser when using google's icons for markers

    SameSite cookie complaint from chrome browser when using google's icons for markers

    Hello,

    when using the vue3-google-map plugin inside my SPA frontend app, i keep getting errors/warnings in developer console:

    Indicate whether to send a cookie in a cross-site request by specifying its SameSite attribute

    e.g. for:

    <Marker
        ...
        :options="{ icon: 'http://maps.google.com/mapfiles/kml/paddle/wht-circle.png')}"
    />
    ...etc...
    

    being frontend beginner, I am not sure if i understand the core of issue properly, but i believe that:

    • this plugin should allow/be able to change the cookies/headers settings for it's internal requests for icons being requested from "different" domain?

    More error details dumped in the chrome's console:

    Because a cookie’s SameSite attribute was not set or is invalid, it defaults to SameSite=Lax, which prevents the cookie from being sent in a cross-site request. This behavior protects user data from accidentally leaking to third parties and cross-site request forgery.
    
    Resolve this issue by updating the attributes of the cookie:
    
    - Specify `SameSite=None` and `Secure` if the cookie should be sent in cross-site requests. This enables third-party use.
    - Specify `SameSite=Strict` or `SameSite=Lax` if the cookie should not be sent in cross-site requests
    
    Affected resources:
    
    4 cookies
    
    Name | Domain & Path
    -- | --
    HSID | .google.com/
    APISID | .google.com/
    SID | .google.com/
    SIDCC | .google.com/
    
    4 requests
    
    wht-circle.png
    blu-circle.png
    wht-circle.png
    blu-circle.png
    
    opened by RustyJoeM 0
  • <MarkerCluster>, <CustomMarker> & <InfoWindow> forces re-renders as elements change

    , & forces re-renders as elements change

    Very similar to issue #84 but different/might shed some light on how to fix.

    The map seems to re-render on pretty much any iteration/change. This causes the markers to re-render, and clusters to re-calculate in a loop.

    Problem is, it does it even when you interact with something that does not impact it.

    Example:

    • I enabled SuperClusterAlgorithm loging.
    • I have a <InfoWindow> outside all <CustomMarker>, which opens when you click a <CustomMarker>
    • I wrap the <CustomMarker> in <MarkerCluster>

    Problem:

    • <MarkerCluster> will re-calculate even when you open/close the <InfoWindow> located outside anything that should impact anything, except the .

    Also, if you have allot of markers, the cluster will redraw on what it seems to be every marker dom change, ending up with unresponsive browser pages, and instances where 1000 markers take 10 sec to render. (when in reality they took 0.01 sec, but re-did the math 1000 times)

    The same SuperClusterAlgorithm from @googlemaps/markerclusterer works with 100000 markers no problem in other projects (vue2), so that's not the issue. I'm thinking it's some reactivity/watch implementation of this library, but I'm new to vue3 so can't pinpoint it 100%

    Replication code: https://stackblitz.com/edit/vitejs-vite-zwxadc?file=src%2FApp.vue

    • Keep the console opened to see the events.
    perf 
    opened by ValiDrv 5
Releases(v0.15.0)
  • v0.15.0(Sep 3, 2022)

  • v0.14.1(Aug 31, 2022)

  • v0.14.0(Aug 24, 2022)

    What's Changed

    Features

    • feat: heatmap layer by @HusamIbrahim in https://github.com/inocan-group/vue3-google-map/pull/96

    Full Changelog: https://github.com/inocan-group/vue3-google-map/compare/v0.13.2...v0.14.0

    Source code(tar.gz)
    Source code(zip)
  • v0.13.2(Jun 28, 2022)

    What's Changed

    Bug Fixes

    • fix: attrs fallthrough in custom markers and info windows

    Full Changelog: https://github.com/inocan-group/vue3-google-map/compare/v0.13.1...v0.13.2

    Source code(tar.gz)
    Source code(zip)
  • v0.13.1(Jun 27, 2022)

    What's Changed

    Bug Fixes

    • fix: dom managment conflicts in info windows and custom markers by @HusamIbrahim in https://github.com/inocan-group/vue3-google-map/pull/88

    Full Changelog: https://github.com/inocan-group/vue3-google-map/compare/v0.13.0...v0.13.1

    Source code(tar.gz)
    Source code(zip)
  • v0.13.0(May 28, 2022)

    What's Changed

    Features

    • feat: allow loading api script externally by @HusamIbrahim in https://github.com/inocan-group/vue3-google-map/pull/78

    Full Changelog: https://github.com/inocan-group/vue3-google-map/compare/v0.12.0...v0.13.0

    Source code(tar.gz)
    Source code(zip)
  • v0.12.0(May 20, 2022)

    What's Changed

    Features

    • Add mapId in GoogleMap Component by @RFrancois6 in https://github.com/inocan-group/vue3-google-map/pull/71
    • feat: custom markers by @HusamIbrahim in https://github.com/inocan-group/vue3-google-map/pull/72

    New Contributors

    • @RFrancois6 made their first contribution in https://github.com/inocan-group/vue3-google-map/pull/71

    Full Changelog: https://github.com/inocan-group/vue3-google-map/compare/0.11.0...v0.12.0

    Source code(tar.gz)
    Source code(zip)
  • 0.11.0(May 11, 2022)

    What's Changed

    • feat: marker clusters by @HusamIbrahim in https://github.com/inocan-group/vue3-google-map/pull/69

    Full Changelog: https://github.com/inocan-group/vue3-google-map/compare/v0.10.0...0.11.0

    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(Mar 25, 2022)

    What's Changed

    ⚠ BREAKING CHANGES

    • separate entry point for bundled themes (27ff148)

    Full Changelog: https://github.com/inocan-group/vue3-google-map/compare/v0.9.0...v0.10.0

    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(Mar 22, 2022)

  • v0.8.5(Mar 21, 2022)

  • v0.8.4(Mar 20, 2022)

    What's Changed

    Features

    • info windows by @HusamIbrahim in https://github.com/inocan-group/vue3-google-map/pull/60

    Full Changelog: https://github.com/inocan-group/vue3-google-map/compare/v0.8.3...v0.8.4

    Source code(tar.gz)
    Source code(zip)
Owner
Inocan Group
Inocan Group is an accelerator for businesses in the Cannabis space, this is our home for Open Source projects
Inocan Group
Reactive Vue 3 components for Google maps

Vue 3 Google maps Components Set of mostly used Google Maps components for Vue.js. Why this library exists? We heavily use Google Maps in our projects

Fawad Mirzad 117 Dec 28, 2022
Integrate Google Maps in your Vue application

vue-googlemaps Integrate Google Maps in your Vue application in a "Vue-way". This library is Work In Progress. More components will be available in th

Guillaume Chau 534 Nov 2, 2022
Google maps component for vue with 2-way data binding

CONTRIBUTORS NEEDED! It's been increasingly difficult for me to make time to maintain this project. My projects at work have also gradually migrated a

Daniel Sim 1.9k Jan 6, 2023
A lightweight Google Maps plugin for Vue

x5-gmaps (Live Demo) This is a lightweight Google Maps plugin for Vue. Samples/examples/tutorials Tutorial creating a COVID Heatmap Address Autocomple

Keagan Chisnall 102 Oct 5, 2022
Google maps component for vue with 2-way data binding

vue-google-maps Demo: Demo in production Showcase with a lot of features Presentation If you want to write google map this way : <map :center="{lat:

Guillaume Leclerc 556 Nov 21, 2022
Using Google Maps with Vue.js

stores-map Project setup npm install Compiles and hot-reloads for development npm run serve Compiles and minifies for production npm run build Run

Edoardo Gargano 6 Apr 22, 2022
A wrapper component for consuming Google Maps API built on top of VueJs v2.

A wrapper component for consuming Google Maps API built on top of VueJs v2. Fork of the popular vue-google-maps plugin.

Diego A. Zapata Häntsch 144 Jan 5, 2023
Vue 2 components for Leaflet maps

Vue2Leaflet Vue2Leaflet is a JavaScript library for the Vue framework that wraps Leaflet making it easy to create reactive maps. How to install npm in

Vue Leaflet 1.9k Dec 29, 2022
Integrate Azure Maps in your Vue application

Vue Azure Maps Vue Azure Maps is a library for Vue.js that integrates Azure Maps. It offers several Vue components out of the box and supports custom

Ricardo Ruiz 23 May 19, 2022
A set of Vue.js components to display an interactive SVG map

vue-svg-map A set of Vue.js components to display an interactive SVG map. Demo Take a look at the live demo! Installation npm npm install --save vue-s

Victor Cazanave 80 Dec 18, 2022
Yandex Maps Component for VueJS

vue-yandex-maps Documentation: RU, EN Contributors ✨ Thanks goes to these wonderful people (emoji key): Wormaster ?? Nikitenko Andrey ?? Kamil ?? Alex

null 338 Dec 28, 2022
Annotate maps and generate GeoJSON in Kirby by drawing markers, paths and shapes

Kirby Mapnotator Annotate maps and generate GeoJSON in Kirby by drawing markers, paths and shapes. Overview This plugin is completely free and publish

Sylvain Julé 28 Nov 9, 2022
Traveliko - Travel with Friends ~ Web application prepared using Google Street View API that allows you to real-time travel with your friends in the same place in street view mode.

Traveliko - Travel with Friends! You can create a room with your friends and travel in street view mode and navigate the map. The application basicall

İlker Güldalı 6 Nov 27, 2022
🗺 Vue Mapbox GL - A small components library to use Mapbox GL in Vue

?? Vue Mapbox GL A small components library to use Mapbox GL in Vue. Installation & usage Have a look at the small guide for information on how to set

Studio Meta 48 Dec 18, 2022
vue google map custom marker component

vue2-gmap-custom-marker This component allows you to display custom HTML content on the map using Overlay. This component is an adaptation of the Goog

eric regnier 130 Sep 14, 2022
Vue with Typescript and Google Map

CONTRIBUTORS NEEDED! My projects at work have also gradually migrated away from Google Maps (but still on Vue -- Vue's awesome!), so there's less and

An Nguyen Van 8 Oct 16, 2021
a simple component to generate an static google map

vue-static-map a simple component to generate an static google map Google Documentation Demo SandBox JSBin example Requirements Vue 2.X.X Usage Instal

Eduardo P. Rivero 23 Nov 24, 2022
🔍 Google Place Autocomplete Search - Renderless component + Wrappers for Bulma, Bootstrap and more...

vue-custom-google-autocomplete Installation You need Vue.js version 2.0+ and an Google PLACE API key. This plugin is a renderless component. It comes

Damien Roche 31 Jul 11, 2022
Cografya-3d - 3D models of some geographic shapes and their use with Three.js

??️ Coğrafya 3D Bazı coğrafi şekillerin 3D modelleri ve Three.js ile kullanılmas

Orhan Emre Dikicigil 6 Nov 8, 2022