How to fix 'map center & render all tiles' with vue-leaflet - vue.js

Error loading tiles maps
the page loads but the map is not centered completely and tiles are missing even if I already put the props :center & :zoom
can I initialize the map when loading the page?
Vue-Leaflet
this is my code
<template>
<div class="map">
<l-map class="maps" :zoom="zoom" :center="center">
<l-marker :lat-lng="marker"></l-marker>
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
</l-map>
</div>
</template>
<script>
import { L, LMap, LTileLayer, LMarker } from 'vue2-leaflet';
import { Icon } from 'leaflet';
import 'leaflet/dist/leaflet.css'
delete Icon.Default.prototype._getIconUrl;
Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});
export default {
props:['lat','lng'],
mounted(){
// this.center = L.latLng(this.lat,this.lng)
// this.marker = L.latLng(this.lat,this.lng)
},
data(){
return{
zoom:13,
center: L.latLng(this.lat,this.lng),
url:'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
attribution:'© OpenStreetMap contributors',
marker: L.latLng(this.lat,this.lng),
}
},
components:{
LMap, LTileLayer, LMarker
}
}
</script>
<style>
.map{
width: 100%;
height: 500px;
}
</style>

Related

VueJS - use sidebar component event to control navbar

I am building a web app using Vue3 + vuetify3 running on Vite. I have a v-navigation-drawer within my Sidebar.vue component (child) and I'm emitting mouse events to have my App.vue (parent) listen to it and allow another child components (in this case Topbar.vue) to use that to move the title to the right as the sidebar opens and closes. The problem I'm seeing is that I can log the events in App.vue from the Sidebar as true/false but when I check those values in Topbar.vue they're undefined. I have tried different approaches but can't come up with a solution. If somebody can give me some pointers on how to figure this out I would really appreciate it.
For the sake of space, I'm not including all the css rules and all the items in the sidebar, just the functional sections worth looking at but again, the sidebar is not the issue but the way the topbar is not getting the value from the App.vue.
Sidebar.vue
<template>
<v-navigation-drawer v-model="drawer" class="sidepanel" expand-on-hover rail>
<v-list class="sidebarlist" density="compact" nav>
<router-link to="/">
<v-list-item
class="sidebar-item"
:style="{
backgroundColor: selectedRoute === 'dashboard' ? '#9100e9' : '',
}"
#click="selectedRoute = 'dashboard'"
prepend-icon="mdi-home"
title="Dashboard"
value="dashboard"
></v-list-item>
</router-link>
</v-list>
</v-navigation-drawer>
</template>
<script lang="ts">
export default {
data() {
return {
drawer: true,
selectedRoute: "",
};
},
methods: {
onHover() {
this.$emit("mouseenter");
},
onLeave() {
this.$emit("mouseleave");
},
},
};
</script>
<style scoped>
.sidebar-opened {
opacity: 1;
transition: 0.3s ease-out;
}
.sidebar-item:hover {
background-color: #4b247a;
transition-duration: 0.4s;
}
/* and more */
</style>
App.vue
<template>
<v-app :theme="theme">
<TopbarComp :title="$route.meta.title" :sidebarHovered="sidebarHovered"/>
<SideBarComp #mouseenter="onHover" #mouseleave="onLeave"/>
<router-view />
</v-app>
</template>
<script lang="ts">
import { ref } from "vue";
import SideBarComp from "./components/Sidebar.vue";
export default {
components: {
SideBarComp,
},
methods: {
onHover() {
// Slide Topbar to the right
this.sidebarHovered = true;
console.log('Sidebar entered')
},
onLeave() {
// Slide Topbar back in place
this.sidebarHovered = false;
}
},
setup() {
const theme = ref("dark");
const sidebarHovered = ref(false);
return {
theme,
sidebarHovered
};
}
};
</script>
Topbar.vue
<template>
<v-toolbar fixed app color="#2D2D2D">
<v-toolbar-items>
<v-toolbar-title
class="text-uppercase pa-5"
:class="{ 'slide-right': topbarSlide || sidebarHovered }"
#mouseenter="onHover"
#mouseleave="onLeave"
>
<span class="font-weight-light" style="color: #9E9E9E;">{{ firstWord + ' '}} </span>
<span>{{ restOfWords }}</span>
</v-toolbar-title>
</v-toolbar-items>
</v-toolbar>
</template>
<script lang="ts">
export default {
props: ['title', 'sidebarHovered'],
data() {
return {
toptitle: this.title || '',
topbarSlide: false,
};
},
computed: {
firstWord() {
return this.toptitle.split(" ")[0];
},
restOfWords() {
return this.toptitle.split(" ").slice(1).join(" ");
},
},
methods: {
onHover() {
this.topbarSlide = true;
console.log('The value of the Sidebar is: ',this.sidebarHovered)
console.log('The value of the Topbar is: ', this.topbarSlide)
},
onLeave() {
this.topbarSlide = false;
},
},
};
</script>
<style>
.slide-right {
transform: translateX(20%) !important;
transition: transform 0.3s ease-out !important;
}
</style>

