admin管理员组

文章数量:1425742

I'm trying to use OpenLayers with Angular 5. I'm testing different ways to implement maps, I've already tested Leaflet and OpenLayers in simple HTML files and I've choosed to use OpenLayers which is more efficient in my case.

With this map I want to switch between different layers (with ol-layerswitcher), place markers according to a GeoJSON file and display popups. All these features are well working in my HTML file and now, I want to do the same thing with Angular 5 (not with angular-openlayers-directive) !

I have adapted my HTML code in Angular in my appponent.ts file, the markers are displayed according to my GeoJSON file, my layer-switcher too but I have problems with two functions : forEachFeatureatPixel and getEventPixel ...

Here is my src/app/appponent.ts :

import { Component, OnInit } from '@angular/core';

import OlMap from 'ol/map';
import OlWMS from 'ol/source/tilewms';
import OlTileLayer from 'ol/layer/tile';
import OlView from 'ol/view';
import olProj from 'ol/proj';
import VectorLayer from 'ol/layer/vector';
import VectorSource from 'ol/source/vector';
import Point from 'ol/geom/point';
import Style from 'ol/style/style';
import IconStyle from 'ol/style/icon';
import WFS from 'ol/format/wfs';
import GeoJSON from 'ol/format/geojson';
import Overlay from 'ol/overlay';
import feature from 'ol/feature';
import OlSwitch from 'ol-layerswitcher/src/ol-layerswitcher';
import CanvasMap from 'ol/canvasmap';
//import evt from 'ol/mapbrowserevent';
//import mbe from 'ol/mapbrowsereventtype';

@Component({
  selector: 'app-root',
  templateUrl: './appponent.html',
  styleUrls: ['./appponent.css']
})

export class AppComponent implements OnInit {

  map: OlMap;
  gny_bright: OlWMS;
  gny_bright_mobile: OlWMS;
  layer: OlTileLayer;
  view: OlView;
  layerSwitcher: OlSwitch;
  WFS: WFS;
  vectorLayer: VectorLayer;
  sourceLayer: VectorSource;
  feature: feature;
  evt: evt;
  mbe: mbe;
  //parkvert: IconStyle;
  //parkorange: Style;
  //parkrouge: Style;
  //parknoir: Style;

  constructor() {
  }

  ngOnInit() {

    this.gny_bright = new OlWMS({
      url: '...',
      params: {...},
      attributions: '...'
    });

    this.gny_bright_mobile = new OlWMS({
      url: '...',
      params: {...},
      attributions: '...'
    });

    var parkvert = new Style({
      image: new IconStyle(({
        anchor: [0.5, 46],
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        src: 'assets/image/parking-vert.png'
      }))
    });

    var parkorange = new Style({
      image: new IconStyle(({
        anchor: [0.5, 46],
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        src: 'assets/image/parking-orange.png'
      }))
    });

    this.view = new OlView({
      center: [689805.19, 6222389.4],
      minZoom: 1,
      maxZoom: 19,
      zoom: 2
    });

    this.sourceLayer = new VectorSource({
      url: 'url_to_my_geojson_file',
      format: new GeoJSON()
    });

    this.vectorLayer = new VectorLayer({
      source: this.sourceLayer
    });

    this.map = new OlMap({
      target: 'map',
      layers: [
        new OlTileLayer({
          title: 'gny_bright_mobile',
          source: this.gny_bright_mobile,
          type: 'base',
          attributions: '...'
        }),
        new OlTileLayer({
          title: 'gny_bright',
          source: this.gny_bright,
          type: 'base',
          attributions: '...'
        })
      ],
      view: this.view
    });

    var markers = function style(feature, resolution) {
      if (feature.get('PLACES') == null) {
        return parknoir;

      } else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.05) {
        return parkrouge;

      } else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.15){
        return parkorange;

      } else if(feature.get('PLACES') > feature.get('CAPACITE') * 0.15) {
        return parkvert;
      }
    }

    this.vectorLayer.setStyle(markers);

    //popup

    var element = document.getElementById('popup');

    var popup = new Overlay({
      element: element,
      autoPan: true,
      offset: [0, -30]
    });

  this.map.addOverlay(popup);

  var content_element = document.getElementById('popup-content');
  var closer = document.getElementById('popup-closer');

  closer.onclick = function() {
        popup.setPosition(undefined);
        closer.blur();
        return false;
    };

    this.map.on('click', function(evt){
        this.feature = this.map.forEachFeatureAtPixel(evt.pixel,
          function(feature) {
            return this.feature;
          });
          if (this.feature) {
            var geometry = this.feature.getGeometry();
            var coord = geometry.getCoordinates();

            if(this.feature.get('NOM')!=null) {
              var content = '<center><h2>' + this.feature.get('NOM') + '</h2></center>' + '<br>';
            }

            if(this.feature.get('ADRESSE')!=null) {
              content += '<h5>' + '<i>Adresse : </i>' + this.feature.get('ADRESSE') + '</h5>';
            }

            if(this.feature.get('CAPACITE')!=null) {
              content += '<h5>' + '<i>Capacité : </i>' + this.feature.get('CAPACITE') + '</h5>';
            }

            if(this.feature.get('PLACES')!=null) {
              content += '<h5>' + '<i>Places disponibles : </i>' + this.feature.get('PLACES') + '<h5>';
            }

            content_element.innerHTML = content;
            popup.setPosition(coord);
        }
    });

    this.map.on('pointermove', function(e) {
        if (e.dragging) {
          return;
        };

        var pixel = this.map.getEventPixel(e.originalEvent);
        var hit = this.map.hasFeatureAtPixel(pixel);

        this.map.getViewport().style.cursor = hit ? 'pointer' : '';
    });

    this.map.addControl(this.vectorLayer);
    this.layerSwitcher = new OlSwitch();
    this.map.addControl(this.layerSwitcher);
  }
}

