Search code examples
javascriptprototypebing-maps

Bing maps Topography Overlay Cannot read property 'set_style' of undefined


I am trying to make a zoom based on the Topography Overlay on Bing maps, and I want to load different images for every zoom level and remove them when the zoom changes.

I am storing every TopographicOverlay in an array called UO for every zoom level. The default level is UO[0], and everything was going as expected until I moved the function to insert the objects in the layer (called insertOverlay) outside the main function (called startm).

In other words, my map is not static. It changes dynamically, and I need to be able to call its methods from functions outside startm().

The error message is the following:

Uncaught TypeError: Cannot read property 'set_style' of undefined

var img;
var overlays = [];
var LastOverlayZoom = -1;

function startm(){
    var mapOptions = {
        credentials: "FAKECREDENTIAL",
        customizeOverlays: true,
        mapTypeId: Microsoft.Maps.MapTypeId.aerial
    };
    radar = new Microsoft.Maps.Map(document.getElementById("map_canvas"), mapOptions);

    var viewRect = Microsoft.Maps.LocationRect.fromCorners(
                      new Microsoft.Maps.Location(-23.40367, -68.82516),
                      new Microsoft.Maps.Location(-23.41825, -68.80178));

    radar.setView({bounds: viewRect});

    //
    TopographicOverlay.prototype = new Microsoft.Maps.CustomOverlay();

    showOverlay(0);
}

var UO = [];
function showOverlay(zoom){
    if(zoom >= 0){
        if(LastOverlayZoom!=0){
            if(LastOverlayZoom>0){
                hideOverlay(UO[LastOverlayZoom]);
                UO[LastOverlayZoom]=[];
            }
            if(LastOverlayZoom !=- 1 && 0 == 0){
                LastOverlayZoom = 0;
                return false;
            }
            console.log('Showing zoom 0');
            LastOverlayZoom = 0;
            UO[0] = [];
            UO[0].push(new TopographicOverlay(Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(-23.4, -68.84), new Microsoft.Maps.Location(-23.39, -68.83)), 'https://bingmapsisdk.blob.core.windows.net/isdksamples/topographicMap.gif', radar));
            UO[0].push(new TopographicOverlay(Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(-23.4, -68.83), new Microsoft.Maps.Location(-23.39, -68.82)), 'https://bingmapsisdk.blob.core.windows.net/isdksamples/topographicMap.gif', radar));
            UO[0].push(new TopographicOverlay(Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(-23.4, -68.82), new Microsoft.Maps.Location(-23.39, -68.81)), 'https://bingmapsisdk.blob.core.windows.net/isdksamples/topographicMap.gif', radar));
            UO[0].push(new TopographicOverlay(Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(-23.4, -68.81), new Microsoft.Maps.Location(-23.39, -68.8)), 'https://bingmapsisdk.blob.core.windows.net/isdksamples/topographicMap.gif', radar));
            UO[0].push(new TopographicOverlay(Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(-23.41, -68.84), new Microsoft.Maps.Location(-23.4, -68.83)), 'https://bingmapsisdk.blob.core.windows.net/isdksamples/topographicMap.gif', radar));
            UO[0].push(new TopographicOverlay(Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(-23.41, -68.83), new Microsoft.Maps.Location(-23.4, -68.82)), 'https://bingmapsisdk.blob.core.windows.net/isdksamples/topographicMap.gif', radar));
            UO[0].push(new TopographicOverlay(Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(-23.41, -68.82), new Microsoft.Maps.Location(-23.4, -68.81)), 'https://bingmapsisdk.blob.core.windows.net/isdksamples/topographicMap.gif', radar));
            UO[0].push(new TopographicOverlay(Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(-23.41, -68.81), new Microsoft.Maps.Location(-23.4, -68.8)), 'https://bingmapsisdk.blob.core.windows.net/isdksamples/topographicMap.gif', radar));
            insertOverlay(UO[0]);
        }
    }
}

// Define custom constructor for the overlay
function TopographicOverlay(bounds, image, map) {
    this.bounds = bounds;
    this.image = image;
    this.map = map;
    this.img = document.createElement('img');
}

// Implement the onAdd method to set up DOM element, and use setHtmlElement bind it with the overlay
TopographicOverlay.prototype.onAdd = function () {
    this.img = document.createElement('img');
    this.img.src = this.image;
    this.img.className = 'topographicOverlay';
    this.img.style.width = '100%';
    this.img.style.height = '100%';
    this.img.style.zIndex = '0';
    this.img.style.position = 'absolute';
    this.img.style.pointerEvents = 'none';
    this.setHtmlElement(this.img);
};

// Implement the onLoad method to perform custom operations of rendering the DOM element
TopographicOverlay.prototype.onLoad = function () {
    this.repositionOverlay();
    //repositionOverlay(this);
    //Microsoft.Maps.Events.addHandler(this.map, 'viewchange', repositionOverlay(this));
};

TopographicOverlay.prototype.repositionOverlay = function () {
    var topLeft = this.map.tryLocationToPixel(this.bounds.getNorthwest(), Microsoft.Maps.PixelReference.control);
    var bottomRight = this.map.tryLocationToPixel(this.bounds.getSoutheast(), Microsoft.Maps.PixelReference.control);
    if (topLeft && bottomRight) {
        this.img.style.left = topLeft.x + 'px';
        this.img.style.top = topLeft.y + 'px';
        this.img.style.width = (bottomRight.x - topLeft.x) + 'px';
        this.img.style.height = (bottomRight.y - topLeft.y) + 'px';
        this.img.style.zIndex = 0;
    }
};

function insertOverlay(UOl){ // muestra mapa sobrepuesto, UO es la lista de imagenes de un zoom específico
    UOl.forEach(function(UOimagery){
        console.log(UOimagery.image);
        radar.layers.insert(UOimagery);
    });
}
<script type="text/javascript" src="https://www.bing.com/api/maps/mapcontrol?callback=startm" async defer></script>
<div id="map_canvas" style="width:100%; height:100%; min-height:500px;"></div>

How can I fix this error?

What am I doing wrong?


Solution

  • My first thought is that the startm function is being called before all the code below it is fully loaded. This can happen if the script tag to Bing Maps SDK is before the script with your code. The "async" part of the script tag may also be part of the issue here. Try adding a breakpoint where this function is failing and check to see if it is undefined or not. Since it appears to be a global function, if it is undefined, then it hasn't been loaded into the page yet.

    Another thing to try is move the insertOverlay function higher up in your code so it is loaded before the startm function.

    Looks like you are trying to create animated weather overlay on a map. If you aren't committed to using Bing Maps you may want to take a look at Azure Maps. Azure Maps has weather data as part of it's platform, available as a tile layer. Here is a sample that lets you animate this data: https://azuremapscodesamples.azurewebsites.net/?sample=Animated%20tile%20layer