在缩放之前在传单中获取 GeoJson 区域的地图边界
Getting the map bounds of a GeoJson region in leaflet prior to zooming
我正在使用 leaflet 并根据当前查看的地图的边界框坐标从数据库动态加载我的地图区域。当我放大时,每个新图层的细节都会增加。地图的每一层都会存在相同的区域,不同缩放级别的相同区域将具有相同的id。
我目前正在尝试计算目标地图边界和目标缩放级别,以便我可以加载新地图边界框内的所有相交区域。我目前有以下代码。
zoomToFeature(e) {
//e.g. map zoom for currently visible map is 3
const layer = e.target;
let padding = [5, 5];
let layerBounds = layer.getBounds();
//e.g layerBounds returns:
//ne = lat: -37.770025, lng: 145.02439
//sw = lat: -37.834451, lng: 144.900952
let targetZoom = this.map.getBoundsZoom(layerBounds, false, padding);
targetZoom = Math.min(this.map.getMaxZoom(), targetZoom);
//e.g.targetZoom for this feature is 12
let center = layer.getCenter()
//e.g. center for this layer is lat: -37.78808138412046, lng: 144.93164062500003
let targetPixelBounds = this.map.getPixelBounds(center, targetZoom);
//e.g. targetPixelBounds: max: Point{x: 946751, y: 643578} min:{x:946114,y:643078}
//this looks very wrong, and so causes everything below to fail I think.
//am I supposed to reset the origin? am I meant to project the center and targetZoom?
let sw = this.map.unproject(targetPixelBounds.getBottomLeft());
let ne = this.map.unproject(targetPixelBounds.getTopRight());
let targetMapBounds = new L.LatLngBounds(sw, ne);
this.map.flyTo(center,targetZoom);
this.loadMapData(targetMapBounds, targetZoom).subscribe(() => {
this.removeOldRegions(); // deletes existing geojson
this.loadRegions(); // adds retrieved data to new geojson layer
//find the same region but in the new zoom layer
let newLayer = this.getLayerById(layer.feature.properties.id);
this.highlightFeature(newLayer);
});
}
出错了
让 targetPixelBounds = this.map.getPixelBounds(center, targetZoom)
线.
知道如何解决这个问题吗?
此操作的默认行为是读出边界并将其传递给地图:
map.fitBounds(e.target.getBounds());
那么你的函数可以看起来像:
zoomToFeature(e) {
let padding = [5, 5];
let layerBounds = e.target.getBounds();
let targetZoom = this.map.getBoundsZoom(layerBounds, false, padding);
targetZoom = Math.min(this.map.getMaxZoom(), targetZoom);
//e.g.targetZoom for this feature is 12
map.fitBounds(layerBounds , {padding: padding, maxZoom: targetZoom });
this.loadMapData(layerBounds , targetZoom).subscribe(() => {
this.removeOldRegions(); // deletes existing geojson
this.loadRegions(); // adds retrieved data to new geojson layer
//find the same region but in the new zoom layer
let newLayer = this.getLayerById(layer.feature.properties.id);
this.highlightFeature(newLayer);
});
}
这会移动地图并将其缩放到图层。
好的,我破案了
上面原始代码中的unproject行将缩放级别作为参数,我没有在原始代码中输入。所以我重构了代码,我在下面发布了。
基本上,一旦我有了地图边界框,我就可以执行飞行,并执行代码以在新的缩放级别检索新的 geojson。当动画完成时,新的 geojson 层已经加载。 (用 TypeScript 编写。对不起非 TypeScript 的人)
zoomToFeature(e) {
const layer = e.target;
let padding = [5, 5];
let layerBounds = layer.getBounds();
let targetMapBoundsZoom = this.getTargetMapBoundsZoom(layerBounds, { padding: padding });
this.map.flyToBounds(targetMapBoundsZoom.bounds);
this.loadMapData(targetMapBoundsZoom.bounds, targetMapBoundsZoom.zoom).subscribe(() => {
this.removeOldRegions();
this.loadRegions();
//find the same region but in the new zoom layer
let newLayer = this.getLayerById(layer.feature.properties.id);
this.highlightFeature(newLayer);
});
}
getTargetMapBoundsZoom(bounds, options) {
let newBoundsCenterZoom = this._getBoundsCenterZoom(bounds, options);
let targetMapBoundsPixels = this.map.getPixelBounds(newBoundsCenterZoom.center, newBoundsCenterZoom.zoom);
let targetSw = this.map.unproject(targetMapBoundsPixels.getBottomLeft(), newBoundsCenterZoom.zoom);
let targetNe = this.map.unproject(targetMapBoundsPixels.getTopRight(), newBoundsCenterZoom.zoom);
let targetMapBounds = new L.LatLngBounds(targetSw, targetNe);
return {
bounds: targetMapBounds,
zoom: newBoundsCenterZoom.zoom
}
}
loadMapData(bounds, zoom): Observable<any[]> {
const boundingBox = Util.GetMapBounds(bounds);
const regionTypeId = this.regionTypeIds[this._regionType];
return this.mapService.getGeoJsonData("AU",
regionTypeId,
zoom,
boundingBox.n,
boundingBox.s,
boundingBox.e,
boundingBox.w).pipe(map((response: any) => {
this.mapGeoJsonData = this.createFeatureCollection(response.data);
return this.mapGeoJsonData;
}));
}
//this is a copy of the original _getBoundsCenterZoom that is internal to leaflet, with minor modifications.
_getBoundsCenterZoom(bounds, options) {
options = options || {};
bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds);
var paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]),
paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]),
zoom = this.map.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));
zoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;
if (zoom === Infinity) {
return {
center: bounds.getCenter(),
zoom: zoom
};
}
var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2),
swPoint = this.map.project(bounds.getSouthWest(), zoom),
nePoint = this.map.project(bounds.getNorthEast(), zoom),
center = this.map.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);
return {
center: center,
zoom: zoom
};
}
createFeatureCollection(data: any) {
let featureCollection = {
type: "FeatureCollection",
features: data.map(r => {
const geoJson = JSON.parse(r.geoJson);
if (geoJson.type === "GeometryCollection") {
geoJson.geometries = geoJson.geometries.filter(r => r.type === "Polygon" || r.type === "MultiPolygon");
}
let feature = {
type: "Feature",
id: r.id,
properties: { id: r.id },
geometry: geoJson
}
return feature;
})
};
return featureCollection;
}
我正在使用 leaflet 并根据当前查看的地图的边界框坐标从数据库动态加载我的地图区域。当我放大时,每个新图层的细节都会增加。地图的每一层都会存在相同的区域,不同缩放级别的相同区域将具有相同的id。
我目前正在尝试计算目标地图边界和目标缩放级别,以便我可以加载新地图边界框内的所有相交区域。我目前有以下代码。
zoomToFeature(e) {
//e.g. map zoom for currently visible map is 3
const layer = e.target;
let padding = [5, 5];
let layerBounds = layer.getBounds();
//e.g layerBounds returns:
//ne = lat: -37.770025, lng: 145.02439
//sw = lat: -37.834451, lng: 144.900952
let targetZoom = this.map.getBoundsZoom(layerBounds, false, padding);
targetZoom = Math.min(this.map.getMaxZoom(), targetZoom);
//e.g.targetZoom for this feature is 12
let center = layer.getCenter()
//e.g. center for this layer is lat: -37.78808138412046, lng: 144.93164062500003
let targetPixelBounds = this.map.getPixelBounds(center, targetZoom);
//e.g. targetPixelBounds: max: Point{x: 946751, y: 643578} min:{x:946114,y:643078}
//this looks very wrong, and so causes everything below to fail I think.
//am I supposed to reset the origin? am I meant to project the center and targetZoom?
let sw = this.map.unproject(targetPixelBounds.getBottomLeft());
let ne = this.map.unproject(targetPixelBounds.getTopRight());
let targetMapBounds = new L.LatLngBounds(sw, ne);
this.map.flyTo(center,targetZoom);
this.loadMapData(targetMapBounds, targetZoom).subscribe(() => {
this.removeOldRegions(); // deletes existing geojson
this.loadRegions(); // adds retrieved data to new geojson layer
//find the same region but in the new zoom layer
let newLayer = this.getLayerById(layer.feature.properties.id);
this.highlightFeature(newLayer);
});
}
出错了 让 targetPixelBounds = this.map.getPixelBounds(center, targetZoom) 线.
知道如何解决这个问题吗?
此操作的默认行为是读出边界并将其传递给地图:
map.fitBounds(e.target.getBounds());
那么你的函数可以看起来像:
zoomToFeature(e) {
let padding = [5, 5];
let layerBounds = e.target.getBounds();
let targetZoom = this.map.getBoundsZoom(layerBounds, false, padding);
targetZoom = Math.min(this.map.getMaxZoom(), targetZoom);
//e.g.targetZoom for this feature is 12
map.fitBounds(layerBounds , {padding: padding, maxZoom: targetZoom });
this.loadMapData(layerBounds , targetZoom).subscribe(() => {
this.removeOldRegions(); // deletes existing geojson
this.loadRegions(); // adds retrieved data to new geojson layer
//find the same region but in the new zoom layer
let newLayer = this.getLayerById(layer.feature.properties.id);
this.highlightFeature(newLayer);
});
}
这会移动地图并将其缩放到图层。
好的,我破案了
上面原始代码中的unproject行将缩放级别作为参数,我没有在原始代码中输入。所以我重构了代码,我在下面发布了。
基本上,一旦我有了地图边界框,我就可以执行飞行,并执行代码以在新的缩放级别检索新的 geojson。当动画完成时,新的 geojson 层已经加载。 (用 TypeScript 编写。对不起非 TypeScript 的人)
zoomToFeature(e) {
const layer = e.target;
let padding = [5, 5];
let layerBounds = layer.getBounds();
let targetMapBoundsZoom = this.getTargetMapBoundsZoom(layerBounds, { padding: padding });
this.map.flyToBounds(targetMapBoundsZoom.bounds);
this.loadMapData(targetMapBoundsZoom.bounds, targetMapBoundsZoom.zoom).subscribe(() => {
this.removeOldRegions();
this.loadRegions();
//find the same region but in the new zoom layer
let newLayer = this.getLayerById(layer.feature.properties.id);
this.highlightFeature(newLayer);
});
}
getTargetMapBoundsZoom(bounds, options) {
let newBoundsCenterZoom = this._getBoundsCenterZoom(bounds, options);
let targetMapBoundsPixels = this.map.getPixelBounds(newBoundsCenterZoom.center, newBoundsCenterZoom.zoom);
let targetSw = this.map.unproject(targetMapBoundsPixels.getBottomLeft(), newBoundsCenterZoom.zoom);
let targetNe = this.map.unproject(targetMapBoundsPixels.getTopRight(), newBoundsCenterZoom.zoom);
let targetMapBounds = new L.LatLngBounds(targetSw, targetNe);
return {
bounds: targetMapBounds,
zoom: newBoundsCenterZoom.zoom
}
}
loadMapData(bounds, zoom): Observable<any[]> {
const boundingBox = Util.GetMapBounds(bounds);
const regionTypeId = this.regionTypeIds[this._regionType];
return this.mapService.getGeoJsonData("AU",
regionTypeId,
zoom,
boundingBox.n,
boundingBox.s,
boundingBox.e,
boundingBox.w).pipe(map((response: any) => {
this.mapGeoJsonData = this.createFeatureCollection(response.data);
return this.mapGeoJsonData;
}));
}
//this is a copy of the original _getBoundsCenterZoom that is internal to leaflet, with minor modifications.
_getBoundsCenterZoom(bounds, options) {
options = options || {};
bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds);
var paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]),
paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]),
zoom = this.map.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));
zoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;
if (zoom === Infinity) {
return {
center: bounds.getCenter(),
zoom: zoom
};
}
var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2),
swPoint = this.map.project(bounds.getSouthWest(), zoom),
nePoint = this.map.project(bounds.getNorthEast(), zoom),
center = this.map.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);
return {
center: center,
zoom: zoom
};
}
createFeatureCollection(data: any) {
let featureCollection = {
type: "FeatureCollection",
features: data.map(r => {
const geoJson = JSON.parse(r.geoJson);
if (geoJson.type === "GeometryCollection") {
geoJson.geometries = geoJson.geometries.filter(r => r.type === "Polygon" || r.type === "MultiPolygon");
}
let feature = {
type: "Feature",
id: r.id,
properties: { id: r.id },
geometry: geoJson
}
return feature;
})
};
return featureCollection;
}