I am experiencing a strange issue. I am receiving an error message that reads "ERROR TypeError: Cannot read properties of null (reading 'map_') on line 29". Even though I am able to loop the layers on the map to get the list of features on hover (line 23). Please see my code below and let me know if you have any advice on what I can do to fix this.
The way this is set up is, that my component is using a service that holds the information about the map and overlay. All I want to do is set the position of overlay on hover.
Component
import { Component, OnInit } from '@angular/core';
import { Map } from 'ol';
import { GeneralMapService } from 'src/app/services/general-map.service';
@Component({
selector: 'app-application-map',
templateUrl: './application-map.component.html',
styleUrls: ['./application-map.component.css']
})
export class WhereisMapComponent implements OnInit {
map_: Map;
overlay: any;
constructor(private generalMap: GeneralMapService) {
this.map_ = this.generalMap.map
this.map_.on("pointermove", (e) => {
const positionOfMouse = e.coordinate
this.map_.forEachFeatureAtPixel(e.pixel, function (feature) {
if (feature) {
const { as_tr_name, ass_track, id, descriptio, media } = feature.getProperties();
// I receive an error message here.
console.log(this.map_.getView())
this.map_.getView().mapOverlay.setPosition(positionOfMouse);
}
})
})
this.overlay = document.getElementById('informationOverlay')
this.generalMap.mapOverlay.set("id", "informationOverlay")
this.generalMap.mapOverlay.setElement(this.overlay)
}
ngOnInit(): void {
}
ngAfterViewInit() {
this.map_.setTarget("map")
}
}
General Service
import { Injectable } from '@angular/core';
import { Map, Overlay, Tile, View } from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import { Zoom, ZoomSlider, FullScreen } from 'ol/control';
import XYZ from 'ol/source/XYZ';
import BingMaps from 'ol/source/BingMaps';
import LayerGroup from 'ol/layer/Group';
import { mapDefaultCenter, mapeDefaultZoom } from '../shared/maptilerkey';
import { CreateLayerService } from './create-layer.service';
import { Fill, Stroke, Style } from 'ol/style';
import CircleStyle from 'ol/style/Circle';
import { OverlayService } from './overlay.service';
@Injectable({
providedIn: 'root'
})
export class GeneralMapService {
map: Map;
zoomSlider: ZoomSlider = new ZoomSlider({
className: "zoom-slider-dashboard"
})
mapLayers: LayerGroup = new LayerGroup({
layers: []
})
mapOverlay: Overlay;
constructor(private createLayers: CreateLayerService, overlayService: OverlayService) {
const topographicLayer = new TileLayer({
source: new XYZ({
url: "https://api.maptiler.com/maps/topographique/{z}/{x}/{y}@2x.png?key=WYPadsIvfisd0PUHFJ6K"
}),
visible: false
})
topographicLayer.set('name', 'topographic');
const openStreetMap = new TileLayer({
source: new OSM(),
visible: true
})
openStreetMap.set('name', 'openstreetmap');
const bingMaps = new TileLayer({
preload: Infinity,
source: new BingMaps({
key: 'AngczjEvgHNjwD8lTQe3DJ6CoFxavJfGTFCxxaGbS3bIgUW5_qn4k_m510RR53fe',
imagerySet: "Aerial",
hidpi: true,
maxZoom: 19
}),
visible: false
})
bingMaps.set('name', 'bingmap');
this.map = new Map({
view: new View({
center: mapDefaultCenter,
zoom: mapeDefaultZoom,
minZoom: 5,
projection: "EPSG:3857",
extent: [15766342.542104144, -5590291.031415702, 16739198.402589425, -4713511.626202316]
}),
controls: []
})
const mapLayerGroup = new LayerGroup({
layers: [topographicLayer, openStreetMap, bingMaps]
})
this.map.setLayerGroup(mapLayerGroup)
this.map.addControl(this.zoomSlider)
// vector layer
const walkPointStyle = new Style({
image: new CircleStyle({
radius: 6,
fill: new Fill({
color: '#44c4a1',
}),
stroke: new Stroke({
color: '#fff',
width: 2,
}),
}),
})
const walkPoints = this.createLayers.createVectorLayer("/assets/data/walking-data.geojson", walkPointStyle)
const builtMapLayers = [
walkPoints
]
this.map.getLayers().extend(builtMapLayers)
// Overlay registration
this.mapOverlay = overlayService.overlay
this.map.addOverlay(this.mapOverlay)
console.log("this.map", this.map.getOverlays())
}
ngAfterContentInit() {
}
returnMap() {
return this.map;
}
setMap(updatedMap: Map) {
this.map = updatedMap;
}
}
Any sort of help would be appreciated!
It looks like you need to store context somewhere and then try to use that context forEachFeatureAtPixel
method.
Let me show an example:
let that = this;
this.map_.forEachFeatureAtPixel(e.pixel, function (feature) {
if (feature) {
// ... other code is omitted for the brevity
console.log(that.map_.getView())
that.map_.getView().mapOverlay.setPosition(positionOfMouse);
}