My src/app/appponent.html :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  </head>

    <body>
        <div id="map" class="map"></div>
        <div id="popup" class="ol-popup">
          <a href="#" id="popup-closer" class="ol-popup-closer"></a>
          <div id="popup-content"></div>
        </div>
    </body>

</html>

My src/app/appponent.css :

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

My styles.css :

html, body {
  margin: 0px;
}

/* You can add global styles to this file, and also import other style files */
.ol-box {
  box-sizing: border-box;
  border-radius: 2px;
  border: 2px solid blue;
}

.ol-mouse-position {
  top: 8px;
  right: 8px;
  position: absolute;
}

.ol-scale-line {
  background: rgba(0,60,136,0.3);
  border-radius: 4px;
  bottom: 8px;
  left: 8px;
  padding: 2px;
  position: absolute;
}
.ol-scale-line-inner {
  border: 1px solid #eee;
  border-top: none;
  color: #eee;
  font-size: 10px;
  text-align: center;
  margin: 1px;
  will-change: contents, width;
}
.ol-overlay-container {
  will-change: left,right,top,bottom;
}

.ol-unsupported {
  display: none;
}
.ol-viewport, .ol-unselectable {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
}
.ol-selectable {
  -webkit-touch-callout: default;
  -webkit-user-select: auto;
  -moz-user-select: auto;
  -ms-user-select: auto;
  user-select: auto;
}
.ol-grabbing {
  cursor: -webkit-grabbing;
  cursor: -moz-grabbing;
  cursor: grabbing;
}
.ol-grab {
  cursor: move;
  cursor: -webkit-grab;
  cursor: -moz-grab;
  cursor: grab;
}
.ol-control {
  position: absolute;
  background-color: rgba(255,255,255,0.4);
  border-radius: 4px;
  padding: 2px;
}
.ol-control:hover {
  background-color: rgba(255,255,255,0.6);
}
.ol-zoom {
  top: .5em;
  left: .5em;
}
.ol-rotate {
  top: .5em;
  right: .5em;
  transition: opacity .25s linear, visibility 0s linear;
}
.ol-rotate.ol-hidden {
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s linear, visibility 0s linear .25s;
}
.ol-zoom-extent {
  top: 4.643em;
  left: .5em;
}
.ol-full-screen {
  right: .5em;
  top: .5em;
}
@media print {
  .ol-control {
    display: none;
  }
}

.ol-control button {
  display: block;
  margin: 1px;
  padding: 0;
  color: white;
  font-size: 1.14em;
  font-weight: bold;
  text-decoration: none;
  text-align: center;
  height: 1.375em;
  width: 1.375em;
  line-height: .4em;
  background-color: rgba(0,60,136,0.5);
  border: none;
  border-radius: 2px;
}
.ol-control button::-moz-focus-inner {
  border: none;
  padding: 0;
}
.ol-zoom-extent button {
  line-height: 1.4em;
}
.ol-pass {
  display: block;
  font-weight: normal;
  font-size: 1.2em;
  will-change: transform;
}
.ol-touch .ol-control button {
  font-size: 1.5em;
}
.ol-touch .ol-zoom-extent {
  top: 5.5em;
}
.ol-control button:hover,
.ol-control button:focus {
  text-decoration: none;
  background-color: rgba(0,60,136,0.7);
}
.ol-zoom .ol-zoom-in {
  border-radius: 2px 2px 0 0;
}
.ol-zoom .ol-zoom-out {
  border-radius: 0 0 2px 2px;
}


.ol-attribution {
  text-align: right;
  bottom: .5em;
  right: .5em;
  max-width: calc(100% - 1.3em);
}

