-
-
Notifications
You must be signed in to change notification settings - Fork 860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUG] CircleMarker
incorrectly fills with stroke color and has incorrect size
#1688
Comments
CircleMarker
incorrectly fills with stroke color
Seems to me like an issue with the base implementation, it uses |
can confirm this issue, not sure why i did not pick it up during my review. i think im also seeing incorrect radius on the rendering too. |
Potentially radius and diameter are being switched up. |
I'm on holiday until Wednesday, I'll be able to look into it from then on, sorry for the breaking changes 🥲 |
Ah, no worries. I'll also take a look into it, but you just might have a preferred method. |
CircleMarker
incorrectly fills with stroke colorCircleMarker
incorrectly fills with stroke color and has incorrect size
I'll go using drawCircle only if the marker is not filled, in that way we preserve as much a we can the perf improvement of using drawPoint. |
Not quite sure what you mean, but there's no rush at all! |
@Alexays you should also use |
Hi, when do you plan to update the version with fixes? This bug is quite critical to me |
Hi @DevTello, we'll release a hotfix version once we've resolved a couple more of the v6 bugs. You can use the 'master' branch for now. |
I just created this as a custom component with code from @Alexays import 'dart:ui';
import 'package:flutter/widgets.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart' hide Path;
/// Immutable marker options for circle markers
@immutable
class CustomCircleMarker {
final Key? key;
final LatLng point;
final double radius;
final Color color;
final double borderStrokeWidth;
final Color borderColor;
final bool useRadiusInMeter;
const CustomCircleMarker({
required this.point,
required this.radius,
this.key,
this.useRadiusInMeter = false,
this.color = const Color(0xFF00FF00),
this.borderStrokeWidth = 0.0,
this.borderColor = const Color(0xFFFFFF00),
});
}
@immutable
class CustomCircleLayer extends StatelessWidget {
final List<CustomCircleMarker> circles;
const CustomCircleLayer({super.key, required this.circles});
@override
Widget build(BuildContext context) {
final map = MapCamera.of(context);
return MobileLayerTransformer(
child: CustomPaint(
painter: CirclePainter(circles, map),
size: Size(map.size.x, map.size.y),
isComplex: true,
),
);
}
}
@immutable
class CirclePainter extends CustomPainter {
final List<CustomCircleMarker> circles;
final MapCamera map;
const CirclePainter(this.circles, this.map);
@override
void paint(Canvas canvas, Size size) {
const distance = Distance();
final rect = Offset.zero & size;
canvas.clipRect(rect);
// Let's calculate all the points grouped by color and radius
final points = <Color, Map<double, List<Offset>>>{};
final pointsFilledBorder = <Color, Map<double, List<Offset>>>{};
final pointsBorder = <Color, Map<double, Map<double, List<Offset>>>>{};
for (final circle in circles) {
final offset = map.getOffsetFromOrigin(circle.point);
double radius = circle.radius;
if (circle.useRadiusInMeter) {
final r = distance.offset(circle.point, circle.radius, 180);
final delta = offset - map.getOffsetFromOrigin(r);
radius = delta.distance;
}
points[circle.color] ??= {};
points[circle.color]![radius] ??= [];
points[circle.color]![radius]!.add(offset);
if (circle.borderStrokeWidth > 0) {
// Check if color have some transparency or not
// As drawPoints is more efficient than drawCircle
if (circle.color.alpha == 0xFF) {
double radiusBorder = circle.radius + circle.borderStrokeWidth;
if (circle.useRadiusInMeter) {
final rBorder = distance.offset(circle.point, radiusBorder, 180);
final deltaBorder = offset - map.getOffsetFromOrigin(rBorder);
radiusBorder = deltaBorder.distance;
}
pointsFilledBorder[circle.borderColor] ??= {};
pointsFilledBorder[circle.borderColor]![radiusBorder] ??= [];
pointsFilledBorder[circle.borderColor]![radiusBorder]!.add(offset);
} else {
double realRadius = circle.radius;
if (circle.useRadiusInMeter) {
final rBorder = distance.offset(circle.point, realRadius, 180);
final deltaBorder = offset - map.getOffsetFromOrigin(rBorder);
realRadius = deltaBorder.distance;
}
pointsBorder[circle.borderColor] ??= {};
pointsBorder[circle.borderColor]![circle.borderStrokeWidth] ??= {};
pointsBorder[circle.borderColor]![circle.borderStrokeWidth]![
realRadius] ??= [];
pointsBorder[circle.borderColor]![circle.borderStrokeWidth]![
realRadius]!
.add(offset);
}
}
}
// Now that all the points are grouped, let's draw them
final paintBorder = Paint()..style = PaintingStyle.stroke;
for (final color in pointsBorder.keys) {
final paint = paintBorder..color = color;
for (final borderWidth in pointsBorder[color]!.keys) {
final pointsByRadius = pointsBorder[color]![borderWidth]!;
final radiusPaint = paint..strokeWidth = borderWidth;
for (final radius in pointsByRadius.keys) {
final pointsByRadiusColor = pointsByRadius[radius]!;
for (final offset in pointsByRadiusColor) {
_paintCircle(canvas, offset, radius, radiusPaint);
}
}
}
}
// Then the filled border in order to be under the circle
final paintPoint = Paint()
..isAntiAlias = false
..strokeCap = StrokeCap.round;
for (final color in pointsFilledBorder.keys) {
final paint = paintPoint..color = color;
final pointsByRadius = pointsFilledBorder[color]!;
for (final radius in pointsByRadius.keys) {
final pointsByRadiusColor = pointsByRadius[radius]!;
final radiusPaint = paint..strokeWidth = radius * 2;
_paintPoints(canvas, pointsByRadiusColor, radiusPaint);
}
}
// And then the circle
for (final color in points.keys) {
final paint = paintPoint..color = color;
final pointsByRadius = points[color]!;
for (final radius in pointsByRadius.keys) {
final pointsByRadiusColor = pointsByRadius[radius]!;
final radiusPaint = paint..strokeWidth = radius * 2;
_paintPoints(canvas, pointsByRadiusColor, radiusPaint);
}
}
}
void _paintPoints(Canvas canvas, List<Offset> offsets, Paint paint) {
canvas.drawPoints(PointMode.points, offsets, paint);
}
void _paintCircle(Canvas canvas, Offset offset, double radius, Paint paint) {
canvas.drawCircle(offset, radius, paint);
}
@override
bool shouldRepaint(CirclePainter oldDelegate) => false;
} Then CustomCircleLayer(
circles: [
CustomCircleMarker(
point: LatLng(),
radius: 75,
color: Colors.green.withOpacity(0.5),
borderStrokeWidth: 2,
borderColor: Colors.green,
useRadiusInMeter: true,
),
],
), |
@siunus This is already available in the latest release! |
What is the bug?
CircleMarker fills the circle with either CircleMarker.color or CircleMarker.borderColor
How can we reproduce it?
Looks like any circle will be filled with the stroke color regardless of the settings/parameters
Do you have a potential solution?
circle_layer.dart : line 104 and 118
this line looks suspicious:
final radiusPaint = paint..strokeWidth = radius;
should probably be:
final radiusPaint = paint..strokeWidth = borderStrokeWidth;
Platforms
Any
Severity
Obtrusive: Prevents normal functioning but causes no errors in the console
The text was updated successfully, but these errors were encountered: