Working with openlayers and typescript classes - class

/// <reference path="openlayers.d.ts" />
class MapComponent {
element: HTMLElement;
map: OpenLayers.Map;
constructor(element: HTMLElement) {
// Setup our map object
this.element = element;
this.map = new OpenLayers.Map(this.element);
}
init() {
// Setup our two layer objects
var osm_layer_map = new OpenLayers.Layer.OSM("OSM");
// Add layers to the map
this.map.addLayers([osm_layer_map]);
// Add a layer switcher control
this.map.addControl(new OpenLayers.Control.LayerSwitcher({}));
// Zoom the map to the max extent
if (!this.map.getCenter()) {
this.map.zoomToMaxExtent();
}
}
}
window.onload = () => {
var el = document.getElementById('map');
var mc = new MapComponent(el);
mc.init();
}
I have the above piece of code to work with a simple HTML file with only 1 of ID, 'map' with style: height and width # 500px.
I have tried several other ways to get the map to display but so far all i got was a white page (blank).
Can anybody point me in the right direction?
Solutions tried so far:
using jquery with ready function
replace window.onload with a call direct from the html, <script><script/>
place document.getElementById() in the new OpenLayers.Map(here); when first creating this.map
placing the window.onload call above and below (currently)
using export class or public init() or both
As of now, I just want it to work.

Seems that creating the map with the element provided and later defining the options doesn't work.
Instead either initialize the map with options
var options = {
projection: "EPSG:3857",
maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000),
center: new OpenLayers.LonLat(-12356463.476333, 5621521.4854095)
};
this.map = new OpenLayers.Map(this.element, options);
Or call this.map.render(this.element) at the end of your init method.
Also make sure your div is actually visible and has some size specified, otherwise it might be not visible...

Related

Defining Leaflet map as dynamic map id (Cannot read property '_container' of undefined)

I have 2 different divs which using by leaflet as map object. I want to define my map objects into a function such as
html
<div id="mymap"></div>
<div id="mymap2"></div>
javascript
var map;
function define_map(map_id) {
var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
osm = L.tileLayer(osmUrl, {
maxZoom: 7
}),
map = new L.Map(map_id, {
center: new L.LatLng(51.505, -0.04),
zoom: 7
}),
drawnItems = L.featureGroup().addTo(map);
});
define_map("mymap");
define_map("mymap2");
$(".btnmarker").on("click", function() {
console.log(map);
L.DomUtil.addClass(map._container, 'my_crosshair-cursor-enabled'); // ON THIS LINE GETTING ERROR CODE Cannot read property '_container' of undefined
selected_tool = $(this).attr("id");
});
There is no problem, my maps seems working good until accessing features of them from button click event (this button will add a marker class to a map which i clicked on it)
But i'm getting map is not defined error. map is a variable and defined on top line of page.
Thanks inadvance

Here Maps not showing in Ionic tabs

