概述
LatLngBounds
类是 Leaflet 中用于表示地理坐标边界框的类,通常用于定义地图的可视区域或进行空间查询。它包含了两个 LatLng
对象,分别表示边界框的左下角和右上角。
源码分析
源码实现
LatLngBounds.js
源码实现和介绍如下:
// 构造函数:创建地理边界边框,表示由西南sw和东北ne定义的矩形区域
export function LatLngBounds(corner1, corner2) {
if (!corner1) {
return;
}
var latlngs = corner2 ? [corner1, corner2] : corner1;
for (var i = 0, len = latlngs.length; i < len; i++) {
this.extend(latlngs[i]);
}
}
// LatLngBounds的原型上定义方法
LatLngBounds.prototype = {
// 扩展边界以包含给定对象(点或者另一个矩形区域)
extend: function (obj) {
var sw = this._southWest,
ne = this._northEast,
sw2,
ne2;
if (obj instanceof LatLng) {
sw2 = obj;
ne2 = obj;
} else if (obj instanceof LatLngBounds) {
sw2 = obj._southWest;
ne2 = obj._northEast;
if (!sw2 || !ne2) {
return this;
}
} else {
return obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this;
}
if (!sw && !ne) {
this._southWest = new LatLng(sw2.lat, sw2.lng);
this._northEast = new LatLng(ne2.lat, ne2.lng);
} else {
sw.lat = Math.min(sw2.lat, sw.lat);
sw.lng = Math.min(sw2.lng, sw.lng);
ne.lat = Math.max(ne2.lat, ne.lat);
ne.lng = Math.max(ne2.lng, ne.lng);
}
return this;
},
// 缓冲扩展:按比例扩展边界,生成更大的边界
pad: function (bufferRatio) {
var sw = this._southWest,
ne = this._northEast,
heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio,
widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;
return new LatLngBounds(
new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer),
new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)
);
},
// 获取边界框的中心点
getCenter: function () {
return new LatLng(
(this._southWest.lat + this._northEast.lat) / 2,
(this._southWest.lng + this._northEast.lng) / 2
);
},
// 获取边界框的西南角
getSouthWest: function () {
return this._southWest;
},
// 获取边界框的东北角
getNorthEast: function () {
return this._northEast;
},
// 获取边界框的西北角
getNorthWest: function () {
return new LatLng(this.getNorth(), this.getWest());
},
// 获取边界框的东南角
getSouthEast: function () {
return new LatLng(this.getSouth(), this.getEast());
},
// 获取边界框的西边界
getWest: function () {
return this._southWest.lng;
},
// 获取边界框的东边界
getEast: function () {
return this._northEast.lng;
},
// 获取边界框的南边界
getSouth: function () {
return this._southWest.lat;
},
// 获取边界框的北边界
getNorth: function () {
return this._northEast.lat;
},
// 判断点或者边界是否完全在当前边界内
contains: function (obj) {
if (typeof obj[0] === "number" || obj instanceof LatLng || "lat" in obj) {
obj = toLatLng(obj);
} else {
obj = toLatLngBounds(obj);
}
var sw = this._southWest,
ne = this._northEast,
sw2,
ne2;
if (obj instanceof LatLngBounds) {
sw2 = obj.getSouthWest();
ne2 = obj.getNorthEast();
} else {
sw2 = ne2 = obj;
}
return (
sw2.lat >= sw.lat &&
ne2.lat <= ne.lat &&
sw2.lng >= sw.lng &&
ne2.lng <= ne.lng
);
},
// 相交判断,检查两个边界是否有重叠区域(包括边界接触)
intersects: function (bounds) {
bounds = toLatLngBounds(bounds);
var sw = this._southWest,
ne = this._northEast,
sw2 = bounds.getSouthWest(),
ne2 = bounds.getNorthEast(),
latIntersects = ne2.lat >= sw.lat && sw2.lat <= ne.lat,
lngIntersects = ne2.lng >= sw.lng && sw2.lng <= ne.lng;
return latIntersects && lngIntersects;
},
// 重叠判断:检查两个边界是否有严格重叠区域(不包括边界接触)
overlaps: function (bounds) {
bounds = toLatLngBounds(bounds);
var sw = this._southWest,
ne = this._northEast,
sw2 = bounds.getSouthWest(),
ne2 = bounds.getNorthEast(),
latOverlaps = ne2.lat > sw.lat && sw2.lat < ne.lat, // 纬度严格重叠
lngOverlaps = ne2.lng > sw.lng && sw2.lng < ne.lng; // 经度严格重叠
return latOverlaps && lngOverlaps;
},
// 边界字符串:将边界框转换为字符串形式,通常用于URL参数或调试输出
toBBoxString: function () {
return [
this.getWest(),
this.getSouth(),
this.getEast(),
this.getNorth(),
].join(",");
},
// 判断两个边界是否相等,maxMargin 表示容差范围
equals: function (bounds, maxMargin) {
if (!bounds) {
return false;
}
bounds = toLatLngBounds(bounds);
return (
this._southWest.equals(bounds.getSouthWest(), maxMargin) &&
this._northEast.equals(bounds.getNorthEast(), maxMargin)
);
},
// 判断边界是否有效
isValid: function () {
return !!(this._southWest && this._northEast);
},
};
export function toLatLngBounds(a, b) {
if (a instanceof LatLngBounds) {
return a;
}
return new LatLngBounds(a, b);
}
使用场景
- 地图视口计算
- 动态加载数据
- 碰撞检测
总结
通过 LatLngBounds
类,Leaflet 提供了高效的地理范围操作工具,支撑了地图的渲染优化、空间查询和交互逻辑。