Update cluster marker style in map browser

This commit is contained in:
Ming Ming 2024-07-13 21:12:18 +08:00
parent b6abb4ae47
commit 7cae2827c7
2 changed files with 87 additions and 7 deletions

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:ui'; import 'dart:ui';
import 'package:copy_with/copy_with.dart'; import 'package:copy_with/copy_with.dart';
import 'package:flex_seed_scheme/flex_seed_scheme.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';

View file

@ -56,27 +56,41 @@ class _MapViewState extends State<_MapView> {
Future<BitmapDescriptor> _getClusterBitmap( Future<BitmapDescriptor> _getClusterBitmap(
int size, { int size, {
String? text, String? text,
required Color color,
}) async { }) async {
final PictureRecorder pictureRecorder = PictureRecorder(); final PictureRecorder pictureRecorder = PictureRecorder();
final Canvas canvas = Canvas(pictureRecorder); final Canvas canvas = Canvas(pictureRecorder);
final Paint paint1 = Paint()..color = Theme.of(context).colorScheme.primary; final Paint paint1 = Paint()..color = color;
canvas.drawCircle(Offset(size / 2, size / 2), size / 2.0, paint1); const shadowPadding = 6.0;
const shadowPaddingHalf = shadowPadding / 2;
final shadowPath = Path()
..addOval(
Rect.fromLTWH(0, 0, size - shadowPadding, size - shadowPadding));
canvas.drawShadow(shadowPath, Colors.black, 1, false);
canvas.drawCircle(
Offset(size / 2 - shadowPaddingHalf, size / 2 - shadowPaddingHalf),
size / 2 - shadowPaddingHalf,
paint1,
);
if (text != null) { if (text != null) {
TextPainter painter = TextPainter(textDirection: TextDirection.ltr); TextPainter painter = TextPainter(textDirection: TextDirection.ltr);
painter.text = TextSpan( painter.text = TextSpan(
text: text, text: text,
style: TextStyle( style: TextStyle(
fontSize: size / 3, fontSize: size / 3.5,
color: Theme.of(context).colorScheme.onPrimary, color: Theme.of(context).colorScheme.onPrimaryContainer,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
), ),
); );
painter.layout(); painter.layout();
painter.paint( painter.paint(
canvas, canvas,
Offset(size / 2 - painter.width / 2, size / 2 - painter.height / 2), Offset(
size / 2 - painter.width / 2 - shadowPaddingHalf,
size / 2 - painter.height / 2 - shadowPaddingHalf,
),
); );
} }
@ -86,6 +100,63 @@ class _MapViewState extends State<_MapView> {
return BitmapDescriptor.fromBytes(data.buffer.asUint8List()); return BitmapDescriptor.fromBytes(data.buffer.asUint8List());
} }
String _getMarkerCountString(int count) {
switch (count) {
case >= 10000:
return "10000+";
case >= 1000:
return "${count ~/ 1000 * 1000}+";
case >= 100:
return "${count ~/ 100 * 100}+";
case >= 10:
return "${count ~/ 10 * 10}+";
default:
return count.toString();
}
}
Color _getMarkerColor(int count) {
const step = 1 / 4;
final double r;
switch (count) {
case >= 10000:
r = 1;
case >= 1000:
r = (count ~/ 1000) / 10 * step + step * 3;
case >= 100:
r = (count ~/ 100) / 10 * step + step * 2;
case >= 10:
r = (count ~/ 10) / 10 * step + step;
default:
r = (count / 10) * step;
}
if (Theme.of(context).brightness == Brightness.light) {
final tone = (r * 30 + 65).toInt();
return Color(_colorTonalPalette.get(tone));
} else {
final tone = (60 - r * 30).toInt();
return Color(_colorTonalPalette.get(tone));
}
}
int _getMarkerSize(int count) {
const step = 1 / 4;
final double r;
switch (count) {
case >= 10000:
r = 1;
case >= 1000:
r = (count ~/ 1000) / 10 * step + step * 3;
case >= 100:
r = (count ~/ 100) / 10 * step + step * 2;
case >= 10:
r = (count ~/ 10) / 10 * step + step;
default:
r = (count / 10) * step;
}
return (r * 50).toInt() + 90;
}
late final _clusterManager = ClusterManager<_DataPoint>( late final _clusterManager = ClusterManager<_DataPoint>(
const [], const [],
(markers) { (markers) {
@ -109,9 +180,17 @@ class _MapViewState extends State<_MapView> {
arguments: CollectionBrowserArguments(c), arguments: CollectionBrowserArguments(c),
); );
}, },
icon: await _getClusterBitmap(cluster.isMultiple ? 125 : 50, icon: await _getClusterBitmap(
text: cluster.isMultiple ? cluster.count.toString() : null), _getMarkerSize(cluster.count * 1),
text: _getMarkerCountString(cluster.count * 1),
color: _getMarkerColor(cluster.count * 1),
),
), ),
); );
GoogleMapController? _mapController; GoogleMapController? _mapController;
late final _colorTonalPalette = () {
final hct = Hct.fromInt(Theme.of(context).colorScheme.primary.value);
return FlexTonalPalette.of(hct.hue, hct.chroma);
}();
} }