circleAvatar method

Future<Uint8List> circleAvatar(
  1. CircleAvatarParams params
)

Generate the circle avatar marker bitmap. Specify the color and sizes of marker with CircleAvatarParams. The image will be resized to diameter of circle(CircleAvatarParams.radius * dpr * 2) with original aspect ratio. It will automatically clip the center of image so the overflowed part won't be showed.

Implementation

Future<Uint8List> circleAvatar(CircleAvatarParams params) async {
  final cacheKey = _buildKey(params.keyPrefix);
  final cache = await _getFileFromCache(cacheKey);
  if (cache != null) {
    return cache;
  }

  final radius = params.radius * dpr;
  final borderWidth = params.borderWidth * dpr;
  final dotRadius = params.dotRadius * dpr;
  final diameter = radius * 2;
  final dotDiameter = dotRadius * 2;
  final spacing = params.spacing * dpr;

  await _initImageDescriptor();
  final image = await _getImage(diameter.toInt());

  final imageStartingPoint = _aspectRatio >= 1
      ? Offset(0 - ((image.width - diameter) / 2), 0)
      : Offset(0, 0 - ((image.height - diameter) / 2));
  final imageCenter = Offset(radius, radius);

  final recorder = PictureRecorder();
  final canvas = Canvas(recorder);

  final outlinePath = Path()
    ..addOval(Rect.fromCircle(center: imageCenter, radius: radius));
  final imagePath = Path()
    ..addOval(
        Rect.fromCircle(center: imageCenter, radius: radius - borderWidth));
  final borderPath =
      Path.combine(PathOperation.difference, outlinePath, imagePath);

  final dotCenter = imageCenter.translate(0, radius + spacing + dotRadius);
  final dotPath = Path()
    ..addOval(
      Rect.fromCircle(center: dotCenter, radius: dotRadius),
    );

  final reducePath = Path.combine(PathOperation.union, outlinePath, dotPath);

  canvas
    ..clipPath(reducePath)
    ..drawImage(image, imageStartingPoint, Paint())
    ..drawPath(borderPath, Paint()..color = params.color)
    ..drawCircle(dotCenter, dotRadius, Paint()..color = params.color);

  final recorded = await recorder
      .endRecording()
      .toImage(diameter.toInt(), (diameter + spacing + dotDiameter).toInt());
  final byteData = await recorded.toByteData(format: ImageByteFormat.png);
  final result = byteData!.buffer.asUint8List();
  await cacheManager.putFile(
    url,
    result,
    key: cacheKey,
    fileExtension: 'png',
  );
  return result;
}