Changing Leaflet ImageLayer With File Input - leaflet

I'm working on a dynamic image mapper that will users can load their floor plan of apartment then put markers on parts of floor. So I wan't to change url of image layer of Leaflet map dynamically.
I'm loading map with ChangeMap function for the first time. It loads my image correctly.
function ChangeMap(_url)
{
var map = L.map('map', {
minZoom: 1,
maxZoom: 5,
center: [0, 0],
zoom: 3,
crs: L.CRS.Simple
}).setView([50.4333, 30.5167], 3);
// dimensions of the image
var w = 1526,
h = 626,
url = _url;
// calculate the edges of the image, in coordinate space
var southWest = map.unproject([0, h], map.getMaxZoom() - 1);
var northEast = map.unproject([w, 0], map.getMaxZoom() - 1);
var bounds = new L.LatLngBounds(southWest, northEast);
// add the image overlay,
// so that it covers the entire map
var overlay = L.imageOverlay(url, bounds);
overlay.addTo(map);
}
But if I try another time without refresh the page I'm getting an error "map container is alreay initialized". After that error I thought I can add div with id='map' dynamically like this.
var mapContainer = $("#mapContainer");
mapContainer.append("<div id='map' width='100%' height='400px'></div>");
I added that append function at the beginning of my ChangeMap() function. But this time there was no map on page. How can I do this ?