how to import a GeoJson file in vue.js 2 component in leaflet

I have a GeoJson file and added it to my project file, but I don't know how to import and use it in my map component. I tried the code below, but it didn't work.
<template>
<div class="locationMap">
<l-map
:zoom="6"
:center="[47.31322, -1.319482]"
style="height: 800px; width: 1000px"
>
<l-tile-layer :url="url" :attribution="attribution" />
<l-geo-json
:geojson="geojson"
:options="options"
:options-style="styleFunction"
/>
</l-map>
</div>
</template>
<script>
import geojson from "../components/provinces.json";
export default {
name: "locationMap",
data() {
return {
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
attribution:
'© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a>contributors',
geojson: null,
};
},
mounted() {
this.geojson = geojson;
},
};
</script>
Try to assign this.geojson before mounting and load the file with the fetch method.
async created () {
const jsonFile = await fetch('../components/provinces.json')
this.geojson = await jsonFile.json()
}
This example is available in Vue Leaflet documentation.
https://vue2-leaflet.netlify.app/components/LGeoJson.html#demo
So I still couldn't find a solution to import the GeoJson file using vue2-leaflet package , but I was able to import the file using the code below:
<template>
<div class="container">
<div id="mapContainer">
</div>
</div>
</template>
<script>
import "leaflet/dist/leaflet.css";
import L from "leaflet";
import geojson from "../components/provinces.json"
export default{
name: "locationMap",
data() {
return{
center: [32.87255939010237, 53.781741816799745],
}
},
methods: {
setupLeafletMap: function () {
const mapDiv = L.map("mapContainer").setView(this.center, 5);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{
attribution: '© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors',
// maxZoom: 18,
}
).addTo(mapDiv);
var myStyle = {
"fillColor": "#818181",
"color": "black",
"weight": 2,
"opacity": 0.65,
"fillOpacity": 0.6
};
L.geoJSON(geojson,{
style: myStyle,
}
}
}
mounted() {
this.setupLeafletMap()
console.log(mockData.colors[1].id)
},
}
</script>

erro while using bootstrap-vue in vue3 project

