A Simple Guide to OpenLayers in Angular

Paul Harwood
May 31, 2020 · 4 min read

How to use the powerful mapping library in Angular

Having been using Leaflet for mapping in Angular and writing about how to do it, I have now been working on some mapping projects using OpenLayers.

Why OpenLayers

… Why change to OpenLayers?

Leaflet is a great library and it is very easy to quickstart simple projects. It needs very little set up and has a large library of controls and extensions. However, if you want to go beyond the basics, particularly in terms of complicated projection manipulation or wanting to have real GIS symbology on the layers (i.e. programmatic control of the shape, size and colour of features) as opposed to simple markers, Leaflet runs out of steam quite fast. It is a bit like Google Maps in that regard.

OpenLayers (OL) is, to my mind, much more powerful but tends to have a higher cost to learn and to start a project because of that. OL also expects you to understand mapping and build your own components and controls. Probably too much for my mind. The best thing about Leaflet is the wealth of 3rd party controls. This is not really true of OL.

I needed to do some sites that needed real GIS symbology. So I moved to OpenLayers.

OpenLayers in Angular

While there are similar modules for OL, I have to say that my impression was that they are not actively managed. I also felt that, given that OL is much better behaved as a Class-based JS library and has an officially supported @types definition, a wrapper would not be required.

So — we are doing this naked:).

We still have the problem that mapping applications create a storm of UI events as you move the map around. We want that interaction to be as smooth as possible so we want to keep those events away from the Angular Change Detection system.

To do that, we are going to have to get involved in Zones. If you want an overview of what Zones are you can do worse than reading this …

We want to run OL in the outside zone so that ChangeDetection is not triggered. This is achieved by creating a NgZone Service and calling .runOutsideAngular(). This will mean that we need to manually run ChangeDetection if there are events coming from OL that need to update parts of the Angular app. This will be done using ChangeDetectorRef.

Getting Started

npm install ol
npm install @types/ol
npm install proj4
npm install @types/proj4

Then there are the usual problems with CSS. You need to load the ol.css and there are many ways to do that. I usually choose to put the following in styles.scss …

@import "../node_modules/ol/ol.css";

Note : this method does not work with StackBlitz. In SB examples, the working solution I have found is to put <link rel=”stylesheet” href=”https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.3.1/css/ol.css" type=”text/css”> in index.html.

This should be enough to enable your project for OpenLayers.

Basic Map

This allows the map to be created by the following HTML …

<app-ol-map class="map"
[center]="[-483281,6904172]"
[zoom]="8.5"
(mapReady)="onMapReady($event)"
></app-ol-map>

Note that this is all happening in EPSG:3857, the CRS for OSM. It could be made more generic but that would complicate things too much at this stage. I have used proj4js to explicitly instantiate the projection for EPSG:3857, partly to show how it is done and partly because I have had some strange behaviours in the past with the inbuilt conversions to 3857. Details are linked in the resources.

The map should be initialised from NgInitView, since we want the dom to be created before we start. The calling function looks like this :

ngAfterViewInit():void {
if (! this.Map) {
this.zone.runOutsideAngular(() => this.initMap())
}
setTimeout(()=>this.mapReady.emit(this.Map));
}

As you can see if the map does not exist, we are creating it using runOutsideAngular. The map is actually created by initMap, which is fairly straight forward OL code to create an OSM map (the full code is shown below in Resources).

The mapReady.emit command is triggered after a very short timeout. This is a simple way to avoid the error messages you get when things have changed during the change detection cycle.

With that you have a fully functional OL map integrated into Angular 9 in a fairly generic way.

Read This Next

Resources

The full code for the ol-map component can also be seen in this gist …

The API for OpenLayers 6 is documented here.

The API for Proj4js and how it is used in this example to create a named projection is shown here.

You can get the CRS definition strings from epsg.io.

Runic Software

Some learnings about how to make somethings work

Paul Harwood

Written by

Paul is a long time veteran of the tech industries — with 30 years in the trenches including stints with Nokia and Google as well as startups QR8 and trackbash.

Runic Software

Some learnings about how to make somethings work

Paul Harwood

Written by

Paul is a long time veteran of the tech industries — with 30 years in the trenches including stints with Nokia and Google as well as startups QR8 and trackbash.

Runic Software

Some learnings about how to make somethings work

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store