mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 08:46:18 +01:00
Update and match marker style betwen google and osm backend (as much as possible)
This commit is contained in:
parent
3c94741da3
commit
a7ef3b0ed7
4 changed files with 152 additions and 99 deletions
|
@ -23,6 +23,7 @@ import 'package:nc_photos/exception_event.dart';
|
|||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/stream_extension.dart';
|
||||
import 'package:nc_photos/stream_util.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/theme/dimension.dart';
|
||||
import 'package:nc_photos/widget/collection_browser.dart';
|
||||
|
|
|
@ -14,16 +14,8 @@ class _DataPoint extends DataPoint {
|
|||
final int fileId;
|
||||
}
|
||||
|
||||
class _GoogleMarkerBuilder {
|
||||
_GoogleMarkerBuilder(this.context);
|
||||
|
||||
Future<BitmapDescriptor> build(List<DataPoint> dataPoints) {
|
||||
return _getClusterBitmap(
|
||||
_getMarkerSize(dataPoints.length),
|
||||
text: _getMarkerCountString(dataPoints.length),
|
||||
color: _getMarkerColor(dataPoints.length),
|
||||
);
|
||||
}
|
||||
class _MarkerBuilder {
|
||||
_MarkerBuilder(this.context);
|
||||
|
||||
String _getMarkerCountString(int count) {
|
||||
switch (count) {
|
||||
|
@ -40,7 +32,7 @@ class _GoogleMarkerBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
Color _getMarkerColor(int count) {
|
||||
double _getMarkerRatio(int count) {
|
||||
const step = 1 / 4;
|
||||
final double r;
|
||||
switch (count) {
|
||||
|
@ -55,43 +47,77 @@ class _GoogleMarkerBuilder {
|
|||
default:
|
||||
r = (count / 10) * step;
|
||||
}
|
||||
if (Theme.of(context).brightness == Brightness.light) {
|
||||
return HSLColor.fromAHSL(
|
||||
1,
|
||||
_colorHsl.hue,
|
||||
r * .7 + .3,
|
||||
(_colorHsl.lightness - (.1 - r * .1)).clamp(0, 1),
|
||||
).toColor();
|
||||
} else {
|
||||
return HSLColor.fromAHSL(
|
||||
1,
|
||||
_colorHsl.hue,
|
||||
r * .6 + .4,
|
||||
(_colorHsl.lightness - (.1 - r * .1)).clamp(0, 1),
|
||||
).toColor();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
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 * 85).toInt() + 85;
|
||||
final BuildContext context;
|
||||
|
||||
late final _minColorHsl =
|
||||
HSLColor.fromColor(Theme.of(context).colorScheme.primary)
|
||||
.withSaturation(
|
||||
Theme.of(context).brightness == Brightness.light ? .9 : .7)
|
||||
.withLightness(
|
||||
Theme.of(context).brightness == Brightness.light ? .4 : .3);
|
||||
late final _maxColorHsl =
|
||||
HSLColor.fromColor(Theme.of(context).colorScheme.primary)
|
||||
.withSaturation(
|
||||
Theme.of(context).brightness == Brightness.light ? .9 : .7)
|
||||
.withLightness(
|
||||
Theme.of(context).brightness == Brightness.light ? .3 : .2);
|
||||
}
|
||||
|
||||
class _OsmMarkerBuilder extends _MarkerBuilder {
|
||||
_OsmMarkerBuilder(super.context);
|
||||
|
||||
Widget build(List<DataPoint> dataPoints) {
|
||||
final text = _getMarkerCountString(dataPoints.length);
|
||||
return _OsmMarker(
|
||||
size: _getMarkerSize(dataPoints.length),
|
||||
text: text,
|
||||
textSize: _getMarkerTextSize(text, dataPoints.length),
|
||||
color: _getMarkerColor(dataPoints.length),
|
||||
);
|
||||
}
|
||||
|
||||
double _getMarkerSize(int count) {
|
||||
final r = _getMarkerRatio(count);
|
||||
return (r * 28).toInt() + 28;
|
||||
}
|
||||
|
||||
double _getMarkerTextSize(String text, int count) {
|
||||
final r = _getMarkerRatio(count);
|
||||
return (r * 3) + 9 - ((text.length / 6) * 1);
|
||||
}
|
||||
|
||||
Color _getMarkerColor(int count) {
|
||||
final r = _getMarkerRatio(count);
|
||||
return HSLColor.lerp(_minColorHsl, _maxColorHsl, r)!.toColor();
|
||||
}
|
||||
}
|
||||
|
||||
class _GoogleMarkerBuilder extends _MarkerBuilder {
|
||||
_GoogleMarkerBuilder(super.context);
|
||||
|
||||
Future<BitmapDescriptor> build(List<DataPoint> dataPoints) {
|
||||
return _getClusterBitmap(
|
||||
_getMarkerSize(dataPoints.length),
|
||||
text: _getMarkerCountString(dataPoints.length),
|
||||
color: _getMarkerColor(dataPoints.length),
|
||||
);
|
||||
}
|
||||
|
||||
double _getMarkerSize(int count) {
|
||||
final r = _getMarkerRatio(count);
|
||||
return (r * 75).toInt() + 100;
|
||||
}
|
||||
|
||||
Color _getMarkerColor(int count) {
|
||||
final r = _getMarkerRatio(count);
|
||||
return HSLColor.lerp(_minColorHsl, _maxColorHsl, r)!.toColor();
|
||||
}
|
||||
|
||||
Future<BitmapDescriptor> _getClusterBitmap(
|
||||
int size, {
|
||||
double size, {
|
||||
String? text,
|
||||
required Color color,
|
||||
}) async {
|
||||
|
@ -99,9 +125,7 @@ class _GoogleMarkerBuilder {
|
|||
final Canvas canvas = Canvas(pictureRecorder);
|
||||
final fillPaint = Paint()..color = color;
|
||||
final outlinePaint = Paint()
|
||||
..color = Theme.of(context).brightness == Brightness.light
|
||||
? Colors.black.withOpacity(.28)
|
||||
: Colors.white.withOpacity(.6)
|
||||
..color = Colors.white.withOpacity(.75)
|
||||
..strokeWidth = size / 28
|
||||
..style = PaintingStyle.stroke;
|
||||
const shadowPadding = 6.0;
|
||||
|
@ -126,7 +150,7 @@ class _GoogleMarkerBuilder {
|
|||
text: text,
|
||||
style: TextStyle(
|
||||
fontSize: size / 3 - ((text.length / 6) * (size * 0.1)),
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
color: Colors.white.withOpacity(.75),
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
);
|
||||
|
@ -139,15 +163,11 @@ class _GoogleMarkerBuilder {
|
|||
),
|
||||
);
|
||||
}
|
||||
final img = await pictureRecorder.endRecording().toImage(size, size);
|
||||
final img =
|
||||
await pictureRecorder.endRecording().toImage(size.ceil(), size.ceil());
|
||||
final data = await img.toByteData(format: ImageByteFormat.png) as ByteData;
|
||||
return BitmapDescriptor.fromBytes(data.buffer.asUint8List());
|
||||
}
|
||||
|
||||
final BuildContext context;
|
||||
|
||||
late final _colorHsl =
|
||||
HSLColor.fromColor(Theme.of(context).colorScheme.primaryContainer);
|
||||
}
|
||||
|
||||
enum _DateRangeType {
|
||||
|
|
|
@ -26,42 +26,44 @@ class _MapViewState extends State<_MapView> {
|
|||
builder: (context, state) {
|
||||
final prevPosition =
|
||||
context.read<PrefController>().mapBrowserPrevPositionValue;
|
||||
return InteractiveMap(
|
||||
providerHint: GpsMapProvider.google,
|
||||
initialPosition: prevPosition ?? const MapCoord(0, 0),
|
||||
initialZoom: prevPosition == null ? 2.5 : 10,
|
||||
dataPoints: state.data,
|
||||
onClusterTap: (dataPoints) {
|
||||
final c = Collection(
|
||||
name: "",
|
||||
contentProvider: CollectionAdHocProvider(
|
||||
account: context.bloc.account,
|
||||
fileIds: dataPoints
|
||||
.cast<_DataPoint>()
|
||||
.map((e) => e.fileId)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
Navigator.of(context).pushNamed(
|
||||
CollectionBrowser.routeName,
|
||||
arguments: CollectionBrowserArguments(c),
|
||||
);
|
||||
},
|
||||
googleClusterBuilder: (context, dataPoints) =>
|
||||
_GoogleMarkerBuilder(context).build(dataPoints),
|
||||
osmClusterBuilder: (context, dataPoints) => _OsmMarker(
|
||||
count: dataPoints.length,
|
||||
return ValueStreamBuilder<GpsMapProvider>(
|
||||
stream: context.bloc.prefController.gpsMapProvider,
|
||||
builder: (context, gpsMapProvider) => InteractiveMap(
|
||||
providerHint: gpsMapProvider.requireData,
|
||||
initialPosition: prevPosition ?? const MapCoord(0, 0),
|
||||
initialZoom: prevPosition == null ? 2.5 : 10,
|
||||
dataPoints: state.data,
|
||||
onClusterTap: (dataPoints) {
|
||||
final c = Collection(
|
||||
name: "",
|
||||
contentProvider: CollectionAdHocProvider(
|
||||
account: context.bloc.account,
|
||||
fileIds: dataPoints
|
||||
.cast<_DataPoint>()
|
||||
.map((e) => e.fileId)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
Navigator.of(context).pushNamed(
|
||||
CollectionBrowser.routeName,
|
||||
arguments: CollectionBrowserArguments(c),
|
||||
);
|
||||
},
|
||||
googleClusterBuilder: (context, dataPoints) =>
|
||||
_GoogleMarkerBuilder(context).build(dataPoints),
|
||||
osmClusterBuilder: (context, dataPoints) =>
|
||||
_OsmMarkerBuilder(context).build(dataPoints),
|
||||
contentPadding: EdgeInsets.only(
|
||||
top: MediaQuery.of(context).padding.top,
|
||||
bottom: MediaQuery.of(context).padding.bottom,
|
||||
),
|
||||
onMapCreated: (controller) {
|
||||
_controller = controller;
|
||||
if (state.initialPoint != null) {
|
||||
controller.setPosition(state.initialPoint!);
|
||||
}
|
||||
},
|
||||
),
|
||||
contentPadding: EdgeInsets.only(
|
||||
top: MediaQuery.of(context).padding.top,
|
||||
bottom: MediaQuery.of(context).padding.bottom,
|
||||
),
|
||||
onMapCreated: (controller) {
|
||||
_controller = controller;
|
||||
if (state.initialPoint != null) {
|
||||
controller.setPosition(state.initialPoint!);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -73,26 +75,50 @@ class _MapViewState extends State<_MapView> {
|
|||
|
||||
class _OsmMarker extends StatelessWidget {
|
||||
const _OsmMarker({
|
||||
required this.count,
|
||||
required this.size,
|
||||
required this.text,
|
||||
required this.textSize,
|
||||
required this.color,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
count.toString(),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
return Center(
|
||||
child: Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(size / 2),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(.3),
|
||||
blurRadius: 2,
|
||||
offset: const Offset(1, 1),
|
||||
),
|
||||
],
|
||||
border: Border.all(
|
||||
color: Colors.white.withOpacity(.75),
|
||||
width: 1.5,
|
||||
),
|
||||
color: color,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: textSize,
|
||||
color: Colors.white.withOpacity(.75),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final int count;
|
||||
final double size;
|
||||
final String text;
|
||||
final double textSize;
|
||||
final Color color;
|
||||
}
|
||||
|
||||
class _PanelContainer extends StatefulWidget {
|
||||
|
|
|
@ -73,6 +73,12 @@ class _OsmInteractiveMapState extends State<OsmInteractiveMap> {
|
|||
context,
|
||||
markers.cast<_OsmDataPoint>().map((e) => e.original).toList(),
|
||||
),
|
||||
// need to be large enough to contain markers of all size
|
||||
size: const Size.square(120),
|
||||
// disable all tap handlers from package
|
||||
zoomToBoundsOnClick: false,
|
||||
centerMarkerOnClick: false,
|
||||
spiderfyCluster: false,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
|
|
Loading…
Reference in a new issue