PolyUtil
多边形的底层工具:按矩形裁剪环、计算面积重心、计算顶点平均中心。
裁剪在像素坐标上做,bounds 是像素空间的 L.Bounds。
方法
| 方法 | 返回 | 说明 |
|---|---|---|
clipPolygon(points, bounds, round?) | Point[] | 用 Sutherland-Hodgman 算法把环裁到矩形内 |
polygonCenter(latlngs, crs) | LatLng | 投影后按面积求重心,再反投影回经纬度 |
centroid(latlngs) | LatLng | 所有顶点的算术平均,不做面积加权 |
裁剪到视口
渲染器画多边形前会先裁剪,屏幕外的顶点不参与路径构建。 自己写 Canvas 渲染逻辑时可以复用同一套算法,保证裁剪边界与 Leaflet 一致。
var size = map.getSize();
var box = new L.Bounds(L.point(0, 0), L.point(size.x, size.y));
var ring = polygon.getLatLngs()[0].map(function (latlng) {
return map.latLngToLayerPoint(latlng);
});
var clipped = L.PolyUtil.clipPolygon(ring, box, true);
ctx.beginPath();
clipped.forEach(function (p, i) {
if (i === 0) { ctx.moveTo(p.x, p.y); }
else { ctx.lineTo(p.x, p.y); }
});
ctx.closePath();
ctx.fill();
round 传 true 时交点坐标取整,适合像素对齐的绘制;
SVG 路径可以保持小数,交给浏览器做抗锯齿。
面积重心与顶点平均
| 调用 | 算法 | 表现 |
|---|---|---|
polygonCenter(latlngs, crs) | 投影后按面积加权 | 形状的重心,可能落在多边形之外(凹形) |
centroid(latlngs) | 顶点算术平均 | 顶点密集处会把中心拉过去,计算快 |
var ring = polygon.getLatLngs()[0];
var center = L.PolyUtil.polygonCenter(ring, map.options.crs);
var average = L.PolyUtil.centroid(ring);
L.marker(center).bindTooltip('面积重心').addTo(map);
L.circleMarker(average, { radius: 4 }).bindTooltip('顶点平均').addTo(map);
polygonCenter 必须传 CRS,它需要先把经纬度投影到平面,
否则面积计算没有意义。传嵌套数组时只处理第一个环,控制台给出提示。
带洞多边形
两个函数都只接受单环。带洞的面要分别处理外环与内环:
标签位置用外环重心,洞的裁剪各自独立进行。
clipPolygon 本身不区分外环内环,传入哪一圈就裁哪一圈。
重心不一定在面上
L 形、C 形等凹多边形的面积重心可能落在图形外部。
标注位置要求「必须在面内」时,不能直接用重心,
需要在重心处做一次点面判断(booleanPointInPolygon 之类的工具),
失败再退回到包围盒中心的候选点。
裁剪只对当前视图有效。 裁剪结果带着当前缩放与像素原点,缓存到下一次缩放就会错位。 每次重绘重新计算,或直接交给 Leaflet 的渲染器处理。
经纬志(2026)。《PolyUtil》。https://www.jingweizhi.com/leaflet/api/poly-util.html(访问日期 2026-11-03)。