Building a Map Application with Amplify Geo and Vue.js
Tags: amazonlocationservice, vue, awsamplify, maplibre
Published: 2021-11-15 10:31:53

![img](https://day-journal.com/memo/images/try-068_01.png)
<br>

### I built a map application using Amplify Geo and Vue.js :tada:  

Amplify Geo was officially released to the public the other day, so I got to try it out.
Amplify Geo is a feature of AWS Amplify that allows you to build Amazon Location Service easier!

<br>

Advance Preparation
- Setting up AWS Amplify and Vue.js to the login feature

[Building a login function with AWS Amplify, Amplify UI Vue, and Vue 3](https://dev.to/aws-builders/building-a-login-function-with-aws-amplify-amplify-ui-vue-and-vue-3-4043)
<br>

## Setting up Amplify Geo
First, we will configure Amplify Geo.
[Add location feature (map)](https://day-journal.com/memo/aws-amplify-004)

<br>

If you only need a location function (geocoding), you can implement it with these two commands as same as the map function!
Amazon Location Service requires AWS console configuration and role configuration, but Amplify Geo does all of that for you!

```sh
amplify add geo
```

```sh
amplify push
```

This completes the configuration of Amplify Geo.

<br>

## Frontend
Next, let's build the actual map application.

Once Amplify and Vue.js are configured, it's just a matter of adding a new "MapPane.vue" and changing some of the code.

<br>

execution environment
- node v16.10.0  
- npm v7.24.0 

<br>

Install MapLibre GL JS v1 and MapLibre GL JS Amplify, a wrapper library, in advance.


```sh
npm install maplibre-gl@1.15.2
```

```sh
npm install maplibre-gl-js-amplify
```

<br>

Overall composition

![img](https://day-journal.com/memo/images/try-068_02.png)


#### package.json

```json
{
  "name": "amplify-geo",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@aws-amplify/ui-components": "^1.9.2",
    "aws-amplify": "^4.3.4",
    "core-js": "^3.6.5",
    "maplibre-gl": "^1.15.2",
    "maplibre-gl-js-amplify": "^1.1.2",
    "vue": "^3.0.0",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^7.0.0"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/vue3-essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}
```

<br>

/src

#### main.js

```javascript
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'maplibre-gl/dist/maplibre-gl.css'

import {
  applyPolyfills,
  defineCustomElements
} from '@aws-amplify/ui-components/loader';
import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);

applyPolyfills().then(() => {
  defineCustomElements(window);
});

const app = createApp(App);
app.config.isCustomElement = tag => tag.startsWith('amplify-');
app.use(store).use(router).mount('#app');
```

<br>

Load MapLibre GL JS.

```javascript
import 'maplibre-gl/dist/maplibre-gl.css'
```

<br>

/src/views

#### Home.vue

```vue
<template>
  <div class="home">
    <h2>Amplify Geo</h2>
    <MapPane></MapPane>
    <amplify-sign-out></amplify-sign-out>
  </div>
</template>

<script>
import MapPane from '@/components/MapPane.vue'

export default {
  name: 'Home',
  components: {
    MapPane
  }
}
</script>
```

<br>

Set the map component.

```vue
<MapPane></MapPane>
```

<br>

Loads the map component.

```javascript
import MapPane from '@/components/MapPane.vue'

export default {
    name: 'home',
    components: {
        MapPane
    }
}
```

<br>

<br>

/src/components

#### MapPane.vue

```vue
<template>
    <div class='mapPane'>
        <div id='map'></div>
    </div>
</template>

<script>
    import { createMap, drawPoints } from 'maplibre-gl-js-amplify';

    export default {
        name: 'MapPane',
        data() {
            return {
            }
        },
        mounted: async function () {
            this.mapCreate();
        },
        methods: {
            mapCreate: async function() {
                const map = await createMap({
                    container: 'map',
                    center: [139.7648, 35.6794],
                    zoom: 15,
                    bearing: 64.8,
                    pitch: 60,
                    hash: true,
                });

                map.on('load', function () {
                    drawPoints('pointsSource',
                        [
                            {
                                coordinates: [139.7646, 35.6827],
                                title: 'Point01',
                                address: 'Main Points',
                            },
                            {
                                coordinates: [139.7720, 35.6768],
                                title: 'Point02',
                            },
                            {
                                coordinates: [139.7607, 35.6759],
                            },
                        ],
                        map,
                        {
                            showCluster: true,
                            unclusteredOptions: {
                                showMarkerPopup: true,
                                defaultColor: '#005773'
                            },
                            clusterOptions: {
                                showCount: true,
                                fillColor: '#005773'
                            },
                        }
                    );
                });
            }
        }
    }
</script>

<style scoped>
    #map {
        z-index: 0;
        height: 800px;
    }
</style>
```

<br>

Load the map and marker functions in MapLibre GL JS Amplify.

```javascript
import { createMap, drawPoints } from 'maplibre-gl-js-amplify';
```

<br>

Set up the map in MapLibre GL JS Amplify.

```javascript
const map = await createMap({
    container: 'map',
    center: [139.7648, 35.6794],
    zoom: 15,
    bearing: 64.8,
    pitch: 60,
    hash: true,
});
```

<br>

Set the marker in MapLibre GL JS Amplify.

```javascript
drawPoints('pointsSource',
    [
        {
            coordinates: [139.7646, 35.6827],
            title: 'Point01',
            address: 'Main Points',
        },
        {
            coordinates: [139.7720, 35.6768],
            title: 'Point02',
        },
        {
            coordinates: [139.7607, 35.6759],
        },
    ],
    map,
    {
        showCluster: true,
        unclusteredOptions: {
            showMarkerPopup: true,
            defaultColor: '#005773'
        },
        clusterOptions: {
            showCount: true,
            fillColor: '#005773'
        },
    }
);
```

<br>

Let's check with a simple local server.

```shell
npm run serve
```

<br>

Start up a local server and try logging in :bulb: 

![img](https://day-journal.com/memo/images/try-068_00.gif)  

#### I was able to build a map application using Amplify Geo combined with Vue.js :thumbsup: 

Using Amplify Geo eliminates the need to configure roles and settings in the AWS console, making it easier to build than using Amazon Location Service as it is. However, when customizing beyond the existing functions, MapLibre GL JS needs to be directly loaded and developed, and it seems that more complex customization can be done by using it in combination with the necessary parts of Amplify Geo. I'll keep exploring this :thumbsup: