使用用户 imageURL 及其名称为 flutter 中的谷歌地图构建自定义标记

问题描述 投票:0回答:2

尝试使用用户 imageURL 及其名称为 flutter 中的谷歌地图构建自定义标记。就像下图一样,但我对定制油漆不太熟悉。我只知道简单的形状。 我已经按照 this 构建了像给定的图像。

代码:


  Future<BitmapDescriptor> getMarkerImage(NearbyUsers user) async {
    if (user.image != null) {
      final File markerImageFile =
          await DefaultCacheManager().getSingleFile(user.image);
     
      Size s = user.userId == profileData.userId.toString()
          ? Size(150, 150)
          : Size(120, 120);

      var icon = await getMarkerIcon(markerImageFile.path, s, user);
      return icon;
    } else {
    
      return BitmapDescriptor.defaultMarker;
    }
  }
Future<BitmapDescriptor> getMarkerIcon(
      String imagePath, Size size, NearbyUsers user) async {
    final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
    final Canvas canvas = Canvas(pictureRecorder);

    final Radius radius = Radius.circular(size.width / 2);


    final Paint nameTagPaint = Paint()..color = MyTheme.primaryColor;
    final double nameTagWidth = 40.0;

    final Paint shadowPaint = Paint()
      ..color = MyTheme.primaryColor.withAlpha(120);
    final double shadowWidth = 15.0;

    final Paint borderPaint = Paint()..color = Colors.white;
    final double borderWidth = 3.0;

    final double imageOffset = shadowWidth + borderWidth;
  

    
    // Add shadow circle
    canvas.drawRRect(
        RRect.fromRectAndCorners(
          Rect.fromLTWH(0.0, 0.0, size.width, size.height),
          topLeft: radius,
          topRight: radius,
          bottomLeft: radius,
          bottomRight: radius,
        ),
        shadowPaint);

    // Add border circle
    canvas.drawRRect(
        RRect.fromRectAndCorners(
          Rect.fromLTWH(shadowWidth, shadowWidth,
              size.width - (shadowWidth * 2), size.height - (shadowWidth * 2)),
          topLeft: radius,
          topRight: radius,
          bottomLeft: radius,
          bottomRight: radius,
        ),
        borderPaint);


    // Name tag BG
    canvas.drawRRect(
        RRect.fromRectAndCorners(
          Rect.fromCircle(center: Offset(nameTagWidth/2,nameTagWidth/2), radius: size.height *0.4 ),
          topLeft: Radius.circular(8),
          topRight:  Radius.circular(8),
          bottomLeft: Radius.circular(8),
          bottomRight: Radius.circular(8),
        ),
        nameTagPaint);

    // Add Name text
    TextPainter textPainter = TextPainter(textDirection: TextDirection.ltr);
    textPainter.text = TextSpan(
      text: '${user.fname} ${user.lname}',
      style: TextStyle(fontSize: 20.0, color: Colors.white),
    );

    textPainter.layout();
    textPainter.paint(
        canvas,
        Offset(1.0, 1.0),
        // Offset(size.width - nameTagWidth / 2 - textPainter.width / 2,
        //     nameTagWidth / 2 - textPainter.height / 2)
        );
    

    // Oval for the image
    Rect oval = Rect.fromLTWH(imageOffset, imageOffset,
        size.width - (imageOffset * 2), size.height - (imageOffset * 2));

    // Add path for oval image
    canvas.clipPath(Path()..addOval(oval));



    // Add image
    ui.Image image = await getImageFromPath(
        imagePath); // Alternatively use your own method to get the image
    paintImage(canvas: canvas, image: image, rect: oval, fit: BoxFit.fitWidth);

    // Convert canvas to image
    final ui.Image markerAsImage = await pictureRecorder
        .endRecording()
        .toImage(size.width.toInt(), size.height.toInt());

    // Convert image to bytes
    final ByteData byteData =
        await markerAsImage.toByteData(format: ui.ImageByteFormat.png);
    final Uint8List uint8List = byteData.buffer.asUint8List();

    return BitmapDescriptor.fromBytes(uint8List);
  }

Future<ui.Image> getImageFromPath(String imagePath) async {
    File imageFile = File(imagePath);

    Uint8List imageBytes = imageFile.readAsBytesSync();

    final Completer<ui.Image> completer = new Completer();

    ui.decodeImageFromList(imageBytes, (ui.Image img) {
      return completer.complete(img);
    });

    return completer.future;
  }

输出:

flutter dart flutter-layout custom-painter
2个回答
3
投票

经过长期研究,现在我能够理解一点点颤振自定义画家、画家或画布,无论我们如何称呼它。

但我仍然对设置阴影圆圈图像的偏移量感到愚蠢,并且无法根据给定的大小给它们动态偏移量。现在只给出静态偏移。请暂时忽略这一点。

完整代码:

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:upstanders/global/theme/colors.dart';

class MapSample extends StatefulWidget {
  @override
  _MapSampleState createState() => _MapSampleState();
}

class _MapSampleState extends State<MapSample> {
  BitmapDescriptor customIcon;
  Set<Marker> markers = {};
    Future<BitmapDescriptor> createCustomMarkerBitmapWithNameAndImage(
      String imagePath, Size size, String name) async {

      
    TextSpan span = new TextSpan(
        style: new TextStyle(
          height: 1.2,
          color: Colors.black,
          fontSize: 30.0,
          fontWeight: FontWeight.bold,
        ),
        text: name);

    TextPainter tp = new TextPainter(
      text: span,
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
    );
    tp.layout();

    ui.PictureRecorder recorder = new ui.PictureRecorder();
    Canvas canvas = new Canvas(recorder);

    final double shadowWidth = 15.0;
    final double borderWidth = 3.0;
    final double imageOffset = shadowWidth + borderWidth;


    final Radius radius = Radius.circular(size.width / 2);

    final Paint shadowCirclePaint = Paint()
      ..color = MyTheme.primaryColor.withAlpha(180);

    // Add shadow circle
    canvas.drawRRect(
        RRect.fromRectAndCorners(
          Rect.fromLTWH(
              size.width / 8, size.width / 2, size.width, size.height),
          topLeft: radius,
          topRight: radius,
          bottomLeft: radius,
          bottomRight: radius,
        ),
        shadowCirclePaint);

    // TEXT BOX BACKGROUND
    Paint textBgBoxPaint = Paint()..color = MyTheme.primaryColor;
   
    Rect rect = Rect.fromLTWH(
      0,
      0,
      tp.width + 35,
      50,
    );

    canvas.drawRRect(
      RRect.fromRectAndRadius(rect, Radius.circular(10.0)),
      textBgBoxPaint,
    );
    
    //ADD TEXT WITH ALIGN TO CANVAS
    tp.paint(canvas, new Offset(20.0, 5.0)); 

    /* Do your painting of the custom icon here, including drawing text, shapes, etc. */

    Rect oval = Rect.fromLTWH(35, 78, size.width - (imageOffset * 2),
        size.height - (imageOffset * 2));

   
    // ADD  PATH TO OVAL IMAGE
    canvas.clipPath(Path()..addOval(oval));

    ui.Image image = await getImageFromPath(
        imagePath);
    paintImage(canvas: canvas, image: image, rect: oval, fit: BoxFit.fitWidth);

    ui.Picture p = recorder.endRecording();
    ByteData pngBytes = await (await p.toImage(300, 300))
        .toByteData(format: ui.ImageByteFormat.png);

    Uint8List data = Uint8List.view(pngBytes.buffer);

    return BitmapDescriptor.fromBytes(data);
  }

  Future<ui.Image> getImageFromPath(String imagePath) async {
    File imageFile = File(imagePath);

    Uint8List imageBytes = imageFile.readAsBytesSync();

    final Completer<ui.Image> completer = new Completer();

    ui.decodeImageFromList(imageBytes, (ui.Image img) {
      return completer.complete(img);
    });

    return completer.future;
  }


  Future<BitmapDescriptor> getMarkerIcon(String image, String name) async {
    if (image != null) {
      final File markerImageFile =
          await DefaultCacheManager().getSingleFile(image);
      Size s = Size(120, 120);

      var icon = await createCustomMarkerBitmapWithNameAndImage(markerImageFile.path, s, name);
    
      return icon;
    } else {
      return BitmapDescriptor.defaultMarker;
    }
  }

  @override
  void initState() {
    super.initState();
    setAllMarkers();
  }

  setAllMarkers() async {
    markers.add(
      Marker(
        markerId: MarkerId("1"),
        position: LatLng(30.699285146824476, 76.69179040341325),
        icon: await getMarkerIcon(
            "https://quizprojectapp.s3.us-east-2.amazonaws.com/quizImage_1629380529687.png",
            "DAVID"),
      ),
    );
    markers.add(
      Marker(
        markerId: MarkerId("2"),
        position: LatLng(30.70246327295858, 76.69501482303754),
        icon: await getMarkerIcon(
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTcA3AmOb_BMAsPra4XquXuWFMNAi7grJL0ug&usqp=CAU",
            "ROSE"),
      ),
    );
    markers.add(
      Marker(
        markerId: MarkerId("3"),
        position: LatLng(30.704382049382055, 76.70102297115308),
        icon: await getMarkerIcon(
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSuIavvjuQFB38Se2ZNa0GkZ1Gol3C5OwioHA&usqp=CAU",
            "JASSABELLE"),
      ),
    );
    setState(() {});
    
  }

  @override
  build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
          initialCameraPosition:
              CameraPosition(target: const LatLng(30.699285146824476, 76.69179040341325), zoom: 15),
          markers: markers),
    );
  }

}


结果:


0
投票

我刚刚发布了一篇文章,您可以在此处找到有关如何使用任何小部件自定义标记图标的文章。

© www.soinside.com 2019 - 2024. All rights reserved.