Use OpenLayers 4 with Angular 5
Asked Answered
L

3

19

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?

Limbo answered 16/1, 2018 at 14:37 Comment(0)
E
43

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.

Embellishment answered 17/1, 2018 at 14:18 Comment(8)
Works like a charm, thank you. One last question, I'd like to use cusom tiles, so tiles which are stored locally. To archieve this i changed source to OSM. My route is the following "url: './tiles/{z}/{x}/{y}.png'" but i get a 404 Error. Is it because I have to specify a route to tiles with the route service?Limbo
Puh. Sorry, but I can't help about that. Though, your route looks a bit wired.Embellishment
For custom tiles, make sure you add ./tiles folder to your angular-cli.json as: "assets": [ "assets", "tiles" ],Devout
@AlicW This works, but you should not do it this way, because usually you have a lot of tiles. If you then build your app, all tiles are included: the bundle is going to be huge.Embellishment
The build process will just keep the same tiles subfolder in the output (build) folder. From what I understand, this is how Giuseppe wants to deploy the app anyway, including custom tiles into the distribution.Devout
if i only want user current location details (like google geolocation) how can i retrieve it using opengl maps?Vicar
@federer Feel free to open a new question :)Embellishment
Just a note, I use angular 6 , node 8.11.1, locally on win 10. By using import OlProj from 'ol/Proj'; I get errors. Replace it with import * as OlProj from 'ol/proj'; and it will runThen
X
8

If you do not want to start from zero with Angular5 and OpenLayers4, there is a mature project called IGO2-lib which is based on Angular 5.x, NodeJS, OpenLayers 4.x and Material Design. IGO2 is also a complete framework.

  1. Clone repository using: git clone https://github.com/infra-geo-ouverte/igo2-lib.git
  2. Deploy in cd igo2-lib/ and install from: npm install
  3. Start form: npm start
  4. Open your browser at http://localhost:4200/

Here it is a live demo from IGO2: https://geoegl.msp.gouv.qc.ca/igo2/apercu-qc/

Xanthine answered 3/3, 2018 at 5:16 Comment(2)
Are you affiliated to IGO?Phelia
No, I am more a user of IGO, why?Xanthine
L
0

Use this code into ngAfterViewInit() instead of ngOnInit()

Lisabeth answered 28/3, 2019 at 13:20 Comment(1)
It's more likely to be comment to Other postRosenarosenbaum

© 2022 - 2024 — McMap. All rights reserved.