Search code examples
angularopenlayersangular5

Use OpenLayers 4 with Angular 5


I'm trying to use OpenLayers 4 in Angular 5.

Basically I just want to implement the QuickStart example from the official OpenLayers Site.

What I have done so far:

  1. npm install ol --save to download the ol package
  2. angular-cli.json added those lines to the angular-cli.json. Saw that this has to be done on another example on Stackoverflow. The ol.css file exists. The ol.js file doesnt. So I don't know if this is the right or the wrong way but it can clearly not work.

My angular project consists of 3 components:

 -app
 --console
 --map
 --sidebar

 app.component.css
 app.compinent.html
 app.component.spec.ts
 app.component.ts
 app.module.ts

map.component.html

import { Component, OnInit } from '@angular/core';
import * as ol from '../../../node_modules/ol';

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
  mapId: string;
  map: ol.Map = undefined;

  constructor() { }

  ngOnInit() {
    this.map = new ol.Map({
      target: this.mapId,
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM(),
        }),
      ],
      view: new ol.View({
        center: ol.proj.fromLonLat([6.661594, 50.433237]),
        zoom: 3,
      })
    });
  }
}

Can anyone tell how to get this working correctly?


Solution

  • Edit: An example with Angular 14 and OpenLayers 7 can be found on GitHub.

    Updated to Angular 8.x and OpenLayers 6.x:

    Install ol and do the following changes:

    1.) Add the accordant CSS in the html.index (make sure that the version of the CSS matches the installed version of ol) :

    <link rel="stylesheet" href="https://openlayers.org/en/v6.1.1/css/ol.css" type="text/css">
    

    Another way is to reference the CSS in the styles object within the angular.json:

    "styles": [
      "./node_modules/ol/ol.css",
      "src/styles.scss"
    ],
    

    2.) Create a map in app.component.ts:

    import { AfterViewInit, Component } from '@angular/core';
    import { defaults as defaultControls } from 'ol/control';
    
    import Map from 'ol/Map';
    import View from 'ol/View';
    import TileLayer from 'ol/layer/Tile';
    import XYZ from 'ol/source/XYZ';
    import ZoomToExtent from 'ol/control/ZoomToExtent';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    
    export class AppComponent implements AfterViewInit {
    
      map: Map;
    
      ngAfterViewInit() {
        this.map = new Map({
          target: 'map',
          layers: [
            new TileLayer({
              source: new XYZ({
                url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
              })
            })
          ],
          view: new View({
            center: [813079.7791264898, 5929220.284081122],
            zoom: 7
          }),
          controls: defaultControls().extend([
            new ZoomToExtent({
              extent: [
                813079.7791264898, 5929220.284081122,
                848966.9639063801, 5936863.986909639
              ]
            })
          ])
        });
      }
    }
    

    3.) Some style in app.component.css:

    .map {
      width: 100%;
      height: 100vh;
    }
    

    4.) And finally the markup in app.component.html:

    <div id="map" class="map"></div>
    

    Feel also free to take a look at my GitHub repo.

    Edit:

    As stated by Bhalchandra Bhosale it might be even better to set the target of the map within ngAfterViewInit:

    export class MapComponent implements OnInit, AfterViewInit {
    
      ...
    
      ngAfterViewInit() {
        this.map.setTarget('map');
      }
    }
    

    Old answer for version 5.2 of ol:

    ol is the right package for OpenLayers. However, you do not need to add anything in the angular-cli.json.

    With the recent update ("ol": "^5.2.0") the way of importing classes and functions of OpenLayers changed a bit.

    map.component.ts:

    import { Component, OnInit } from '@angular/core';
    
    import OlMap from 'ol/Map';
    import OlXYZ from 'ol/source/XYZ';
    import OlTileLayer from 'ol/layer/Tile';
    import OlView from 'ol/View';
    
    import { fromLonLat } from 'ol/proj';
    
    @Component({
      selector: 'app-map',
      templateUrl: './map.component.html',
      styleUrls: ['./map.component.css']
    })
    
    export class MapComponent implements OnInit {
    
      map: OlMap;
      source: OlXYZ;
      layer: OlTileLayer;
      view: OlView;
    
      ngOnInit() {
        this.source = new OlXYZ({
          url: 'http://tile.osm.org/{z}/{x}/{y}.png'
        });
    
        this.layer = new OlTileLayer({
          source: this.source
        });
    
        this.view = new OlView({
          center: fromLonLat([6.661594, 50.433237]),
          zoom: 3
        });
    
        this.map = new OlMap({
          target: 'map',
          layers: [this.layer],
          view: this.view
        });
      }
    }
    

    map.component.html:

    <div id="map" class="map"></div>
    

    map.component.css:

    .map {
      width: 100%;
      height: 100vh;
    }
    

    Add the CSS of OpenLayers within the header-tag of index.html:

    <link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.1.3/css/ol.css" type="text/css">
    <style>html, body { margin: 0; }</style>
    

    Even older answer:

    Your component might look like the following:

    import {Component, OnInit} from '@angular/core';
    
    import OlMap from 'ol/map';
    import OlXYZ from 'ol/source/xyz';
    import OlTileLayer from 'ol/layer/tile';
    import OlView from 'ol/view';
    import OlProj from 'ol/proj';
    
    @Component({
      selector: 'app-map',
      templateUrl: './map.component.html',
      styleUrls: ['./map.component.css']
    })
    
    export class MapComponent implements OnInit {
    
      map: OlMap;
      source: OlXYZ;
      layer: OlTileLayer;
      view: OlView;
    
      constructor() {
      }
    
      ngOnInit() {
        this.source = new OlXYZ({
          url: 'http://tile.osm.org/{z}/{x}/{y}.png'
        });
    
        this.layer = new OlTileLayer({
          source: this.source
        });
    
        this.view = new OlView({
          center: OlProj.fromLonLat([6.661594, 50.433237]),
          zoom: 3
        });
    
        this.map = new OlMap({
          target: 'map',
          layers: [this.layer],
          view: this.view
        });
      }
    }
    

    CSS:

    .map {
      width: 100%;
      height: 100vh;
    }
    

    HTML:

    <div id="map" class="map"></div>
    

    Let me know if this solution works for you.