I have created a Fantasy Map and have installed the longtitude and latitude overlay and a minimap. My Problem is if i zoom 100% i have grids with the size of 32px (about any reason is 40px after zoom but this is not the problem).
I would now like to adjust the coordinates so that a grid field with 32px also matches the coordinates so that each grid field can be clearly assigned.
I've tried pretty much everything in the Leaflet docs and references and also various scripts on Github, but nothing solves my problem.
This is the Sourcecode of the javascript inside the html:
<script type="text/javascript">
// initialize the map on the "map" div with a given center and zoom
var map = new L.Map('map');
var osmUrl='https://cmeta.space/worldmap/assets/images/{z}/{x}/{y}.png';
var osmAttrib='';
var osm = new L.TileLayer(osmUrl, {minZoom: 3, maxZoom: 8, attribution: osmAttrib, crs: L.CRS.Simple});
map.addLayer(osm);
map.setView(new L.LatLng(0, 0),3);
//Plugin magic goes here! Note that you cannot use the same layer object again, as that will confuse the two map controls
var osm2 = new L.TileLayer(osmUrl, {minZoom: 0, maxZoom: 13, attribution: osmAttrib, crs: L.CRS.Simple });
var miniMap = new L.Control.MiniMap(osm2, { toggleDisplay: true }).addTo(map);
map.attributionControl.setPrefix('© <a href="https://cmeta.space/copyright">cMETA</a> Cardano Metaverse')
// MouseOverlay
// OLD = L.control.mousePosition().addTo(map);
L.control.coordinates({
position:"bottomleft",
decimals:0,
decimalSeperator:",",
labelTemplateLat:"Latitude: {y}",
labelTemplateLng:"Longitude: {x}"
}).addTo(map);
// UserOverlay
var imageUser1 = 'https://cmeta.space/worldmap/logo.png',
imageBounds = [[-15.28, 45.35], [-15.62, 45.69]];
L.imageOverlay(imageUser1, imageBounds).addTo(map);
</script>
and this is the additional javascript code:
/* MINIMAP */
// Following https://github.com/Leaflet/Leaflet/blob/master/PLUGIN-GUIDE.md
(function (factory, window) {
// define an AMD module that relies on 'leaflet'
if (typeof define === 'function' && define.amd) {
define(['leaflet'], factory);
// define a Common JS module that relies on 'leaflet'
} else if (typeof exports === 'object') {
module.exports = factory(require('leaflet'));
}
// attach your plugin to the global 'L' variable
if (typeof window !== 'undefined' && window.L) {
window.L.Control.MiniMap = factory(L);
window.L.control.minimap = function (layer, options) {
return new window.L.Control.MiniMap(layer, options);
};
}
}(function (L) {
var MiniMap = L.Control.extend({
includes: L.Evented ? L.Evented.prototype : L.Mixin.Events,
options: {
position: 'bottomright',
toggleDisplay: false,
zoomLevelOffset: -5,
zoomLevelFixed: false,
centerFixed: false,
zoomAnimation: false,
autoToggleDisplay: false,
minimized: false,
width: 150,
height: 150,
collapsedWidth: 19,
collapsedHeight: 19,
aimingRectOptions: {color: '#ff7800', weight: 1, interactive: false},
shadowRectOptions: {color: '#000000', weight: 1, interactive: false, opacity: 0, fillOpacity: 0},
strings: {hideText: 'Hide MiniMap', showText: 'Show MiniMap'},
mapOptions: {} // Allows definition / override of Leaflet map options.
},
// layer is the map layer to be shown in the minimap
initialize: function (layer, options) {
L.Util.setOptions(this, options);
// Make sure the aiming rects are non-clickable even if the user tries to set them clickable (most likely by forgetting to specify them false)
this.options.aimingRectOptions.interactive = false;
this.options.shadowRectOptions.interactive = false;
this._layer = layer;
},
onAdd: function (map) {
this._mainMap = map;
// Creating the container and stopping events from spilling through to the main map.
this._container = L.DomUtil.create('div', 'leaflet-control-minimap');
this._container.style.width = this.options.width + 'px';
this._container.style.height = this.options.height + 'px';
L.DomEvent.disableClickPropagation(this._container);
L.DomEvent.on(this._container, 'mousewheel', L.DomEvent.stopPropagation);
var mapOptions = {
attributionControl: false,
dragging: !this.options.centerFixed,
zoomControl: false,
zoomAnimation: this.options.zoomAnimation,
autoToggleDisplay: this.options.autoToggleDisplay,
touchZoom: this.options.centerFixed ? 'center' : !this._isZoomLevelFixed(),
scrollWheelZoom: this.options.centerFixed ? 'center' : !this._isZoomLevelFixed(),
doubleClickZoom: this.options.centerFixed ? 'center' : !this._isZoomLevelFixed(),
boxZoom: !this._isZoomLevelFixed(),
crs: map.options.crs
};
mapOptions = L.Util.extend(this.options.mapOptions, mapOptions); // merge with priority of the local mapOptions object.
this._miniMap = new L.Map(this._container, mapOptions);
this._miniMap.addLayer(this._layer);
// These bools are used to prevent infinite loops of the two maps notifying each other that they've moved.
this._mainMapMoving = false;
this._miniMapMoving = false;
// Keep a record of this to prevent auto toggling when the user explicitly doesn't want it.
this._userToggledDisplay = false;
this._minimized = false;
if (this.options.toggleDisplay) {
this._addToggleButton();
}
this._miniMap.whenReady(L.Util.bind(function () {
this._aimingRect = L.rectangle(this._mainMap.getBounds(), this.options.aimingRectOptions).addTo(this._miniMap);
this._shadowRect = L.rectangle(this._mainMap.getBounds(), this.options.shadowRectOptions).addTo(this._miniMap);
this._mainMap.on('moveend', this._onMainMapMoved, this);
this._mainMap.on('move', this._onMainMapMoving, this);
this._miniMap.on('movestart', this._onMiniMapMoveStarted, this);
this._miniMap.on('move', this._onMiniMapMoving, this);
this._miniMap.on('moveend', this._onMiniMapMoved, this);
}, this));
return this._container;
},
addTo: function (map) {
L.Control.prototype.addTo.call(this, map);
var center = this.options.centerFixed || this._mainMap.getCenter();
this._miniMap.setView(center, this._decideZoom(true));
this._setDisplay(this.options.minimized);
return this;
},
onRemove: function (map) {
this._mainMap.off('moveend', this._onMainMapMoved, this);
this._mainMap.off('move', this._onMainMapMoving, this);
this._miniMap.off('moveend', this._onMiniMapMoved, this);
this._miniMap.removeLayer(this._layer);
},
changeLayer: function (layer) {
this._miniMap.removeLayer(this._layer);
this._layer = layer;
this._miniMap.addLayer(this._layer);
},
_addToggleButton: function () {
this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton(
'', this._toggleButtonInitialTitleText(), ('leaflet-control-minimap-toggle-display leaflet-control-minimap-toggle-display-' +
this.options.position), this._container, this._toggleDisplayButtonClicked, this) : undefined;
this._toggleDisplayButton.style.width = this.options.collapsedWidth + 'px';
this._toggleDisplayButton.style.height = this.options.collapsedHeight + 'px';
},
_toggleButtonInitialTitleText: function () {
if (this.options.minimized) {
return this.options.strings.showText;
} else {
return this.options.strings.hideText;
}
},
_createButton: function (html, title, className, container, fn, context) {
var link = L.DomUtil.create('a', className, container);
link.innerHTML = html;
link.href = '#';
link.title = title;
var stop = L.DomEvent.stopPropagation;
L.DomEvent
.on(link, 'click', stop)
.on(link, 'mousedown', stop)
.on(link, 'dblclick', stop)
.on(link, 'click', L.DomEvent.preventDefault)
.on(link, 'click', fn, context);
return link;
},
_toggleDisplayButtonClicked: function () {
this._userToggledDisplay = true;
if (!this._minimized) {
this._minimize();
} else {
this._restore();
}
},
_setDisplay: function (minimize) {
if (minimize !== this._minimized) {
if (!this._minimized) {
this._minimize();
} else {
this._restore();
}
}
},
_minimize: function () {
// hide the minimap
if (this.options.toggleDisplay) {
this._container.style.width = this.options.collapsedWidth + 'px';
this._container.style.height = this.options.collapsedHeight + 'px';
this._toggleDisplayButton.className += (' minimized-' + this.options.position);
this._toggleDisplayButton.title = this.options.strings.showText;
} else {
this._container.style.display = 'none';
}
this._minimized = true;
this._onToggle();
},
_restore: function () {
if (this.options.toggleDisplay) {
this._container.style.width = this.options.width + 'px';
this._container.style.height = this.options.height + 'px';
this._toggleDisplayButton.className = this._toggleDisplayButton.className
.replace('minimized-' + this.options.position, '');
this._toggleDisplayButton.title = this.options.strings.hideText;
} else {
this._container.style.display = 'block';
}
this._minimized = false;
this._onToggle();
},
_onMainMapMoved: function (e) {
if (!this._miniMapMoving) {
var center = this.options.centerFixed || this._mainMap.getCenter();
this._mainMapMoving = true;
this._miniMap.setView(center, this._decideZoom(true));
this._setDisplay(this._decideMinimized());
} else {
this._miniMapMoving = false;
}
this._aimingRect.setBounds(this._mainMap.getBounds());
},
_onMainMapMoving: function (e) {
this._aimingRect.setBounds(this._mainMap.getBounds());
},
_onMiniMapMoveStarted: function (e) {
if (!this.options.centerFixed) {
var lastAimingRect = this._aimingRect.getBounds();
var sw = this._miniMap.latLngToContainerPoint(lastAimingRect.getSouthWest());
var ne = this._miniMap.latLngToContainerPoint(lastAimingRect.getNorthEast());
this._lastAimingRectPosition = {sw: sw, ne: ne};
}
},
_onMiniMapMoving: function (e) {
if (!this.options.centerFixed) {
if (!this._mainMapMoving && this._lastAimingRectPosition) {
this._shadowRect.setBounds(new L.LatLngBounds(this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.sw), this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.ne)));
this._shadowRect.setStyle({opacity: 1, fillOpacity: 0.3});
}
}
},
_onMiniMapMoved: function (e) {
if (!this._mainMapMoving) {
this._miniMapMoving = true;
this._mainMap.setView(this._miniMap.getCenter(), this._decideZoom(false));
this._shadowRect.setStyle({opacity: 0, fillOpacity: 0});
} else {
this._mainMapMoving = false;
}
},
_isZoomLevelFixed: function () {
var zoomLevelFixed = this.options.zoomLevelFixed;
return this._isDefined(zoomLevelFixed) && this._isInteger(zoomLevelFixed);
},
_decideZoom: function (fromMaintoMini) {
if (!this._isZoomLevelFixed()) {
if (fromMaintoMini) {
return this._mainMap.getZoom() + this.options.zoomLevelOffset;
} else {
var currentDiff = this._miniMap.getZoom() - this._mainMap.getZoom();
var proposedZoom = this._miniMap.getZoom() - this.options.zoomLevelOffset;
var toRet;
if (currentDiff > this.options.zoomLevelOffset && this._mainMap.getZoom() < this._miniMap.getMinZoom() - this.options.zoomLevelOffset) {
// This means the miniMap is zoomed out to the minimum zoom level and can't zoom any more.
if (this._miniMap.getZoom() > this._lastMiniMapZoom) {
// This means the user is trying to zoom in by using the minimap, zoom the main map.
toRet = this._mainMap.getZoom() + 1;
// Also we cheat and zoom the minimap out again to keep it visually consistent.
this._miniMap.setZoom(this._miniMap.getZoom() - 1);
} else {
// Either the user is trying to zoom out past the mini map's min zoom or has just panned using it, we can't tell the difference.
// Therefore, we ignore it!
toRet = this._mainMap.getZoom();
}
} else {
// This is what happens in the majority of cases, and always if you configure the min levels + offset in a sane fashion.
toRet = proposedZoom;
}
this._lastMiniMapZoom = this._miniMap.getZoom();
return toRet;
}
} else {
if (fromMaintoMini) {
return this.options.zoomLevelFixed;
} else {
return this._mainMap.getZoom();
}
}
},
_decideMinimized: function () {
if (this._userToggledDisplay) {
return this._minimized;
}
if (this.options.autoToggleDisplay) {
if (this._mainMap.getBounds().contains(this._miniMap.getBounds())) {
return true;
}
return false;
}
return this._minimized;
},
_isInteger: function (value) {
return typeof value === 'number';
},
_isDefined: function (value) {
return typeof value !== 'undefined';
},
_onToggle: function () {
L.Util.requestAnimFrame(function () {
L.DomEvent.on(this._container, 'transitionend', this._fireToggleEvents, this);
if (!L.Browser.any3d) {
L.Util.requestAnimFrame(this._fireToggleEvents, this);
}
}, this);
},
_fireToggleEvents: function () {
L.DomEvent.off(this._container, 'transitionend', this._fireToggleEvents, this);
var data = { minimized: this._minimized };
this.fire(this._minimized ? 'minimize' : 'restore', data);
this.fire('toggle', data);
}
});
L.Map.mergeOptions({
miniMapControl: false
});
L.Map.addInitHook(function () {
if (this.options.miniMapControl) {
this.miniMapControl = (new MiniMap()).addTo(this);
}
});
return MiniMap;
}, window));
/* MOUSECONTROL */
L.Control.Coordinates = L.Control.extend({
options: {
position: 'bottomright',
//decimals used if not using DMS or labelFormatter functions
decimals: 4,
//decimalseperator used if not using DMS or labelFormatter functions
decimalSeperator: ".",
//label templates for usage if no labelFormatter function is defined
labelTemplateLat: "Lat: {y}",
labelTemplateLng: "Lng: {x}",
//label formatter functions
labelFormatterLat: undefined,
labelFormatterLng: undefined,
//switch on/off input fields on click
enableUserInput: true,
//use Degree-Minute-Second
useDMS: false,
//if true lat-lng instead of lng-lat label ordering is used
useLatLngOrder: false
},
onAdd: function(map) {
this._map = map;
var className = 'leaflet-control-coordinates',
container = this._container = L.DomUtil.create('div', className),
options = this.options;
//label containers
this._labelcontainer = L.DomUtil.create("div", "uiElement label", container);
this._label = L.DomUtil.create("span", "labelFirst", this._labelcontainer);
//input containers
this._inputcontainer = L.DomUtil.create("div", "uiElement input uiHidden", container);
var xSpan, ySpan;
if (options.useLatLngOrder) {
ySpan = L.DomUtil.create("span", "", this._inputcontainer);
this._inputY = this._createInput("inputY", this._inputcontainer);
xSpan = L.DomUtil.create("span", "", this._inputcontainer);
this._inputX = this._createInput("inputX", this._inputcontainer);
} else {
xSpan = L.DomUtil.create("span", "", this._inputcontainer);
this._inputX = this._createInput("inputX", this._inputcontainer);
ySpan = L.DomUtil.create("span", "", this._inputcontainer);
this._inputY = this._createInput("inputY", this._inputcontainer);
}
xSpan.innerHTML = options.labelTemplateLng.replace("{x}", "");
ySpan.innerHTML = options.labelTemplateLat.replace("{y}", "");
L.DomEvent.on(this._inputX, 'keyup', this._handleKeypress, this);
L.DomEvent.on(this._inputY, 'keyup', this._handleKeypress, this);
//connect to mouseevents
map.on("mousemove", this._update, this);
map.on('dragstart', this.collapse, this);
map.whenReady(this._update, this);
this._showsCoordinates = true;
//wether or not to show inputs on click
if (options.enableUserInput) {
L.DomEvent.addListener(this._container, "click", this._switchUI, this);
}
return container;
},
/**
* Creates an input HTML element in given container with given classname
*/
_createInput: function(classname, container) {
var input = L.DomUtil.create("input", classname, container);
input.type = "text";
L.DomEvent.disableClickPropagation(input);
return input;
},
_clearMarker: function() {
this._map.removeLayer(this._marker);
},
/**
* Called onkeyup of input fields
*/
_handleKeypress: function(e) {
switch (e.keyCode) {
case 27: //Esc
this.collapse();
break;
case 13: //Enter
this._handleSubmit();
this.collapse();
break;
default: //All keys
this._handleSubmit();
break;
}
},
/**
* Called on each keyup except ESC
*/
_handleSubmit: function() {
var x = L.NumberFormatter.createValidNumber(this._inputX.value, this.options.decimalSeperator);
var y = L.NumberFormatter.createValidNumber(this._inputY.value, this.options.decimalSeperator);
if (x !== undefined && y !== undefined) {
var marker = this._marker;
if (!marker) {
marker = this._marker = L.marker();
marker.on("click", this._clearMarker, this);
}
marker.setLatLng(new L.LatLng(y, x));
marker.addTo(this._map);
}
},
/**
* Shows inputs fields
*/
expand: function() {
this._showsCoordinates = false;
this._map.off("mousemove", this._update, this);
L.DomEvent.addListener(this._container, "mousemove", L.DomEvent.stop);
L.DomEvent.removeListener(this._container, "click", this._switchUI, this);
L.DomUtil.addClass(this._labelcontainer, "uiHidden");
L.DomUtil.removeClass(this._inputcontainer, "uiHidden");
},
/**
* Creates the label according to given options and formatters
*/
_createCoordinateLabel: function(ll) {
var opts = this.options,
x, y;
if (opts.labelFormatterLng) {
x = opts.labelFormatterLng(ll.lng);
} else {
x = L.Util.template(opts.labelTemplateLng, {
x: this._getNumber(ll.lng, opts)
});
}
if (opts.labelFormatterLat) {
y = opts.labelFormatterLat(ll.lat);
} else {
y = L.Util.template(opts.labelTemplateLat, {
y: this._getNumber(ll.lat, opts)
});
}
if (opts.useLatLngOrder) {
return y + " " + x;
}
return x + " " + y;
},
/**
* Returns a Number according to options (DMS or decimal)
*/
_getNumber: function(n, opts) {
var res;
if (opts.useDMS) {
res = L.NumberFormatter.toDMS(n);
} else {
res = L.NumberFormatter.round(n, opts.decimals, opts.decimalSeperator);
}
return res;
},
/**
* Shows coordinate labels after user input has ended. Also
* displays a marker with popup at the last input position.
*/
collapse: function() {
if (!this._showsCoordinates) {
this._map.on("mousemove", this._update, this);
this._showsCoordinates = true;
var opts = this.options;
L.DomEvent.addListener(this._container, "click", this._switchUI, this);
L.DomEvent.removeListener(this._container, "mousemove", L.DomEvent.stop);
L.DomUtil.addClass(this._inputcontainer, "uiHidden");
L.DomUtil.removeClass(this._labelcontainer, "uiHidden");
if (this._marker) {
var m = L.marker(),
ll = this._marker.getLatLng();
m.setLatLng(ll);
var container = L.DomUtil.create("div", "");
var label = L.DomUtil.create("div", "", container);
label.innerHTML = this._createCoordinateLabel(ll);
var close = L.DomUtil.create("a", "", container);
close.innerHTML = "Remove";
close.href = "#";
var stop = L.DomEvent.stopPropagation;
L.DomEvent
.on(close, 'click', stop)
.on(close, 'mousedown', stop)
.on(close, 'dblclick', stop)
.on(close, 'click', L.DomEvent.preventDefault)
.on(close, 'click', function() {
this._map.removeLayer(m);
}, this);
m.bindPopup(container);
m.addTo(this._map);
this._map.removeLayer(this._marker);
this._marker = null;
}
}
},
/**
* Click callback for UI
*/
_switchUI: function(evt) {
L.DomEvent.stop(evt);
L.DomEvent.stopPropagation(evt);
L.DomEvent.preventDefault(evt);
if (this._showsCoordinates) {
//show textfields
this.expand();
} else {
//show coordinates
this.collapse();
}
},
onRemove: function(map) {
map.off("mousemove", this._update, this);
},
/**
* Mousemove callback function updating labels and input elements
*/
_update: function(evt) {
var pos = evt.latlng,
opts = this.options;
if (pos) {
pos = pos.wrap();
this._currentPos = pos;
this._inputY.value = L.NumberFormatter.round(pos.lat, opts.decimals, opts.decimalSeperator);
this._inputX.value = L.NumberFormatter.round(pos.lng, opts.decimals, opts.decimalSeperator);
this._label.innerHTML = this._createCoordinateLabel(pos);
}
}
});
//construcotr registration
L.control.coordinates = function(options) {
return new L.Control.Coordinates(options);
};
//map init hook
L.Map.mergeOptions({
coordinateControl: false
});
L.Map.addInitHook(function() {
if (this.options.coordinateControl) {
this.coordinateControl = new L.Control.Coordinates();
this.addControl(this.coordinateControl);
}
});L.NumberFormatter = {
round: function (num,dec,sep) {
var res = L.Util.formatNum(num,dec)+"",
numbers=res.split(".");
if (numbers[1]) {
var d = dec-numbers[1].length;
for (; d > 0; d--) {
numbers[1]+="0";
}
res = numbers.join(sep||".");
}
return res;
},
toDMS : function (deg) {
var d = Math.floor (deg);
var minfloat = (deg-d)*60;
var m = Math.floor(minfloat);
var secfloat = (minfloat-m)*60;
var s = Math.round(secfloat);
if (s==60) {
m++;
s="00";
}
if (m==60) {
d++;
m="00";
}
if(s<10) {
s="0"+s;
}
if(m<10){
m="0"+m;
}
return ("" + d + "° " + m + "' " + s + "''");
},
createValidNumber:function(num,sep){
if (num&&num.length>0){
var numbers = num.split(sep||".");
try{
var numRes=Number(numbers.join("."));
if(isNaN(numRes)){
return undefined;
}
return numRes;
}catch(e){
return undefined;
}
}
return undefined;
}
};
/* FORMAT Numbers of Mouse Control */
L.NumberFormatter = {
round: function(num, dec, sep) {
var res = L.Util.formatNum(num, dec) + "",
numbers = res.split(".");
if (numbers[1]) {
var d = dec - numbers[1].length;
for (; d > 0; d--) {
numbers[1] += "0";
}
res = numbers.join(sep || ".");
}
return res;
},
toDMS: function(deg) {
var d = Math.floor(Math.abs(deg));
var minfloat = (Math.abs(deg) - d) * 60;
var m = Math.floor(minfloat);
var secfloat = (minfloat - m) * 60;
var s = Math.round(secfloat);
if (s == 60) {
m++;
s = "00";
}
if (m == 60) {
d++;
m = "00";
}
if (s < 10) {
s = "0" + s;
}
if (m < 10) {
m = "0" + m;
}
var dir = "";
if (deg < 0) {
dir = "-";
}
return ("" + dir + d + "° " + m + "' " + s + "''");
},
createValidNumber: function(num, sep) {
if (num && num.length > 0) {
var numbers = num.split(sep || ".");
try {
var numRes = Number(numbers.join("."));
if (isNaN(numRes)) {
return undefined;
}
return numRes;
} catch (e) {
return undefined;
}
}
return undefined;
}
};
is there any solution to set the size of the coordinates?