.ol-attribution ul {
  margin: 0;
  padding: 0 .5em;
  font-size: .7rem;
  line-height: 1.375em;
  color: #000;
  text-shadow: 0 0 2px #fff;
}
.ol-attribution li {
  display: inline;
  list-style: none;
  line-height: inherit;
}
.ol-attribution li:not(:last-child):after {
  content: " ";
}
.ol-attribution img {
  max-height: 2em;
  max-width: inherit;
  vertical-align: middle;
}
.ol-attribution ul, .ol-attribution button {
  display: inline-block;
}
.ol-attribution.ol-collapsed ul {
  display: none;
}
.ol-attribution.ol-logo-only ul {
  display: block;
}
.ol-attribution:not(.ol-collapsed) {
  background: rgba(255,255,255,0.8);
}
.ol-attribution.ol-uncollapsible {
  bottom: 0;
  right: 0;
  border-radius: 4px 0 0;
  height: 1.1em;
  line-height: 1em;
}
.ol-attribution.ol-logo-only {
  background: transparent;
  bottom: .4em;
  height: 1.1em;
  line-height: 1em;
}
.ol-attribution.ol-uncollapsible img {
  margin-top: -.2em;
  max-height: 1.6em;
}
.ol-attribution.ol-logo-only button,
.ol-attribution.ol-uncollapsible button {
  display: none;
}

.ol-zoomslider {
  top: 4.5em;
  left: .5em;
  height: 200px;
}
.ol-zoomslider button {
  position: relative;
  height: 10px;
}

.ol-touch .ol-zoomslider {
  top: 5.5em;
}

.ol-overviewmap {
  left: 0.5em;
  bottom: 0.5em;
}
.ol-overviewmap.ol-uncollapsible {
  bottom: 0;
  left: 0;
  border-radius: 0 4px 0 0;
}
.ol-overviewmap .ol-overviewmap-map,
.ol-overviewmap button {
  display: inline-block;
}
.ol-overviewmap .ol-overviewmap-map {
  border: 1px solid #7b98bc;
  height: 150px;
  margin: 2px;
  width: 150px;
}
.ol-overviewmap:not(.ol-collapsed) button{
  bottom: 1px;
  left: 2px;
  position: absolute;
}
.ol-overviewmap.ol-collapsed .ol-overviewmap-map,
.ol-overviewmap.ol-uncollapsible button {
  display: none;
}
.ol-overviewmap:not(.ol-collapsed) {
  background: rgba(255,255,255,0.8);
}
.ol-overviewmap-box {
  border: 2px dotted rgba(0,60,136,0.7);
}

.ol-overviewmap .ol-overviewmap-box:hover {
  cursor: move;
}

.layer-switcher.shown.ol-control {
  background-color: transparent;
}

.layer-switcher.shown.ol-control:hover {
  background-color: transparent;
}

.layer-switcher {
  position: absolute;
  top: 3.5em;
  right: 0.5em;
  text-align: left;
}

.layer-switcher.shown {
  bottom: 3em;
}

.layer-switcher .panel {
  padding: 0 1em 0 0;
  margin: 0;
  border: 4px solid #eee;
  border-radius: 4px;
  background-color: white;
  display: none;
  max-height: 100%;
  overflow-y: auto;
}

.layer-switcher.shown .panel {
  display: block;
}