Only initialize the map once...So take var map = L.map('map', {... out of ChangeMap and only run it once before.I'd also recommend only initializing the L.imageOverlay once...and using setUrl to dynamically swap when needed inside ChangeMap.

Related

Leaflet JS getBound to TileLayer

I have a web site to displaying historic maps. The maps have been tiled and are loaded as a tilelayer. Is there a way to getBound so I can set the map with fitBound. By default tilelayer does not have a getBounds method. I have tried making a featureGroup of the layer but that just raises an error. Am I missing something? Thanks.
// Initiate map
var map = new L.Map('map', {minZoom: 8, maxZoom: 18, zoom: 10});
// Display and set boundary
var layer = new L.TileLayer('../../maps/1866/{z}/{x}/{y}.png',{maxNativeZoom: 17});
//create featuregroup
var fgroup = new L.featureGroup([layer]);
fgroup.addTo(map);
map.fitBounds(fgroup.getBounds());

layerGroup in layerControl is radio. want checkbox

if I add "baseMaps" to my layer control, "huts" is actually a checkbox. But I only have one basemap, so I dont need that in my layer controls. But I still wanted to be able tu turn off my "huts" overlay. But as soon as I remove "baseMaps" "huts" becomes a radio button and cannot be turned off. Is there a way?
var huts = L.layerGroup();
var hut00 = L.marker([0, 0]).bindPopup('This is <b>HTML</b>content').addTo(huts);
bounds = new L.LatLngBounds(new L.LatLng(90, -180), new L.LatLng(-90, 180));
var baseMap = L.tileLayer("mapTiles/{z}_{x}_{y}.jpg", {tileSize: 512, minZoom: 1, maxZoom: 4, noWrap: true});
var pcMap = L.map('pcMapDiv', {
layers: [baseMap, huts],
center: bounds.getCenter(),
zoom: 0,
maxBounds: bounds,
maxBoundsViscosity: 1.0
});
pcMap.setView([0, 0], 0);
var baseMaps = {
"Plan": baseMap,
};
var overlays = {'Hütten': huts};
var layerControl = L.control.layers(baseMaps, overlays).addTo(pcMap);
var popup = L.popup();
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(pcMap);
}
pcMap.on('click', onMapClick);
The 1st argument of L.control.layers populates the "base maps" (with radio button), while its 2nd argument populates "overlays" (with checkboxes).
If you only want overlays, you can simply pass null to the 1st argument:
L.control.layers(null, overlays)
or initialize an empty Control and explicitly add the overlay:
var layerControl = L.control.layers().addTo(map);
layerControl.addOverlay(huts, "Hütten");

Make boundary for ol static image

I'm using ol v5.3.0 for view static image.
I want to bound the image for the size of the ol div.
When the image minimize more than the div size the will not minimize anymore.
I tried to use the projection attribute of the static image with the extent of the original image size
But it does not help.
there is any option to do it?
Based on this example https://openlayers.org/en/v4.6.5/examples/static-image.html
Instead of opening immediately at zoom 2, if first you fit the extent to the map size and get the zoom level (which will be fractional) which that produces and set it as the minimum zoom the map cannot be zoomed out beyond the size of the image (although it is possible to pan outside the extent).
var extent = [0, 0, 1024, 968];
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent
});
var map = new ol.Map({
layers: [
new ol.layer.Image({
source: new ol.source.ImageStatic({
attributions: '© xkcd',
url: 'https://imgs.xkcd.com/comics/online_communities.png',
projection: projection,
imageExtent: extent
})
})
],
target: 'map',
view: new ol.View({
projection: projection
})
});
var view = map.getView();
view.fit(extent, { constrainResolution: false });
view.setMinZoom(view.getZoom());
// set opening zoom level (zoom set by code must not be less than the minZoom)
view.setZoom(Math.max(2, view.getMinZoom());
var center = ol.extent.getCenter(extent);
view.on(['change:center','change:resolution'], function() {
// map.on('moveend', function() { // alternative
var viewCenter = view.getCenter();
if ((viewCenter[0] != center[0] || viewCenter[1] != center[1]) && view.getZoom() == view.getMinZoom()) {
view.setCenter(center);
}
});

How to set maxZoom for interpolate after 18 with BING layer

I am trying to "zoom in" (by interpolation if not possible more tham 18)...
var BING_KEY = 'AuhiCJHlGzhg93IqUH_oCpl_-ZUrIE6SPftlyGYUvr9Amx5nzA-WqGcPquyFZl4L'
var map = L.map('map').setView([1.2862100, 103.8541900], 18)
map.options.maxZoom = 20; // NOT WORKING
map.options.maxNativeZoom = 18; // NOT WORKING
var bingLayer = L.tileLayer.bing(BING_KEY).addTo(map)
It is not working (blank image), after 18 (clicking "+")
See Leaflet-JS BING-layer.
The options available for a L.Map are different from the options available for a L.TileLayer. Note how both Map and TileLayer both have a maxZoom option with different meaning, and how TileLayer inherits the maxNativeZoom option from the GridLayer class.
Therefore, apply the options to the TileLayer and not to the Map:
var map = L.map('map');
var bingLayer = L.tileLayer.bing({bingKey: 'ABCD', maxNativeZoom: 18, maxZoom: 20}).addTo(map);

OpenLayers 3 - change base map from ol.layer.Tile (Bing) to ol.layer.Image (static image)

I need high-res map images for my application (solar power system design). Bing Maps in OL is good for finding the right building, but too low-res for laying out solar panels. So, I want to use a small high-res static map for doing the layout. Here's what I have currently. First load the Bing Maps layer:
var layers = [];
var baseBingMapLayer = new ol.layer.Tile({
source: new ol.source.BingMaps({
key: 'XXXXX',
imagerySet: 'AerialWithLabels',
})
});
layers.push(baseBingMapLayer);
var map = new ol.Map({
layers: layers,
target: 'map',
view: new ol.View({
center: [-13569845.9277,4485666.89612],
zoom: 5,
})
});
Then when I want to load the static map, the strategy is to remove the Bing Maps layer and then add the static image layer. I'm doing the following:
var extent = [0, 0, 1024, 768];
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent
});
var staticURL =
"https://maps.googleapis.com/maps/api/staticmap"
+ "?center=37.7431569802915,-121.4451930197085&"
+ "zoom=20&size=1024x768&scale=2&zoom=3&"
+ "format=jpg&maptype=satellite"
+ "&key=XXX";
map.removeLayer(baseBingMapLayer);
var imageLayer = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: staticURL,
imageSize: [1024,768],
projection: projection,
imageExtent: extent
})
});
var imageLayerView = new ol.View({
projection: projection,
center: ol.extent.getCenter(extent),
zoom: 2
});
map.addLayer(imageLayer);
map.addView(imageLayerView);
Needless to say, this isn't working. I just get a blank screen with no exceptions thrown.
I actually had some success using jQuery to just empty the entire map div and start over with a new map object. However this seems to cause other problems and didn't seem like the right approach to me.
I'm going to continue working on this problem, but thought I would post since I'm sure I won't be the last person to try this little stunt :-)
Gary