Getting Started with Here Maps and Web Components using Lit
Originally published at labs.thisdot.co
Aug 5, 2021 · 6 minutes read · Follow @luixaviles
In the past months, I have been actively working on the development of geolocation-oriented solutions in web applications. My experience has been good so far, taking into account the availability of modern tools and libraries, with a wide range of features that even enable the use of interactive maps and location services.
In this article, I’ll explain how to integrate Here Maps through web components, using Lit and TypeScript, in just a few steps.
Introduction
Let’s start by explaining the technologies that we will be integrating into this post, step by step.
Lit
Lit is the next-generation library for creating simple, fast, and lightweight web components.
One of the benefits of using Lit is the power of interoperability, which means that your web components can be integrated within any framework, or can even be used on their own. This is possible since we’re talking about native web components that can be rendered in any modern web browser.
If you’re interested in learning more about this technology, you can take a look at the LitElement Series that has been published in this blog.
Here Maps
Let’s say your application requires real-time navigation, the creation of custom maps, or the ability to visualize datasets over a map. HERE Maps meet these requirements without too much effort.
In fact, there is a Maps API for JavaScript, which can be used to build web applications using either JavaScript or TypeScript.
Note
Although this guide provides an API key for testing purposes only, you may need to register your app, and get your API Key to move forward with your applications.
Creating the Project
Project Scaffolding
An easy way to initialize an application is through the project generator from the Open Web Components initiative. They provide a set of tools and guides to create a web components application, adding the testing, linting, and build support in the beginning.
Let’s create the project using a command-line interface
npm init @open-wc
# Select "Scaffold a new project" (What would you like to do today?)
# Select "Application" (What would you like to scaffold?)
# You can select any option for (What would you like to add?)
# Yes (Would you like to use TypeScript?)
# Mark/Select "Testing", "Demoing" and "Building" (Would you like to scaffold examples files for?)
# spa-heremaps-lit (What is the tag name of your application/web component?)
# Yes (Do you want to write this file structure to disk?)
# Yes, with npm (Do you want to install dependencies?)
Pay attention to the project structure that is generated. Also, take a look at your package.json
file to review the dependencies and scripts that have been added.
Update to Lit
In case you generated a project based on LitElement, it shouldn’t be complicated to replace dependencies with lit
:
- Install the last version of Lit
npm install --save lit
- Uninstall
LitElement
andlit-html
library
npm uninstall lit-element lit-html
Also, you can make sure to update the imports as follows to make it work:
import { LitElement, html, css } from 'lit';
import { customElement, property } from 'lit/decorators.js';
Next, make sure the preview of the application is working fine using the following command:
npm run start
Creating a Map Component
Installing Here Maps
Before creating a web component that will render a map, you are required to load the API code libraries in our index.html
file:
<link
rel="stylesheet"
type="text/css"
href="https://js.api.here.com/v3/3.1/mapsjs-ui.css"
/>
<script
src="https://js.api.here.com/v3/3.1/mapsjs-core.js"
type="text/javascript"
charset="utf-8"
></script>
<script
src="https://js.api.here.com/v3/3.1/mapsjs-service.js"
type="text/javascript"
charset="utf-8"
></script>
<script
src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"
type="text/javascript"
charset="utf-8"
></script>
<script
src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"
type="text/javascript"
charset="utf-8"
></script>
You can see HERE Maps API for JavaScript Modules for more information about each imported script.
Since the initial project is based on TypeScript, we may need to install the type definitions for the HERE Maps API.
npm install --save-dev @types/heremaps
Now we’re ready to go and code the web component using TypeScript.
The Map Component Implementation
Let’s create a src/map/map.ts
file with the following content:
// map.ts
import { LitElement, html, css } from 'lit';
import { customElement, property } from 'lit/decorators.js';
@customElement('spa-map')
export class Map extends LitElement {
static styles = css`
:host {
display: block;
width: 100%;
height: 100vh;
}
`;
@property({ type: Object }) location: H.geo.IPoint = {
lat: 40.71427,
lng: -74.00597,
};
render() {
return html`
<link
rel="stylesheet"
type="text/css"
href="https://js.api.here.com/v3/3.1/mapsjs-ui.css"
/>
<div id="spa-map" style="width:100%; height:100vh"></div>
`;
}
}
The above code snippet allows the definition of a new custom element through the @customElement
decorator. Also, it defines the location
value as a component property so that it can be configured later as:
<spa-map .location="${VALUE}"></spa-map>
Also, the render
method is ready to return a TemplateResult
object which contains a div
element that will be rendered in all the available space. The <div>
element is the HTML container in which the map will be rendered later.
To finish the component implementation, we’ll need to write the firstUpdated
method.
// map.ts
@customElement('spa-map')
export class Map extends LitElement {
// Other methods/properties defined above...
firstUpdated() {
const platform = new H.service.Platform({
apikey: '<API_KEY>',
});
const defaultLayers = platform.createDefaultLayers();
const divContainer = this.shadowRoot?.getElementById(
'spa-map'
) as HTMLDivElement;
const map = new H.Map(divContainer, defaultLayers.vector.normal.map, {
center: this.location,
zoom: 10,
pixelRatio: window.devicePixelRatio || 1,
});
const behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
const ui = H.ui.UI.createDefault(map, defaultLayers);
window.addEventListener('resize', () => map.getViewPort().resize());
}
}
Before creating the map object, it’s required to initialize the communication with the back-end services provided by HERE maps. In that way, an H.service.Platform
object is created using the <API_Key>
value you got in previous steps.
However, most of the code in the previous block has to do with the initialization of the map:
- An instance of
H.Map
class is created specifying the container element, the map type to use, the geographic coordinates to be used to center the map, and a zoom level. - In case you need to make your map interactive, an
H.mapevents.Behavior
object can be created to enable the event system through aMapEvents
instance. - On other hand, the default UI components for the map can be added using the
H.ui.UI.createDefault
method. - The
resize
listener can be used to make sure the map is rendered in the entire container.
Using the Map Component
As a final step, we’ll need to update the spa-heremaps-lit.ts
file:
import { LitElement, html, css } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import './map/map';
@customElement('spa-heremaps-lit')
export class SpaHeremapsLit extends LitElement {
static styles = css`
:host {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
font-size: calc(10px + 2vmin);
color: #1a2b42;
max-width: 960px;
margin: 0 auto;
text-align: center;
}
`;
render() {
return html` <spa-map></spa-map> `;
}
}
Since this class defines a new custom element as a container for the map component, it’s required to import the previous component definition using import './map/map'
.
Then, inside the class definition we can find:
- The
static styles
attribute defines the styles for the component using a tagged template literal(css
) - The
render
method returns the HTML content through a template literal(html
).- The HTML content uses the previous custom element we created:
<spa-map></spa-map>
- The HTML content uses the previous custom element we created:
The screenshot shows the map rendered in the main component of the application.
Source Code of the Project
Find the latest version of this project in this GitHub repository: spa-heremaps-lit. If you want to see the final code for this article, take a look at 01-setup-lit-heremaps tag. Do not forget to give it a star ⭐️ and play around with the code.
Feel free to reach out on Twitter if you have any questions. Follow me on GitHub to see more about my work.