I have a quite basic Here Map in an Ionic tap that is loaded in a Ionic tab with this JavaScript.
var platform = new H.service.Platform({
useCIT: true,
'app_id': $(component).data('appid'),
'app_code': $(component).data('appcode'),
useHTTPS: true
});
// Obtain the default map types from the platform object
var maptypes = platform.createDefaultLayers();
// Instantiate (and display) a map object:
var map = new H.Map(
document.getElementById('mapContainer'),
maptypes.normal.map,
{
zoom: 10,
center: { lng: $(component).data('long'),
lat: $(component).data('lat')
}
});
// Enable the event system on the map instance:
var mapEvents = new H.mapevents.MapEvents(map);
// Add event listeners:
map.addEventListener('tap', function(evt) {
// Log 'tap' and 'mouse' events:
console.log(evt.type, evt.currentPointer.type);
When adding this not in tab 1 the map is not showing. I tried and searched for several things but they only are for Google Maps. How can i get this working in the Ionic tabs?
Please try with following code snippet :
function moveMapToBerlin(map){
map.setCenter({lat:52.5159, lng:13.3777});
map.setZoom(14);
}
/**
* Boilerplate map initialization code starts below:
*/
//Step 1: initialize communication with the platform
// In your own code, replace variable window.apikey with your own apikey
var platform = new H.service.Platform({
apikey: window.apikey
});
var defaultLayers = platform.createDefaultLayers();
//Step 2: initialize a map - this map is centered over Europe
var map = new H.Map(document.getElementById('map'),
defaultLayers.vector.normal.map,{
center: {lat:50, lng:5},
zoom: 4,
pixelRatio: window.devicePixelRatio || 1
});
// add a resize listener to make sure that the map occupies the whole container
window.addEventListener('resize', () => map.getViewPort().resize());
//Step 3: make the map interactive
// MapEvents enables the event system
// Behavior implements default interactions for pan/zoom (also on mobile touch environments)
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Create the default UI components
var ui = H.ui.UI.createDefault(map, defaultLayers);
// Now use the map as required...
window.onload = function () {
moveMapToBerlin(map);
}

MapBox - Add a clusterGroup clickable with Layer Control

I'm still learning and I'm a bit stuck. I may be trying to do to much at once. I have a MapBox map working great with a clickable layer menu taken from examples on the MapBox site. I also have a MarkerClusterGroup which also works and is always visible on the map. Is there a way I could somehow have the MarkerClusterGroup clickable on/off just like layers identified in var overlays = { ...
Below is the code that I think needs the help:
var layers = {
Streets: L.mapbox.tileLayer('mapbox.streets').addTo(map),
Satellite: L.mapbox.tileLayer('mapbox.satellite'),
Light: L.mapbox.tileLayer('mapbox.light'),
};
var overlays = {
DataA: L.mapbox.featureLayer().loadURL('/data/ctsnew.geojson'),
DataB: L.mapbox.featureLayer().loadURL('/data/selectZipcodes.geojson'),
};
// Since featureLayer is an asynchronous method, we use the `.on('ready'`
// call to only use its marker data once we know it is actually loaded.
Markers: L.mapbox.featureLayer('examples.map-h61e8o8e').on('ready', function(e) {
// The clusterGroup gets each marker in the group added to it
// once loaded, and then is added to the map
var clusterGroup = new L.MarkerClusterGroup();
e.target.eachLayer(function(layer) {
clusterGroup.addLayer(layer);
});
map.addLayer(clusterGroup);
});
Could be something as simple as misuse of brackets. Thanks in advance.
You have to include your Marker Cluster Group in your overlays object. For example you could instantiate it just before defining overlays, even if your Cluster Group is empty for now.
Then you fill it once it has downloaded its data.
var layers = {
Streets: L.mapbox.tileLayer('mapbox.streets').addTo(map),
Satellite: L.mapbox.tileLayer('mapbox.satellite'),
Light: L.mapbox.tileLayer('mapbox.light'),
};
var clusterGroup = L.markerClusterGroup();
var overlays = {
DataA: L.mapbox.featureLayer().loadURL('/data/ctsnew.geojson'),
DataB: L.mapbox.featureLayer().loadURL('/data/selectZipcodes.geojson'),
Markers: clusterGroup
};
// Since featureLayer is an asynchronous method, we use the `.on('ready'`
// call to only use its marker data once we know it is actually loaded.
L.mapbox.featureLayer('examples.map-h61e8o8e').on('ready', function(e) {
// The clusterGroup gets each marker in the group added to it
// once loaded, and then is added to the map
e.target.eachLayer(function(layer) {
clusterGroup.addLayer(layer);
});
map.addLayer(clusterGroup); // use that line if you want to automatically add the cluster group to the map once it has downloaded its data.
});

Cannot set style on leaflet L.geoJSON layer

I am having a bit of trouble setting the style on a L.geoJSON based layer,my code looks like this:
var addProperties = function addProperties(prop,map)
{
//the API does not seem to support adding properties to an existing feature,
//the idea here is simple:
//(1) currentFeature.toGeoJson() needs to be called to obtain a json representation
//(2) set the properties on the geojson
//(3) create a new feature based on the geojson
//(4) remove res and add the new feature as res
var style = function style(feature){
var markerStyle = {
draggable: 'true',
icon: L.AwesomeMarkers.icon({
icon: 'link',
prefix: 'glyphicon',
markerColor: 'red',
spin: true
})
};
if(feature.geometry.type==='Point')
return markerStyle;
};
var onEachFeature = function onEachFeature(feature,layer){
console.log("Inside on each feature,checking to see if feature was passed to it ",feature);
layer.on('click',function(e){
//open display sidebar
console.log("Checking to see if setupTabs exists ",setupTabs);
setupTabs('#display-feature-tabs');
console.log("Checking to see if featureInfo exists ",featureInfo);
var featureInfoAPI =featureInfo('feature-properties');
featureInfoAPI.swap(feature.properties);
setTimeout(function() {
sidebar.show();
}, 100);
});
};
console.log("Inside add properties");
var geoJSON,feature;
if(res != null)
{
geoJSON = res.toGeoJSON();
geoJSON.properties = prop;
console.log(geoJSON);
feature = L.geoJson(geoJSON,{style:style,onEachFeature:onEachFeature});
console.log("The new feature that has been created ",feature);
removeFeature(map);
addFeature(feature);
feature.addTo(map);
}
};
I have also tried the style method as well,I am looking to add styles to the active layer for points(styles will also be added for lines and polylines by type).
To style point features, you should use pointToLayer option instead.

Destroy leaflet map trouble

I use several leaflet maps at one time. They can be created and deleted dynamically. But when a map is destroyed by using the map.remove() there is a memory leak. Detached DOM trees appears. You can see it in Chrome Dev Tools.
Screenshot with a leak.
Example function I use to recreate div and map:
var map, mapDiv;
recreateMap = function(){
// destroy previous map and div
if(map) map.remove();
if(mapDiv) mapDiv.parentNode.removeChild(mapDiv);
// create new map div
var randomDivId = 'mapId' + new Date().getTime();
mapDiv = document.createElement('div');
mapDiv.id = randomDivId;
mapDiv.style.height = '200px';
mapDiv.style.width = '200px';
document.getElementsByTagName('body')[0].appendChild(mapDiv);
// attach map to div
map = L.map(randomDivId).setView([51.505, -0.09], 13);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png').addTo(map);
map.invalidateSize();
};
Working example here.
How to properly destroy the leaflet maps?
Assume you create a leaflet map with some thing like the following
var lat =39, long = 40;
var coords=[lat,long];
var zoomLevel=13;
var mapInstance = leafLet.map(mapContainerId).setView(coords, zoomLevel);
You can remove it using the following code
if (mapInstance && mapInstance.remove) {
mapInstance.off();
mapInstance.remove();
}
If you are working with non blocking javascript code or async calls, if required you can use a timer to ensure that your code does not error out. Following is a sample implementation of the same
var timeoutIndex=0;
var watcher=window.setInterval(function(){
timeoutIndex++;
if (mapInstance && mapInstance.remove) {
mapInstance.off();
mapInstance.remove();
window.clearInterval(watcher);
}
if(timeoutIndex >50) { //wait for 5 seconds before giving up
window.clearInterval(watcher);
}
},100);
It worked for me. Guess it helps you too
If you have several maps, you need to put each map into diffents var.
var map1 = L.map(mapDiv1);
var map2 = L.map(mapDiv2);
You can also create a function to control map initialisation and container :
function BoolMapInit(map, mapDiv) {
return (map != null && map._container.id == divMap);
}
And the fonction to remove existing map :
function RemoveExistingMap(map) {
if (map != null) {
map.remove();
map = null;
}
}
Hope this help ;)
I had the same problem, and after spending much time on it, the best solution for this problem is to put the map container in a div, and when you want to regenerate the map, remove all of the div's HTML and create a new map container:
<div id="map-bx">
<div id="map"></div>
</div>
<script type="text/javascript">
// Map init
</script>
and when you want to regenerate (destroy) the map like so:
<script type="text/javascript">
$("#map-box").html("");
$("#map-box").html('<div id="map"></div>');
// map init code
</script>
in my case, map.remove() or map.unload() do not work.
maybe try to unload map first? (documentation says that map is being unloaded automatically when using remove method but it's worth to give an additional shot and try unload it manually first)