.layer-switcher button {
  float: right;
  width: 38px;
  height: 38px;
  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACE1BMVEX///8A//8AgICA//8AVVVAQID///8rVVVJtttgv98nTmJ2xNgkW1ttyNsmWWZmzNZYxM4gWGgeU2JmzNNr0N1Rwc0eU2VXxdEhV2JqytQeVmMhVmNoydUfVGUgVGQfVGQfVmVqy9hqy9dWw9AfVWRpydVry9YhVmMgVGNUw9BrytchVWRexdGw294gVWQgVmUhVWPd4N6HoaZsy9cfVmQgVGRrytZsy9cgVWQgVWMgVWRsy9YfVWNsy9YgVWVty9YgVWVry9UgVWRsy9Zsy9UfVWRsy9YgVWVty9YgVWRty9Vsy9aM09sgVWRTws/AzM0gVWRtzNYgVWRuy9Zsy9cgVWRGcHxty9bb5ORbxdEgVWRty9bn6OZTws9mydRfxtLX3Nva5eRix9NFcXxOd4JPeINQeIMiVmVUws9Vws9Vw9BXw9BYxNBaxNBbxNBcxdJexdElWWgmWmhjyNRlx9IqXGtoipNpytVqytVryNNrytZsjZUuX210k5t1y9R2zNR3y9V4lp57zth9zdaAnKOGoaeK0NiNpquV09mesrag1tuitbmj1tuj19uktrqr2d2svcCu2d2xwMO63N+7x8nA3uDC3uDFz9DK4eHL4eLN4eIyYnDX5OM5Z3Tb397e4uDf4uHf5uXi5ePi5+Xj5+Xk5+Xm5+Xm6OY6aHXQ19fT4+NfhI1Ww89gx9Nhx9Nsy9ZWw9Dpj2abAAAAWnRSTlMAAQICAwQEBgcIDQ0ODhQZGiAiIyYpKywvNTs+QklPUlNUWWJjaGt0dnd+hIWFh4mNjZCSm6CpsbW2t7nDzNDT1dje5efr7PHy9PT29/j4+Pn5+vr8/f39/f6DPtKwAAABTklEQVR4Xr3QVWPbMBSAUTVFZmZmhhSXMjNvkhwqMzMzMzPDeD+xASvObKePPa+ffHVl8PlsnE0+qPpBuQjVJjno6pZpSKXYl7/bZyFaQxhf98hHDKEppwdWIW1frFnrxSOWHFfWesSEWC6R/P4zOFrix3TzDFLlXRTR8c0fEEJ1/itpo7SVO9Jdr1DVxZ0USyjZsEY5vZfiiAC0UoTGOrm9PZLuRl8X+Dq1HQtoFbJZbv61i+Poblh/97TC7n0neCcK0ETNUrz1/xPHf+DNAW9Ac6t8O8WH3Vp98f5lCaYKAOFZMLyHL4Y0fe319idMNgMMp+zWVSybUed/+/h7I4wRAG1W6XDy4XmjR9HnzvDRZXUAYDFOhC1S/Hh+fIXxen+eO+AKqbs+wAo30zDTDvDxKoJN88sjUzDFAvBzEUGFsnADoIvAJzoh2BZ8sner+Ke/vwECuQAAAABJRU5ErkJggg==') /*logo.png*/;
  background-repeat: no-repeat;
  background-position: 2px;
  background-color: white;
  border: none;
}

.layer-switcher.shown button {
  display: none;
}

.layer-switcher button:focus, .layer-switcher button:hover {
  background-color: white;
}

.layer-switcher ul {
  padding-left: 1em;
  list-style: none;
}

.layer-switcher li.group {
  padding-top: 5px;
}

.layer-switcher li.group > label {
  font-weight: bold;
}

.layer-switcher li.layer {
  display: table;
}

.layer-switcher li.layer label, .layer-switcher li.layer input {
  display: table-cell;
  vertical-align: sub;
}

.layer-switcher label.disabled {
  opacity:0.4;
}

.layer-switcher input {
  margin: 6px;
}

.layer-switcher.touch ::-webkit-scrollbar {
  width: 4px;
}

.layer-switcher.touch ::-webkit-scrollbar-track {
  -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
  border-radius: 10px;
}

.layer-switcher.touch ::-webkit-scrollbar-thumb {
  border-radius: 10px;
  -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
}

/** Popup */

.ol-popup {
  position: absolute;
  min-width: 260px;
  background-color: white;
  -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
  filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
  padding: 15px;
  border-radius: 10px;
  border: 1px solid #ccc;
  bottom: 12px;
  left: -50px;
}
.ol-popup:after, .ol-popup:before {
  top: 100%;
  border: solid transparent;
  content: " ";
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}
.ol-popup:after {
  border-top-color: white;
  border-width: 10px;
  left: 48px;
  margin-left: -10px;
}
.ol-popup:before {
  border-top-color: #cccccc;
  border-width: 11px;
  left: 48px;
  margin-left: -11px;
}
.ol-popup-closer {
  text-decoration: none;
  position: absolute;
  top: 2px;
  right: 8px;
}
.ol-popup-closer:after {
  color: red;
  content: "✖";
}

All the code is working in Angular until the line '//popup' in scr/app/appponent.ts !

And after that line I have the two errors, getEventPixel when I fly over the map with my mouse and forEachFeatureAtPixel when I click on a marker ...

Errors with forEachFeature at Pixel and getEventPixel

Thanks in advance !!

I'm trying to use OpenLayers with Angular 5. I'm testing different ways to implement maps, I've already tested Leaflet and OpenLayers in simple HTML files and I've choosed to use OpenLayers which is more efficient in my case.

With this map I want to switch between different layers (with ol-layerswitcher), place markers according to a GeoJSON file and display popups. All these features are well working in my HTML file and now, I want to do the same thing with Angular 5 (not with angular-openlayers-directive) !

I have adapted my HTML code in Angular in my app.ponent.ts file, the markers are displayed according to my GeoJSON file, my layer-switcher too but I have problems with two functions : forEachFeatureatPixel and getEventPixel ...

Here is my src/app/app.ponent.ts :

import { Component, OnInit } from '@angular/core';

