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 'package:copy_with/copy_with.dart';
import 'package:flex_seed_scheme/flex_seed_scheme.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View file

@ -56,27 +56,41 @@ class _MapViewState extends State<_MapView> {
Future<BitmapDescriptor> _getClusterBitmap(
int size, {
String? text,
required Color color,
}) async {
final PictureRecorder pictureRecorder = 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) {
TextPainter painter = TextPainter(textDirection: TextDirection.ltr);
painter.text = TextSpan(
text: text,
style: TextStyle(
fontSize: size / 3,
color: Theme.of(context).colorScheme.onPrimary,
fontSize: size / 3.5,
color: Theme.of(context).colorScheme.onPrimaryContainer,
fontWeight: FontWeight.normal,
),
);
painter.layout();
painter.paint(
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());
}
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>(
const [],
(markers) {
@ -109,9 +180,17 @@ class _MapViewState extends State<_MapView> {
arguments: CollectionBrowserArguments(c),
);
},
icon: await _getClusterBitmap(cluster.isMultiple ? 125 : 50,
text: cluster.isMultiple ? cluster.count.toString() : null),
icon: await _getClusterBitmap(
_getMarkerSize(cluster.count * 1),
text: _getMarkerCountString(cluster.count * 1),
color: _getMarkerColor(cluster.count * 1),
),
),
);
GoogleMapController? _mapController;
late final _colorTonalPalette = () {
final hct = Hct.fromInt(Theme.of(context).colorScheme.primary.value);
return FlexTonalPalette.of(hct.hue, hct.chroma);
}();
}