我已使用自定义CRS(EPSG:32633)设置了传单地图。地图通常效果很好,只要每当我尝试使用捏放大移动设备缩放地图时它就会冻结。
在缩放到缩放时发生的错误是"未捕获错误:无效的LatLng对象:(NaN,NaN)"。
这是一个可以用来重现问题的方法:
http://jsfiddle.net/thL5bbnv/2/
这里是代码(也在jsfiddle中使用):
// Defining the projection system
L.Projection.UTM33 = {
ZONE: 33,
R_MINOR: 6356752.3142,
R_MAJOR: 6378137,
DEG_TO_RAD: Math.PI / 180,
RAD_TO_DEG: 180 / Math.PI,
bounds: L.bounds([-2500000, 3500000], [3045984, 9045984]),
project: function(latlng) {
var latRad = latlng.lat * this.DEG_TO_RAD,
longRad = latlng.lng * this.DEG_TO_RAD,
longOriginRad = (-183 + (6 * this.ZONE)) * this.DEG_TO_RAD,
eccs = 1 - ((this.R_MINOR / this.R_MAJOR) * (this.R_MINOR / this.R_MAJOR)),
k0 = 0.9996,
eccps = eccs / (1 - eccs),
n = this.R_MAJOR / Math.sqrt(1 - eccs * Math.sin(latRad) * Math.sin(latRad)),
t = Math.tan(latRad) * Math.tan(latRad),
c = eccps * Math.cos(latRad) * Math.cos(latRad),
a = Math.cos(latRad) * (longRad - longOriginRad),
m = this.R_MAJOR * ((1 - eccs / 4 - 3 * eccs * eccs / 64 - 5 * eccs * eccs * eccs / 256) * latRad - (3 * eccs / 8 + 3 * eccs * eccs / 32 + 45 * eccs * eccs * eccs / 1024) * Math.sin(2 * latRad) + (15 * eccs * eccs / 256 + 45 * eccs * eccs * eccs / 1024) * Math.sin(4 * latRad) - (35 * eccs * eccs * eccs / 3072) * Math.sin(6 * latRad)),
x = k0 * n * (a + (1 - t + c) * a * a * a / 6 + (5 - 18 * t + t * t + 72 * c - 58 * eccps) * a * a * a * a * a / 120) + 500000.0,
y = k0 * (m + n * Math.tan(latRad) * (a * a / 2 + (5 - t + 9 * c + 4 * c * c) * a * a * a * a / 24.0 + (61.0 - 58 * t + t * t + 600.0 * c - 330.0 * eccps) * a * a * a * a * a * a / 720));
return new L.Point(x, y);
},
unproject: function(point) {
var eccs = 1 - ((this.R_MINOR / this.R_MAJOR) * (this.R_MINOR / this.R_MAJOR)),
e1 = (1 - Math.sqrt(1 - eccs)) / (1 + Math.sqrt(1 - eccs)),
k0 = 0.9996,
x = point.x - 500000,
y = point.y,
longOrigin = (this.ZONE - 1) * 6 - 180 + 3,
eccps = (eccs) / (1 - eccs),
m = y / k0,
mu = m / (this.R_MAJOR * (1 - eccs / 4 - 3 * eccs * eccs / 64 - 5 * eccs * eccs * eccs / 256)),
phi1Rad = (mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.sin(2 * mu) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Math.sin(4 * mu) + (151 * e1 * e1 * e1 / 96) * Math.sin(6 * mu)),
n1 = this.R_MAJOR / Math.sqrt(1 - eccs * Math.sin(phi1Rad) * Math.sin(phi1Rad)),
t1 = Math.tan(phi1Rad) * Math.tan(phi1Rad),
c1 = eccps * Math.cos(phi1Rad) * Math.cos(phi1Rad),
r1 = this.R_MAJOR * (1 - eccs) / Math.pow(1 - eccs * Math.sin(phi1Rad) * Math.sin(phi1Rad), 1.5),
d = x / (n1 * k0),
lng = ((longOrigin * this.DEG_TO_RAD + ((d - (1 + 2 * t1 + c1) * d * d * d / 6 + (5 - 2 * c1 + 28 * t1 - 3 * c1 * c1 + 8 * eccps + 24 * t1 * t1) * d * d * d * d * d / 120) / Math.cos(phi1Rad))) * this.RAD_TO_DEG),
lat = ((phi1Rad - (n1 * Math.tan(phi1Rad) / r1) * (d * d / 2 - (5 + 3 * t1 + 10 * c1 - 4 * c1 * c1 - 9 * eccps) * d * d * d * d / 24 + (61 + 90 * t1 + 298 * c1 + 45 * t1 * t1 - 252 * eccps - 3 * c1 * c1) * d * d * d * d * d * d / 720)) * this.RAD_TO_DEG);
return new L.LatLng(lat, lng);
}
};
// Defining the utm crs
L.CRS.EPSG32633 = L.extend({}, L.CRS.Earth, {
code: "EPSG:32633",
projection: L.Projection.UTM33,
transformation: new L.Transformation(1, 2500000, -1, 9045984),
scale: function(zoom) {
return 1 / (21664 / Math.pow(2, zoom));
}
});
// Creating map with the utm crs
var map = new L.map('map', {
crs: L.CRS.EPSG32633,
minZoom: 0,
maxZoom: 15,
zoomControl: true
}).on("load", function(e) {
// Adding utm basemap
var layer = new L.TileLayer.WMS('https://opencache.statkart.no/gatekeeper/gk/gk.open', {
layers: "topo2",
format: "image/png",
transparent: false,
attribution: "© Kartverket"
});
layer.addTo(e.target);
}).setView([65.276178, 16.683775], 3);
更新:这是我收到的错误的堆栈跟踪:
Uncaught Error: Invalid LatLng object: (NaN, NaN)
at o.LatLng (https://unpkg.com/leaflet@1.0.2/dist/leaflet.js:5:14154)
at Object.unproject (http://fiddle.jshell.net/thL5bbnv/2/show/:105:12)
at Object.pointToLatLng (https://unpkg.com/leaflet@1.0.2/dist/leaflet.js:5:18431)
at e.unproject (https://unpkg.com/leaflet@1.0.2/dist/leaflet.js:5:30126)
at e.layerPointToLatLng (https://unpkg.com/leaflet@1.0.2/dist/leaflet.js:5:30242)
at e._fireDOMEvent (https://unpkg.com/leaflet@1.0.2/dist/leaflet.js:6:3634)
at e._handleDOMEvent (https://unpkg.com/leaflet@1.0.2/dist/leaflet.js:6:3071)
at HTMLDivElement.h (https://unpkg.com/leaflet@1.0.2/dist/leaflet.js:6:11270)
at e._simulateEvent (https://unpkg.com/leaflet@1.0.2/dist/leaflet.js:8:31479)
at e._onMove (https://unpkg.com/leaflet@1.0.2/dist/leaflet.js:8:31242)o.LatLng @ leaflet.js:5unproject @ (index):105pointToLatLng @ leaflet.js:5unproject @ leaflet.js:5layerPointToLatLng @ leaflet.js:5_fireDOMEvent @ leaflet.js:6_handleDOMEvent @ leaflet.js:6h @ leaflet.js:6_simulateEvent @ leaflet.js:8_onMove @ leaflet.js:8h @ leaflet.js:6
leaflet.js:5 Uncaught Error: Invalid LatLng object: (NaN, NaN)(…)o.LatLng @ leaflet.js:5unproject @ (index):105pointToLatLng @ leaflet.js:5unproject @ leaflet.js:5layerPointToLatLng @ leaflet.js:5_fireDOMEvent @ leaflet.js:6_handleDOMEvent @ leaflet.js:6h @ leaflet.js:6_simulateEvent @ leaflet.js:8_onMove @ leaflet.js:8h @ leaflet.js:6
我试图理解为什么缩放失败,以及我可以采取哪些措施来解决问题。有人知道当使用自定义投影时,为什么缩放会导致无效的LatLng对象:(NaN,NaN)?
答案 0 :(得分:2)
好的,所以我已经将问题追溯到对map.getScaleZoom()
的调用:
该函数直接取决于地图CRS的scale
方法,您已将其定义为
scale: function(zoom) {
return 1 / (21664 / Math.pow(2, zoom));
}
现在,CRS的scale
方法必须实现CRS的zoom
方法的反向。它在Leaflet API documentation for L.CRS
中说明了。
您没有在zoom
中定义L.CRS.EPSG32633
方法,但是......
L.CRS.EPSG32633 = L.extend({}, L.CRS.Earth, {
...您正在使用L.CRS.Earth.zoom()
。因此,对于scale(zoom(x))
的任何值,如果x
不为1,则事情将会失败。首先,缩放级别从1.01跳到-19.4。然后,LatLng
的值为1e+233
。然后你的投影代码接受了这个并开始喷出Infinity
和NaN
,一切都以火焰结束。
修正scale
方法的zoom
和L.CRS.EPSG32633
,以便它们具有幂等性。
无论错误如何,我鼓励您使用Proj4Leaflet ,而不是自己实施投影代码。它经过测试,维护,支持所有已知的EPSG预测和CRS。