import OlMap from 'ol/map';
import OlWMS from 'ol/source/tilewms';
import OlTileLayer from 'ol/layer/tile';
import OlView from 'ol/view';
import olProj from 'ol/proj';
import VectorLayer from 'ol/layer/vector';
import VectorSource from 'ol/source/vector';
import Point from 'ol/geom/point';
import Style from 'ol/style/style';
import IconStyle from 'ol/style/icon';
import WFS from 'ol/format/wfs';
import GeoJSON from 'ol/format/geojson';
import Overlay from 'ol/overlay';
import feature from 'ol/feature';
import OlSwitch from 'ol-layerswitcher/src/ol-layerswitcher';
import CanvasMap from 'ol/canvasmap';
//import evt from 'ol/mapbrowserevent';
//import mbe from 'ol/mapbrowsereventtype';

@Component({
  selector: 'app-root',
  templateUrl: './app.ponent.html',
  styleUrls: ['./app.ponent.css']
})

export class AppComponent implements OnInit {

  map: OlMap;
  gny_bright: OlWMS;
  gny_bright_mobile: OlWMS;
  layer: OlTileLayer;
  view: OlView;
  layerSwitcher: OlSwitch;
  WFS: WFS;
  vectorLayer: VectorLayer;
  sourceLayer: VectorSource;
  feature: feature;
  evt: evt;
  mbe: mbe;
  //parkvert: IconStyle;
  //parkorange: Style;
  //parkrouge: Style;
  //parknoir: Style;

  constructor() {
  }

  ngOnInit() {

    this.gny_bright = new OlWMS({
      url: '...',
      params: {...},
      attributions: '...'
    });

    this.gny_bright_mobile = new OlWMS({
      url: '...',
      params: {...},
      attributions: '...'
    });

    var parkvert = new Style({
      image: new IconStyle(({
        anchor: [0.5, 46],
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        src: 'assets/image/parking-vert.png'
      }))
    });

    var parkorange = new Style({
      image: new IconStyle(({
        anchor: [0.5, 46],
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        src: 'assets/image/parking-orange.png'
      }))
    });

    this.view = new OlView({
      center: [689805.19, 6222389.4],
      minZoom: 1,
      maxZoom: 19,
      zoom: 2
    });

    this.sourceLayer = new VectorSource({
      url: 'url_to_my_geojson_file',
      format: new GeoJSON()
    });

    this.vectorLayer = new VectorLayer({
      source: this.sourceLayer
    });

    this.map = new OlMap({
      target: 'map',
      layers: [
        new OlTileLayer({
          title: 'gny_bright_mobile',
          source: this.gny_bright_mobile,
          type: 'base',
          attributions: '...'
        }),
        new OlTileLayer({
          title: 'gny_bright',
          source: this.gny_bright,
          type: 'base',
          attributions: '...'
        })
      ],
      view: this.view
    });

    var markers = function style(feature, resolution) {
      if (feature.get('PLACES') == null) {
        return parknoir;

      } else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.05) {
        return parkrouge;

      } else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.15){
        return parkorange;

      } else if(feature.get('PLACES') > feature.get('CAPACITE') * 0.15) {
        return parkvert;
      }
    }

    this.vectorLayer.setStyle(markers);

    //popup

    var element = document.getElementById('popup');

    var popup = new Overlay({
      element: element,
      autoPan: true,
      offset: [0, -30]
    });

  this.map.addOverlay(popup);

  var content_element = document.getElementById('popup-content');
  var closer = document.getElementById('popup-closer');

  closer.onclick = function() {
        popup.setPosition(undefined);
        closer.blur();
        return false;
    };

    this.map.on('click', function(evt){
        this.feature = this.map.forEachFeatureAtPixel(evt.pixel,
          function(feature) {
            return this.feature;
          });
          if (this.feature) {
            var geometry = this.feature.getGeometry();
            var coord = geometry.getCoordinates();

            if(this.feature.get('NOM')!=null) {
              var content = '<center><h2>' + this.feature.get('NOM') + '</h2></center>' + '<br>';
            }

            if(this.feature.get('ADRESSE')!=null) {
              content += '<h5>' + '<i>Adresse : </i>' + this.feature.get('ADRESSE') + '</h5>';
            }

            if(this.feature.get('CAPACITE')!=null) {
              content += '<h5>' + '<i>Capacité : </i>' + this.feature.get('CAPACITE') + '</h5>';
            }

            if(this.feature.get('PLACES')!=null) {
              content += '<h5>' + '<i>Places disponibles : </i>' + this.feature.get('PLACES') + '<h5>';
            }

            content_element.innerHTML = content;
            popup.setPosition(coord);
        }
    });

    this.map.on('pointermove', function(e) {
        if (e.dragging) {
          return;
        };

        var pixel = this.map.getEventPixel(e.originalEvent);
        var hit = this.map.hasFeatureAtPixel(pixel);

        this.map.getViewport().style.cursor = hit ? 'pointer' : '';
    });

    this.map.addControl(this.vectorLayer);
    this.layerSwitcher = new OlSwitch();
    this.map.addControl(this.layerSwitcher);
  }
}