I am working on bootstrap-vue but I cannot add the functionalities of bootstrap. the code of main.js is
import { createApp } from 'vue'
import App from './App.vue'
import "bootstrap/dist/css/bootstrap.css"
import"bootstrap-vue/dist/bootstrap-vue.css"
createApp(App).mount('#app')
and the code of Helloworld.vue file is
<template>
<div>
<h1>hello from helloworld</h1>
<h5>Pressed and un-pressed state</h5>
<b-button :pressed="true" variant="success">Always Pressed</b-button>
<b-button :pressed="false" variant="success">Not Pressed</b-button>
<h5 class="mt-3">Toggleable Button</h5>
<b-button :v-bind="myToggle" variant="primary">Toggle Me</b-button>
<p>Pressed State: <strong>{{ myToggle }}</strong></p>
<h5>In a button group</h5>
<b-button-group size="sm">
<b-button
v-for="(btn, idx) in buttons"
:key="idx"
:v-bind="btn.state"
variant="primary"
>
{{ btn.caption }}
</b-button>
</b-button-group>
<p>Pressed States: <strong>{{ btnStates }}</strong></p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
myToggle: false,
buttons: [
{ caption: 'Toggle 1', state: true },
{ caption: 'Toggle 2', state: false },
{ caption: 'Toggle 3', state: true },
{ caption: 'Toggle 4', state: false }
]
}
},
computed: {
btnStates() {
return this.buttons.map(btn => btn.state)
}
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
what I do to implement the bootstrap-vue in this project
In your main.js file you are missing bootstrap-vue import. Try the below for vue3, it worked for me. Please note: create a const for app.
import { createApp } from 'vue'
import BootstrapVue3 from 'bootstrap-vue-3'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import App from './App.vue'
const app = createApp(App)
app.use(BootstrapVue3)
app.mount('#app')

Add searchbar for vue2-leaflet

Hi do somebody know or have some samples of code how to add searchbar for vue2-leaflet map, I have tried the following https://www.npmjs.com/package/vue2-leaflet-geosearch but failed, do you know any alternatives how to resolve it,hope for your help, thanks . This is code that works and I would like to add searchbar in the code .
<template>
<div>
<b-modal size="md" :visible="visible" #hidden="$emit('clear')" #shown="modalShown" title="Event details">
<div class="foobar1">
<l-map :minZoom="3" :zoom="13" ref="mymap" #click="addMarker">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<!-- <l-marker :lat-lng="center"></l-marker> -->
</l-map>
</div>
<template slot="modal-footer">
<b-btn variant="danger" #click="">Delete</b-btn>
</template>
</b-modal>
</div>
</template>
<style scoped>
.foobar1 {
width: 450px;
height: 400px;
align: center;
}
</style>
<script>
import {LMap, LMarker, LTileLayer} from "vue2-leaflet";
import L from "leaflet"
export default {
name: "loc",
components: {
LMap,
LMarker,
LTileLayer,
L
},
data() {
return {
marker: L.latLng(77, 154.0),
visible: true,
url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
attribution:
'© OpenStreetMap contributors'
};
},
methods: {
plotCurrentLocation(map) {
var vm = this;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
var currLocation = new L.latLng(position.coords.latitude, position.coords.longitude);
if (vm.marker)
map.removeLayer(vm.marker);
vm.marker = L.marker([position.coords.latitude, position.coords.longitude], {}).addTo(map);
map.setView(currLocation, 11, {animation: true});
map.panTo(currLocation);
}, err => {
// alert(JSON.stringify(err))
}, {timeout: 30000, enableHighAccuracy: true, maximumAge: 75000})
} else {
alert("no");
}
},
async modalShown() {
var map = this.$refs.mymap.mapObject;
map.invalidateSize();
this.plotCurrentLocation(map);
},
addMarker(e) {
var map = this.$refs.mymap.mapObject;
// alert(JSON.stringify(this.marker.getLatLng()));
if (this.marker)
map.removeLayer(this.marker);
this.marker = L.marker([e.latlng.lat, e.latlng.lng], {}).addTo(map);
map.panTo(e.latlng);
}
}
}
</script>
Instructions on the npm package works fine. Something like this should work.
Remember to install and import the necessary libraries.
<template>
<div style="height: 300px; width: 100%" class="text-grey-10">
<l-map #click="addMarker" :zoom="zoom" :center="center">
<l-tile-layer :url="url" :attribution="attribution" />
<l-geosearch :options="geosearchOptions"/>
<l-marker v-if="locationMarker" :latlng="locationMarker"/>
</l-map>
</div>
</template>
<script>
import { LMap, LTileLayer, LMarker } from "vue2-leaflet";
import { OpenStreetMapProvider } from "leaflet-geosearch";
import LGeosearch from "vue2-leaflet-geosearch";
export default {
components: {
LMap,
LTileLayer,
LMarker,
LGeosearch
},
data: () => {
geosearchOptions: {
provider: new OpenStreetMapProvider()
}
}
}
</script>

Leaflet and Vuejs. How to add a new Marker onclick in the map?

I would like to add and remove Markers in my Leaflet Map. i found this good topic but the code is in JS.
Leaflet - How to find existing markers, and delete markers?
My code is like that :
<template>
<l-map :zoom="zoom" :center="center">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker :lat-lng="marker" :draggable=true></l-marker>
</l-map>
</template>
<script>
data:function() {
return {
zoom:7,
center: L.latLng(33.901445, -5.532788),
url:'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
attribution:'© OpenStreetMap
contributors',
marker: L.latLng(47.413220, -1.219482),
}},
</script>
Maybe i should start by creating a function on click like that :
<l-map :zoom="zoom" :center="center" v-on:click="addMarker"></l-map>
And then i wrtie the correct addMarker Function in method. But i can't find the right doc for that.
I would like also to get the position of the new Marker in Data..
Thank you
It turns out to be really, really easy. Use an array with v-for instead of a single marker. Click on marker splices out the marker at that index. Click on map creates a new marker with the latlng. The snippet below is based on this fiddle.
var {
LMap,
LTileLayer,
LMarker
} = Vue2Leaflet;
new Vue({
el: '#app',
components: {
LMap,
LTileLayer,
LMarker
},
data() {
return {
zoom: 14,
center: L.latLng(47.413220, -1.219482),
url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
attribution: '© OpenStreetMap contributors',
markers: [
L.latLng(47.412, -1.218),
L.latLng(47.413220, -1.219482),
L.latLng(47.414, -1.22),
]
}
},
methods: {
removeMarker(index) {
this.markers.splice(index, 1);
},
addMarker(event) {
this.markers.push(event.latlng);
}
}
});
html, body, #app {
height: 100%;
margin: 0;
}
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<link href="https://unpkg.com/leaflet#1.0.3/dist/leaflet.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet#1.0.3/dist/leaflet.js"></script>
<script src="https://unpkg.com/vue2-leaflet#1.0.1/dist/vue2-leaflet.js"></script>
<div id="app">
<l-map :zoom="zoom" :center="center" #click="addMarker">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker v-for="marker, index in markers" :lat-lng="marker" #click="removeMarker(index)"></l-marker>
</l-map>
</div>
<