renderSheenPricePin function Travel

Future<Uint8List> renderSheenPricePin(
  1. String label, {
  2. required bool selected,
  3. required SheenThemeData theme,
  4. double pixelRatio = 3,
  5. double textScale = 1,
})

A SheenPricePin drawn as a PNG for a native map's marker (Google Maps draws markers from bitmaps, not widgets): the same capsule, label and sizes, with the glass approximated by its tint and rim, and a soft shadow around it. The image is pixelRatio times the logical size; give the marker the same ratio. Text grows with textScale up to 1.5, as the widget's does.

Implementation

Future<Uint8List> renderSheenPricePin(
  String label, {
  required bool selected,
  required SheenThemeData theme,
  double pixelRatio = 3,
  double textScale = 1,
}) async {
  final t = theme;
  final style = t.type
      .sized(t.type.price, selected ? 14 : 13)
      .copyWith(height: 1.1, color: selected ? t.colors.onAccent : t.colors.text);
  final tp = TextPainter(
    text: TextSpan(text: label, style: style),
    textDirection: TextDirection.ltr,
    textScaler: TextScaler.linear(textScale.clamp(1.0, 1.5)),
  )..layout();
  final padH = selected ? 13.0 : 11.0;
  final h = math.max(selected ? 34.0 : 30.0, tp.height + 12);
  final w = tp.width + padH * 2;
  const margin = 6.0; // room for the shadow
  final logical = Size(w + margin * 2, h + margin * 2);

  final recorder = ui.PictureRecorder();
  final canvas = Canvas(recorder)..scale(pixelRatio);
  final body = RRect.fromRectAndRadius(Rect.fromLTWH(margin, margin, w, h), Radius.circular(h / 2));
  canvas.drawRRect(
    body.shift(const Offset(0, 2)),
    Paint()
      ..color = const Color(0x59000000)
      ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 4),
  );
  final fill = selected
      ? t.colors.accent
      : Color.alphaBlend(t.colors.surfaceMuted.withValues(alpha: .94), t.colors.background);
  canvas.drawRRect(body, Paint()..color = fill);
  canvas.drawRRect(
    body.deflate(.4),
    Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = .8
      ..color = t.isDark ? const Color(0x2EFFFFFF) : const Color(0x14000000),
  );
  tp.paint(canvas, Offset(margin + padH, margin + (h - tp.height) / 2));

  final image = await recorder.endRecording().toImage(
    (logical.width * pixelRatio).ceil(),
    (logical.height * pixelRatio).ceil(),
  );
  final png = await image.toByteData(format: ui.ImageByteFormat.png);
  image.dispose();
  return png!.buffer.asUint8List();
}