My src/app/app.ponent.html :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  </head>

    <body>
        <div id="map" class="map"></div>
        <div id="popup" class="ol-popup">
          <a href="#" id="popup-closer" class="ol-popup-closer"></a>
          <div id="popup-content"></div>
        </div>
    </body>

</html>

My src/app/app.ponent.css :

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

My styles.css :

html, body {
  margin: 0px;
}

/* You can add global styles to this file, and also import other style files */
.ol-box {
  box-sizing: border-box;
  border-radius: 2px;
  border: 2px solid blue;
}

.ol-mouse-position {
  top: 8px;
  right: 8px;
  position: absolute;
}

.ol-scale-line {
  background: rgba(0,60,136,0.3);
  border-radius: 4px;
  bottom: 8px;
  left: 8px;
  padding: 2px;
  position: absolute;
}
.ol-scale-line-inner {
  border: 1px solid #eee;
  border-top: none;
  color: #eee;
  font-size: 10px;
  text-align: center;
  margin: 1px;
  will-change: contents, width;
}
.ol-overlay-container {
  will-change: left,right,top,bottom;
}

.ol-unsupported {
  display: none;
}
.ol-viewport, .ol-unselectable {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
}
.ol-selectable {
  -webkit-touch-callout: default;
  -webkit-user-select: auto;
  -moz-user-select: auto;
  -ms-user-select: auto;
  user-select: auto;
}
.ol-grabbing {
  cursor: -webkit-grabbing;
  cursor: -moz-grabbing;
  cursor: grabbing;
}
.ol-grab {
  cursor: move;
  cursor: -webkit-grab;
  cursor: -moz-grab;
  cursor: grab;
}
.ol-control {
  position: absolute;
  background-color: rgba(255,255,255,0.4);
  border-radius: 4px;
  padding: 2px;
}
.ol-control:hover {
  background-color: rgba(255,255,255,0.6);
}
.ol-zoom {
  top: .5em;
  left: .5em;
}
.ol-rotate {
  top: .5em;
  right: .5em;
  transition: opacity .25s linear, visibility 0s linear;
}
.ol-rotate.ol-hidden {
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s linear, visibility 0s linear .25s;
}
.ol-zoom-extent {
  top: 4.643em;
  left: .5em;
}
.ol-full-screen {
  right: .5em;
  top: .5em;
}
@media print {
  .ol-control {
    display: none;
  }
}

.ol-control button {
  display: block;
  margin: 1px;
  padding: 0;
  color: white;
  font-size: 1.14em;
  font-weight: bold;
  text-decoration: none;
  text-align: center;
  height: 1.375em;
  width: 1.375em;
  line-height: .4em;
  background-color: rgba(0,60,136,0.5);
  border: none;
  border-radius: 2px;
}
.ol-control button::-moz-focus-inner {
  border: none;
  padding: 0;
}
.ol-zoom-extent button {
  line-height: 1.4em;
}
.ol-pass {
  display: block;
  font-weight: normal;
  font-size: 1.2em;
  will-change: transform;
}
.ol-touch .ol-control button {
  font-size: 1.5em;
}
.ol-touch .ol-zoom-extent {
  top: 5.5em;
}
.ol-control button:hover,
.ol-control button:focus {
  text-decoration: none;
  background-color: rgba(0,60,136,0.7);
}
.ol-zoom .ol-zoom-in {
  border-radius: 2px 2px 0 0;
}
.ol-zoom .ol-zoom-out {
  border-radius: 0 0 2px 2px;
}


.ol-attribution {
  text-align: right;
  bottom: .5em;
  right: .5em;
  max-width: calc(100% - 1.3em);
}

.ol-attribution ul {
  margin: 0;
  padding: 0 .5em;
  font-size: .7rem;
  line-height: 1.375em;
  color: #000;
  text-shadow: 0 0 2px #fff;
}
.ol-attribution li {
  display: inline;
  list-style: none;
  line-height: inherit;
}
.ol-attribution li:not(:last-child):after {
  content: " ";
}
.ol-attribution img {
  max-height: 2em;
  max-width: inherit;
  vertical-align: middle;
}
.ol-attribution ul, .ol-attribution button {
  display: inline-block;
}
.ol-attribution.ol-collapsed ul {
  display: none;
}
.ol-attribution.ol-logo-only ul {
  display: block;
}
.ol-attribution:not(.ol-collapsed) {
  background: rgba(255,255,255,0.8);
}
.ol-attribution.ol-uncollapsible {
  bottom: 0;
  right: 0;
  border-radius: 4px 0 0;
  height: 1.1em;
  line-height: 1em;
}
.ol-attribution.ol-logo-only {
  background: transparent;
  bottom: .4em;
  height: 1.1em;
  line-height: 1em;
}
.ol-attribution.ol-uncollapsible img {
  margin-top: -.2em;
  max-height: 1.6em;
}
.ol-attribution.ol-logo-only button,
.ol-attribution.ol-uncollapsible button {
  display: none;
}

