DEV Community

Cover image for Building a Map Application with Amplify Geo and Vue.js
Yasunori Kirimoto for AWS Community Builders

Posted on • Edited on

Building a Map Application with Amplify Geo and Vue.js

img

I built a map application using Amplify Geo and Vue.js πŸŽ‰

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!

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

Setting up Amplify Geo

First, we will configure Amplify Geo.
Add location feature (map)

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!

amplify add geo
Enter fullscreen mode Exit fullscreen mode
amplify push
Enter fullscreen mode Exit fullscreen mode

This completes the configuration of Amplify Geo.

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.

execution environment

  • node v16.10.0
  • npm v7.24.0

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

npm install maplibre-gl@1.15.2
Enter fullscreen mode Exit fullscreen mode
npm install maplibre-gl-js-amplify
Enter fullscreen mode Exit fullscreen mode

Overall composition

img

package.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"
  ]
}
Enter fullscreen mode Exit fullscreen mode

/src

main.js

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');
Enter fullscreen mode Exit fullscreen mode

Load MapLibre GL JS.

import 'maplibre-gl/dist/maplibre-gl.css'
Enter fullscreen mode Exit fullscreen mode

/src/views

Home.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>
Enter fullscreen mode Exit fullscreen mode

Set the map component.

<MapPane></MapPane>
Enter fullscreen mode Exit fullscreen mode

Loads the map component.

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

export default {
    name: 'home',
    components: {
        MapPane
    }
}
Enter fullscreen mode Exit fullscreen mode

/src/components

MapPane.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>
Enter fullscreen mode Exit fullscreen mode

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

import { createMap, drawPoints } from 'maplibre-gl-js-amplify';
Enter fullscreen mode Exit fullscreen mode

Set up the map in MapLibre GL JS Amplify.

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

Set the marker in MapLibre GL JS Amplify.

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'
        },
    }
);
Enter fullscreen mode Exit fullscreen mode

Let's check with a simple local server.

npm run serve
Enter fullscreen mode Exit fullscreen mode

Start up a local server and try logging in πŸ’‘

img

I was able to build a map application using Amplify Geo combined with Vue.js πŸ‘

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 πŸ‘

Top comments (0)