Skip to content

Commit

Permalink
feat: add option to draw labels on top of all Polygons (#1707)
Browse files Browse the repository at this point in the history
Remove weird left-side label pruning and add an option to draw labels last on top of all the polygons.
  • Loading branch information
ignatz authored Oct 28, 2023
1 parent 394dc27 commit 69a25e9
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 52 deletions.
76 changes: 32 additions & 44 deletions lib/src/layer/polygon_layer/label.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,46 @@ import 'package:flutter_map/src/layer/polygon_layer/polygon_layer.dart';
import 'package:latlong2/latlong.dart';
import 'package:polylabel/polylabel.dart';

void Function(Canvas canvas)? buildLabelTextPainter(
List<LatLng> locs,
LatLng labelLoc, {
void Function(Canvas canvas)? buildLabelTextPainter({
required Offset placementPoint,
required List<Offset> points,
required String labelText,
required double rotationRad,
bool rotate = false,
TextStyle? labelStyle,
double padding = 0,
required bool rotate,
required TextStyle labelStyle,
required double padding,
}) {
double dx = placementPoint.dx;
double dy = placementPoint.dy;
final textSpan = TextSpan(text: labelText, style: labelStyle);
final textPainter = TextPainter(
text: textSpan,
textAlign: TextAlign.center,
textDirection: TextDirection.ltr,
)..layout();

if (dx > 0) {
final textSpan = TextSpan(text: labelText, style: labelStyle);
final textPainter = TextPainter(
text: textSpan,
textAlign: TextAlign.center,
textDirection: TextDirection.ltr,
maxLines: 1,
);
final dx = placementPoint.dx - textPainter.width / 2;
final dy = placementPoint.dy - textPainter.height / 2;

textPainter.layout();
dx -= textPainter.width / 2;
dy -= textPainter.height / 2;
double maxDx = 0;
var minDx = double.infinity;
for (final point in points) {
maxDx = math.max(maxDx, point.dx);
minDx = math.min(minDx, point.dx);
}

var maxDx = 0.0;
var minDx = double.infinity;
for (final point in points) {
maxDx = math.max(maxDx, point.dx);
minDx = math.min(minDx, point.dx);
}
if (maxDx - minDx - padding > textPainter.width) {
return (canvas) {
if (rotate) {
canvas.save();
canvas.translate(placementPoint.dx, placementPoint.dy);
canvas.rotate(-rotationRad);
canvas.translate(-placementPoint.dx, -placementPoint.dy);
}

if (maxDx - minDx - padding > textPainter.width) {
return (canvas) {
if (rotate) {
canvas.save();
canvas.translate(placementPoint.dx, placementPoint.dy);
canvas.rotate(-rotationRad);
canvas.translate(-placementPoint.dx, -placementPoint.dy);
}
textPainter.paint(
canvas,
Offset(dx, dy),
);
if (rotate) {
canvas.restore();
}
};
}
textPainter.paint(canvas, Offset(dx, dy));
if (rotate) {
canvas.restore();
}
};
}
return null;
}
Expand Down Expand Up @@ -89,9 +78,8 @@ LatLng _computePolylabel(List<LatLng> points) {
// i.e. cheaper at the expense off less optimal label placement.
precision: 0.000001,
);
final latlng = LatLng(
return LatLng(
labelPosition.point.y.toDouble(),
labelPosition.point.x.toDouble(),
);
return latlng;
}
43 changes: 35 additions & 8 deletions lib/src/layer/polygon_layer/polygon_layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,15 @@ class PolygonLayer extends StatelessWidget {
// Turn on/off per-polygon label drawing on the layer-level.
final bool polygonLabels;

// Whether to draw labels last and thus over all the polygons.
final bool drawLabelsLast;

const PolygonLayer({
super.key,
required this.polygons,
this.polygonCulling = false,
this.polygonLabels = true,
this.drawLabelsLast = false,
});

@override
Expand All @@ -118,7 +122,7 @@ class PolygonLayer extends StatelessWidget {

return MobileLayerTransformer(
child: CustomPaint(
painter: PolygonPainter(pgons, map, polygonLabels),
painter: PolygonPainter(pgons, map, polygonLabels, drawLabelsLast),
size: size,
isComplex: true,
),
Expand All @@ -131,8 +135,10 @@ class PolygonPainter extends CustomPainter {
final MapCamera map;
final LatLngBounds bounds;
final bool polygonLabels;
final bool drawLabelsLast;

PolygonPainter(this.polygons, this.map, this.polygonLabels)
PolygonPainter(
this.polygons, this.map, this.polygonLabels, this.drawLabelsLast)
: bounds = map.visibleBounds;

int get hash {
Expand Down Expand Up @@ -189,10 +195,10 @@ class PolygonPainter extends CustomPainter {

// Main loop constructing batched fill and border paths from given polygons.
for (final polygon in polygons) {
final offsets = getOffsets(polygon.points);
if (offsets.isEmpty) {
if (polygon.points.isEmpty) {
continue;
}
final offsets = getOffsets(polygon.points);

// The hash is based on the polygons visual properties. If the hash from
// the current and the previous polygon no longer match, we need to flush
Expand Down Expand Up @@ -235,7 +241,7 @@ class PolygonPainter extends CustomPainter {
}
}

if (polygonLabels && polygon.label != null) {
if (polygonLabels && !drawLabelsLast && polygon.label != null) {
// Labels are expensive because:
// * they themselves cannot easily be pulled into our batched path
// painting with the given text APIs
Expand All @@ -246,15 +252,13 @@ class PolygonPainter extends CustomPainter {
// The painter will be null if the layouting algorithm determined that
// there isn't enough space.
final painter = buildLabelTextPainter(
polygon.points,
polygon.labelPosition,
placementPoint: map.getOffsetFromOrigin(polygon.labelPosition),
points: offsets,
labelText: polygon.label!,
labelStyle: polygon.labelStyle,
rotationRad: map.rotationRad,
rotate: polygon.rotateLabel,
padding: 10,
padding: 20,
);

if (painter != null) {
Expand All @@ -267,6 +271,29 @@ class PolygonPainter extends CustomPainter {
}

drawPaths();

if (polygonLabels && drawLabelsLast) {
for (final polygon in polygons) {
if (polygon.points.isEmpty) {
continue;
}
final offsets = getOffsets(polygon.points);

if (polygon.label != null) {
final painter = buildLabelTextPainter(
placementPoint: map.getOffsetFromOrigin(polygon.labelPosition),
points: offsets,
labelText: polygon.label!,
labelStyle: polygon.labelStyle,
rotationRad: map.rotationRad,
rotate: polygon.rotateLabel,
padding: 20,
);

painter?.call(canvas);
}
}
}
}

Paint _getBorderPaint(Polygon polygon) {
Expand Down

0 comments on commit 69a25e9

Please sign in to comment.