.ol-zoomslider {
  top: 4.5em;
  left: .5em;
  height: 200px;
}
.ol-zoomslider button {
  position: relative;
  height: 10px;
}

.ol-touch .ol-zoomslider {
  top: 5.5em;
}

.ol-overviewmap {
  left: 0.5em;
  bottom: 0.5em;
}
.ol-overviewmap.ol-uncollapsible {
  bottom: 0;
  left: 0;
  border-radius: 0 4px 0 0;
}
.ol-overviewmap .ol-overviewmap-map,
.ol-overviewmap button {
  display: inline-block;
}
.ol-overviewmap .ol-overviewmap-map {
  border: 1px solid #7b98bc;
  height: 150px;
  margin: 2px;
  width: 150px;
}
.ol-overviewmap:not(.ol-collapsed) button{
  bottom: 1px;
  left: 2px;
  position: absolute;
}
.ol-overviewmap.ol-collapsed .ol-overviewmap-map,
.ol-overviewmap.ol-uncollapsible button {
  display: none;
}
.ol-overviewmap:not(.ol-collapsed) {
  background: rgba(255,255,255,0.8);
}
.ol-overviewmap-box {
  border: 2px dotted rgba(0,60,136,0.7);
}

.ol-overviewmap .ol-overviewmap-box:hover {
  cursor: move;
}

.layer-switcher.shown.ol-control {
  background-color: transparent;
}

.layer-switcher.shown.ol-control:hover {
  background-color: transparent;
}

.layer-switcher {
  position: absolute;
  top: 3.5em;
  right: 0.5em;
  text-align: left;
}

.layer-switcher.shown {
  bottom: 3em;
}

.layer-switcher .panel {
  padding: 0 1em 0 0;
  margin: 0;
  border: 4px solid #eee;
  border-radius: 4px;
  background-color: white;
  display: none;
  max-height: 100%;
  overflow-y: auto;
}

.layer-switcher.shown .panel {
  display: block;
}

.layer-switcher button {
  float: right;
  width: 38px;
  height: 38px;
  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACE1BMVEX///8A//8AgICA//8AVVVAQID///8rVVVJtttgv98nTmJ2xNgkW1ttyNsmWWZmzNZYxM4gWGgeU2JmzNNr0N1Rwc0eU2VXxdEhV2JqytQeVmMhVmNoydUfVGUgVGQfVGQfVmVqy9hqy9dWw9AfVWRpydVry9YhVmMgVGNUw9BrytchVWRexdGw294gVWQgVmUhVWPd4N6HoaZsy9cfVmQgVGRrytZsy9cgVWQgVWMgVWRsy9YfVWNsy9YgVWVty9YgVWVry9UgVWRsy9Zsy9UfVWRsy9YgVWVty9YgVWRty9Vsy9aM09sgVWRTws/AzM0gVWRtzNYgVWRuy9Zsy9cgVWRGcHxty9bb5ORbxdEgVWRty9bn6OZTws9mydRfxtLX3Nva5eRix9NFcXxOd4JPeINQeIMiVmVUws9Vws9Vw9BXw9BYxNBaxNBbxNBcxdJexdElWWgmWmhjyNRlx9IqXGtoipNpytVqytVryNNrytZsjZUuX210k5t1y9R2zNR3y9V4lp57zth9zdaAnKOGoaeK0NiNpquV09mesrag1tuitbmj1tuj19uktrqr2d2svcCu2d2xwMO63N+7x8nA3uDC3uDFz9DK4eHL4eLN4eIyYnDX5OM5Z3Tb397e4uDf4uHf5uXi5ePi5+Xj5+Xk5+Xm5+Xm6OY6aHXQ19fT4+NfhI1Ww89gx9Nhx9Nsy9ZWw9Dpj2abAAAAWnRSTlMAAQICAwQEBgcIDQ0ODhQZGiAiIyYpKywvNTs+QklPUlNUWWJjaGt0dnd+hIWFh4mNjZCSm6CpsbW2t7nDzNDT1dje5efr7PHy9PT29/j4+Pn5+vr8/f39/f6DPtKwAAABTklEQVR4Xr3QVWPbMBSAUTVFZmZmhhSXMjNvkhwqMzMzMzPDeD+xASvObKePPa+ffHVl8PlsnE0+qPpBuQjVJjno6pZpSKXYl7/bZyFaQxhf98hHDKEppwdWIW1frFnrxSOWHFfWesSEWC6R/P4zOFrix3TzDFLlXRTR8c0fEEJ1/itpo7SVO9Jdr1DVxZ0USyjZsEY5vZfiiAC0UoTGOrm9PZLuRl8X+Dq1HQtoFbJZbv61i+Poblh/97TC7n0neCcK0ETNUrz1/xPHf+DNAW9Ac6t8O8WH3Vp98f5lCaYKAOFZMLyHL4Y0fe319idMNgMMp+zWVSybUed/+/h7I4wRAG1W6XDy4XmjR9HnzvDRZXUAYDFOhC1S/Hh+fIXxen+eO+AKqbs+wAo30zDTDvDxKoJN88sjUzDFAvBzEUGFsnADoIvAJzoh2BZ8sner+Ke/vwECuQAAAABJRU5ErkJggg==') /*logo.png*/;
  background-repeat: no-repeat;
  background-position: 2px;
  background-color: white;
  border: none;
}

