Map Visualization In Vue using Leaflet
Tags: vue, tutorial
Published: 2020-09-26 13:10:53

In this post, I will be sharing how to use leaflet in Vue to create map visuals.

#**About Leaflet**

Leaflet is the leading open-source JavaScript library for mobile-friendly interactive maps. Weighing just about 39 KB of JS, it has all the mapping features most developers ever need.

Leaflet is designed with simplicity, performance and usability in mind. It works efficiently across all major desktop and mobile platforms, can be extended with lots of plugins, has a beautiful, easy to use and well-documented API and a simple, readable source code that is a joy to contribute to.

Here as I am using Vue, I will be using **Vue2Leaflet**.

#**Why Leaflet?**

Anyone may ask, why leaflet? 

There are many libraries that can provide help for map visualization in Vue. Some of them are :
1>**vue2-google-maps**
2>**vue-choropleth**
3>**MapBox**

The reasons I choose Leaflet  for this article is that:
1>**Leaflet is beginner-friendly:**
 In Google-maps, we have to make an account on GCP, which is not free (paid). Although Google Maps provide the most number of features, it is not easy to understand in the beginning. Also in choropleth, we have to go through many things to get a simple output.

2>**No access token to be generated while using it**:
For using MapBox, we have to get an access token, we don't
have to worry about it in Leaflet.


#**Installation**

To install Vue2Leaflet, use this npm command: 
```
npm install vue2-leaflet leaflet --save
```
#**Getting Started**

Here is the tree hierarchy of my folder :

```
D:.
└───components
    ├───Body
    ├───DataGathering
    ├───Footer
    ├───Header
    ├───HomePage
    │   ├───assets
    │   └───Breads
    ├───MapComponents
    └───Visuals
```
Here, for the Map Visual Purpose only, I will use Body and MapComponents folder Only.

#**Setting Up**

Before using the functionalities of Leaflet, we have to import some important things in **<u>main.js</u>** file.

```
import 'leaflet/dist/leaflet.css';
import { Icon } from "leaflet";

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")
});
```

#**Creating the Map component File**

Create a Map Component ( Map.vue ) in the Body folder ( **<u> Body/Map.vue </u>** ) and import that component in the App.vue.

Write this code in that file:
```
<template>
  <div>
  <MapVisual2></MapVisual2>
  </div>
</template>

<script>
import MapVisual2 from '@/components/MapComponents/MapVisual2'
export default {
  components :{
    MapVisual2,
  }
}
</script>
```
#**Creating the visual component for Map-file**

Create a Visual Component ( MapVisual2.vue ) in the MapComponents folder ( **<u> MapComponents/MapVisual2.vue </u>** ) and import that component in the Map.vue.

Code for the component:

```
<template>
  <div style="height: 80vh">
    <LMap :zoom="zoom" :center="center">
      <LTileLayer :url="url"></LTileLayer>
      <LMarker :lat-lng="[13.1333682,77.5651881]"></LMarker>
      <LMarker :lat-lng="[13.1340669,77.56707]"></LMarker>
      <LMarker :lat-lng="[13.1348904,77.5643231]"></LMarker>
      <LMarker :lat-lng="[13.1367826,77.5711133]"></LMarker>
    </LMap>
  </div>
</template>
      
<script>
import { LMap, LTileLayer, LMarker } from "vue2-leaflet";
export default {
  name: "Map",
  components: {
    LMap,
    LTileLayer,
    LMarker
  },
  data() {
    return {
      url: "https://{s}.tile.osm.org/{z}/{x}/{y}.png",
      zoom: 16,
      center: [13.1367826,77.5711133],
      bounds: null
    };
  }
};
</script>
```
#**Output**
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ky3rwq6j0uo939vbs0er.png)


#**Work with Real-Time Data**
For using this install Axios.
To install Axios, use this command:
```
npm install axios
```

Now , in the same Visual component file add this code:
```
<template>
<div>
  <div style="height: 80vh">
    <LMap  @ready="onReady" @locationfound="onLocationFound" :zoom="zoom" :center="center">
      <LTileLayer :url="url"></LTileLayer>
      
      <ul>
        <li v-for="(l,i) in latlong" :key="i">
            <LMarker :lat-lng="l"></LMarker>
        </li>
      </ul>
      
      
    </LMap>
    
  </div>
  <br/>
    <br/>
    
  </div>

</template>
      
<script>
//import L from 'leaflet';
import { LMap, LTileLayer, LMarker } from "vue2-leaflet";
const axios = require("axios");
export default {
  name: "Map",
  components: {
    LMap,
    LTileLayer,
    LMarker
  },
  data() {
    return {
      url: "https://{s}.tile.osm.org/{z}/{x}/{y}.png",
      zoom: 2,
      center: [13.1367826,77.5711133],
      bounds: null,
      results : null,
      country : [],
      latlong : [],
      confirmed : [],
    };
  },
  methods: {
onReady (mapObject) {
  mapObject.locate();
},
onLocationFound(location){
  console.log(location)
}
},
created() {
    axios.get("https://corona.lmao.ninja/v2/jhucsse")
    .then(r => r["data"])
    .then(data => {
        for(var i=0;i<742;i++){
            if(data[i].country in this.country){
                continue
            }
            else{
                
                if(data[i].coordinates["latitude"]!=null && data[i].coordinates["longitude"]!=null){
                    var a=[]
                    this.country.push(data[i].country)
                    a.push(parseFloat(data[i].coordinates["latitude"]))
                    a.push(parseFloat(data[i].coordinates["longitude"]))
                    this.confirmed.push(data[i].stats["confirmed"])
                    console.log(data[i].country)
                    console.log(data[i].coordinates["latitude"])
                    console.log(data[i].coordinates["longitude"])
                    console.log(data[i].stats["confirmed"])
                    this.latlong.push(a)
                }
            }
        

  }
  console.log(this.latlong)
    }
      
  )
}
};
</script>
```
#**Output**
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/es46tlj5f1rxmxasg27r.png)
<center><h1 style="font-weight : bold">That's the End</h1></center>
<img src="https://i.gifer.com/origin/46/46eae4c4ff91c03514a7096538740b42_w200.gif"/>