.layer-switcher.shown button {
  display: none;
}

.layer-switcher button:focus, .layer-switcher button:hover {
  background-color: white;
}

.layer-switcher ul {
  padding-left: 1em;
  list-style: none;
}

.layer-switcher li.group {
  padding-top: 5px;
}

.layer-switcher li.group > label {
  font-weight: bold;
}

.layer-switcher li.layer {
  display: table;
}

.layer-switcher li.layer label, .layer-switcher li.layer input {
  display: table-cell;
  vertical-align: sub;
}

.layer-switcher label.disabled {
  opacity:0.4;
}

.layer-switcher input {
  margin: 6px;
}

.layer-switcher.touch ::-webkit-scrollbar {
  width: 4px;
}

.layer-switcher.touch ::-webkit-scrollbar-track {
  -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
  border-radius: 10px;
}

.layer-switcher.touch ::-webkit-scrollbar-thumb {
  border-radius: 10px;
  -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
}

/** Popup */

.ol-popup {
  position: absolute;
  min-width: 260px;
  background-color: white;
  -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
  filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
  padding: 15px;
  border-radius: 10px;
  border: 1px solid #ccc;
  bottom: 12px;
  left: -50px;
}
.ol-popup:after, .ol-popup:before {
  top: 100%;
  border: solid transparent;
  content: " ";
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}
.ol-popup:after {
  border-top-color: white;
  border-width: 10px;
  left: 48px;
  margin-left: -10px;
}
.ol-popup:before {
  border-top-color: #cccccc;
  border-width: 11px;
  left: 48px;
  margin-left: -11px;
}
.ol-popup-closer {
  text-decoration: none;
  position: absolute;
  top: 2px;
  right: 8px;
}
.ol-popup-closer:after {
  color: red;
  content: "✖";
}

All the code is working in Angular until the line '//popup' in scr/app/app.ponent.ts !

And after that line I have the two errors, getEventPixel when I fly over the map with my mouse and forEachFeatureAtPixel when I click on a marker ...

Errors with forEachFeature at Pixel and getEventPixel

Thanks in advance !!

Share Improve this question asked May 3, 2018 at 9:12 AdrienAdrien 1852 gold badges3 silver badges12 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

JavaScript is not Java. You did not bind the functions to your ponent, so this is not what you think it is. Read the full article about this on mozilla.

Until arrow functions, every new function defined its own this value.

But this is easily solved by using an arrow function!

An arrow function does not have its own this; the this value of the enclosing execution context is used.

Consider your code below:

this.map.on('click', function(evt){ 
  this.map.getEventPixel
});

The code above tries to access a property map of the event function function(evt), which it does not have. To fix it, just change it to an arrow function:

this.map.on('click', (evt) => { 
  this.map.getEventPixel
});

In the code above, this is actually the context of the ponent, so map is the property of the ponent.

I found the solution for 'Cannot read property 'forEachFeatureAtPixel' of undefined' Error.

My Initial code (which will throw error):

this.map.on('click', function(evt){
   var feature = this.map.forEachFeatureAtPixel(evt.pixel, function(feature) {
                    return feature;
                 });
   if (feature) {
      console.log("Feature found");
   }
});

Working code:

this.map.on('click', function(evt){
   var feature = evt.map.forEachFeatureAtPixel(evt.pixel, function(feature) {
                    return feature;
                 });
   if (feature) {
     console.log("Feature found");
   }
});

Explanation: Use map instance from click event (evt.map.forEachFeatureAtPixel) instead of root instance (this.map.forEachFeatureAtPixel).

本文标签: