使用 Flutter Google 地图插件自定义标记

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

有没有办法使用官方的Flutter Google Maps插件在地图上显示自定义标记?根据文档找不到任何方法。

google-maps plugins flutter
13个回答
24
投票
BitmapDescriptor customIcon;

// make sure to initialize before map loading
BitmapDescriptor.fromAssetImage(ImageConfiguration(size: Size(12, 12)),
        'assets/images/car-icon.png')
    .then((d) {
  customIcon = d;
});

final nearbyCarsLocation = [
  LatLng(24.9286825, 67.0403249),
  LatLng(24.985577, 67.0661056), //24.9294892,67.0391903,18.73z
];

void _getNearByCars() {

  for (var i = 0; i < nearbyCarsLocation.length; i++) {
    var now = new DateTime.now().millisecondsSinceEpoch;
    _markers.add(Marker(
      markerId: MarkerId(nearbyCarsLocation[i].toString() + now.toString()),
      position: nearbyCarsLocation[i],
      // infoWindow: InfoWindow(title: address, snippet: "go here"),
      icon: customIcon ));
  }
  notifyListeners();
}

希望这将有助于获得附近的定制地点


9
投票

我正在使用:

controller.addMarker(MarkerOptions(
  icon: BitmapDescriptor.fromAsset("images/restaurant.png"),
  position: LatLng(40.017870, -105.278350),
));

它在 Android 上运行良好,但在 iOS 上不起作用。


9
投票

BitmapDescriptor.fromAsset
已弃用

请使用

BitmapDescriptor.fromAssetImage
代替。

在选择适当的资源时,它会考虑设备 DPI。请参阅声明分辨率感知的图像资源


7
投票

算法阿西 https://www.youtube.com/watch?v=ajuo0HjN3lY&t=905s

BitmapDescriptor icon;


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


// Cargar imagen del Marker
  getIcons() async {
    var icon = await BitmapDescriptor.fromAssetImage(
        ImageConfiguration(devicePixelRatio: 3.2),
        "assets/images/markeruser.png");
    setState(() {
      this.icon = icon;
    });
  }


// Crear Marker
  createMarkers() {
    markers.add(
      Marker(
        markerId: MarkerId("MarkerCurrent"),
        position: currentLocation,
        icon: icon,
        infoWindow: InfoWindow(
            title: "Mi Ubicacion",
            snippet:
                "Lat ${currentLocation.latitude} - Lng ${currentLocation.longitude}"),
        draggable: true,
        onDragEnd: onDragEnd,
      ),
    );
  }


4
投票

您可以将 Flutter 小部件用于此类的自定义标记

import 'package:flutter/material.dart';
import 'dart:typed_data';
import 'package:flutter/rendering.dart';
import 'dart:ui' as ui;

/// This just adds overlay and builds [_MarkerHelper] on that overlay.
/// [_MarkerHelper] does all the heavy work of creating and getting bitmaps
class MarkerGenerator {
  final Function(List<Uint8List>) callback;
  final List<Widget> markerWidgets;

  MarkerGenerator(this.markerWidgets, this.callback);

  void generate(BuildContext context) {
    WidgetsBinding.instance
        .addPostFrameCallback((_) => afterFirstLayout(context));
  }

  void afterFirstLayout(BuildContext context) {
    addOverlay(context);
  }

  void addOverlay(BuildContext context) {
    OverlayState overlayState = Overlay.of(context);

    OverlayEntry entry;
    entry = OverlayEntry(
        builder: (context) {
          return _MarkerHelper(
            markerWidgets: markerWidgets,
            callback: (List<Uint8List> bitmapList) {
                // Given callback function
                callback.call(bitmapList);
                
                // Remove marker widget stack from Overlay when finished
                entry.remove();
              },
          );
        },
        maintainState: true);

    overlayState.insert(entry);
  }
}

/// Maps are embeding GoogleMap library for Andorid/iOS  into flutter.
///
/// These native libraries accept BitmapDescriptor for marker, which means that for custom markers
/// you need to draw view to bitmap and then send that to BitmapDescriptor.
///
/// Because of that Flutter also cannot accept Widget for marker, but you need draw it to bitmap and
/// that's what this widget does:
///
/// 1) It draws marker widget to tree
/// 2) After painted access the repaint boundary with global key and converts it to uInt8List
/// 3) Returns set of Uint8List (bitmaps) through callback
class _MarkerHelper extends StatefulWidget {
  final List<Widget> markerWidgets;
  final Function(List<Uint8List>) callback;

  const _MarkerHelper({Key key, this.markerWidgets, this.callback})
      : super(key: key);

  @override
  _MarkerHelperState createState() => _MarkerHelperState();
}

class _MarkerHelperState extends State<_MarkerHelper> with AfterLayoutMixin {
  List<GlobalKey> globalKeys = [];

  @override
  void afterFirstLayout(BuildContext context) {
    _getBitmaps(context).then((list) {
      widget.callback(list);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Transform.translate(
          offset: Offset(MediaQuery.of(context).size.width, 0),
          child: Material(
            type: MaterialType.transparency,
            child: Stack(
              children: widget.markerWidgets.map((i) {
                final markerKey = GlobalKey();
                globalKeys.add(markerKey);
                return RepaintBoundary(
                  key: markerKey,
                  child: i,
                );
              }).toList(),
            ),
          ),
    );
  }

  Future<List<Uint8List>> _getBitmaps(BuildContext context) async {
    var futures = globalKeys.map((key) => _getUint8List(key));
    return Future.wait(futures);
  }

  Future<Uint8List> _getUint8List(GlobalKey markerKey) async {
    RenderRepaintBoundary boundary =
    markerKey.currentContext.findRenderObject();
    var image = await boundary.toImage(pixelRatio: 2.0);
    ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    return byteData.buffer.asUint8List();
  }
}

/// AfterLayoutMixin
mixin AfterLayoutMixin<T extends StatefulWidget> on State<T> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => afterFirstLayout(context));
  }

  void afterFirstLayout(BuildContext context);
}

使用示例

import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:map_marker_sample/gist/Gist.dart';

class MapScreen extends StatefulWidget {
  @override
  _MapScreenState createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  List<Marker> markers = [];

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Stack(
          children: <Widget>[
            GoogleMap(
              initialCameraPosition:
                  CameraPosition(target: LatLng(45.811328, 15.975862), zoom: 8),
              markers: markers.toSet(),
            ),
          ],
        ),
    );
  }

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

    MarkerGenerator(markerWidgets(), (bitmaps) {
      setState(() {
        markers = mapBitmapsToMarkers(bitmaps);
      });
    }).generate(context);
  }

  List<Marker> mapBitmapsToMarkers(List<Uint8List> bitmaps) {
    List<Marker> markersList = [];
    bitmaps.asMap().forEach((i, bmp) {
      final city = cities[i];
      markersList.add(Marker(
          markerId: MarkerId(city.name),
          position: city.position,
          icon: BitmapDescriptor.fromBytes(bmp)));
    });
    return markersList;
  }
}

// Example of marker widget
Widget _getMarkerWidget(String name) {
  return Container(
    padding: EdgeInsets.symmetric(horizontal: 0, vertical: 0),
    child: Container(
      padding: EdgeInsets.symmetric(horizontal: 3, vertical: 1.5),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(10),
        border: Border.all(color: Colors.black, width: 1),
        color: Colors.white,
        shape: BoxShape.rectangle,
      ),
      child: Text(
        name,
        style: TextStyle(fontSize: 14, color: Colors.black),
      ),
    ),
  );
}

// Example of backing data
List<City> cities = [
  City("Zagreb", LatLng(45.792565, 15.995832)),
  City("Ljubljana", LatLng(46.037839, 14.513336)),
  City("Novo Mesto", LatLng(45.806132, 15.160768)),
  City("Varaždin", LatLng(46.302111, 16.338036)),
  City("Maribor", LatLng(46.546417, 15.642292)),
  City("Rijeka", LatLng(45.324289, 14.444480)),
  City("Karlovac", LatLng(45.489728, 15.551561)),
  City("Klagenfurt", LatLng(46.624124, 14.307974)),
  City("Graz", LatLng(47.060426, 15.442028)),
  City("Celje", LatLng(46.236738, 15.270346))
];

List<Widget> markerWidgets() {
  return cities.map((c) => _getMarkerWidget(c.name)).toList();
}

class City {
  final String name;
  final LatLng position;

  City(this.name, this.position);
}

来源链接:https://infinum.com/the-capsized-eight/creating-custom-markers-on-google-maps-in-flutter-apps

github存储库:https://github.com/itsJoKr/markers_generator_sample


2
投票

根据新插件 BitmapDescriptor.fromAsset("images/restaurant.png") 无法正常工作,因此请参考此 link 并找到我的解决方案。

Future<BitmapDescriptor> _getAssetIcon(BuildContext context) async {
final Completer<BitmapDescriptor> bitmapIcon =
    Completer<BitmapDescriptor>();
final ImageConfiguration config = createLocalImageConfiguration(context);

const AssetImage('assets/red_square.png')
    .resolve(config)
    .addListener((ImageInfo image, bool sync) async {
  final ByteData bytes =
      await image.image.toByteData(format: ImageByteFormat.png);
  final BitmapDescriptor bitmap =
      BitmapDescriptor.fromBytes(bytes.buffer.asUint8List());
  bitmapIcon.complete(bitmap);
});

return await bitmapIcon.future;}

然后像这样使用它

void _add(LatLng position,String address) async{
final MarkerId markerId = MarkerId('1');
BitmapDescriptor markericon = await _getAssetIcon(context);

// creating a new MARKER
final Marker marker = Marker(
  markerId: markerId,
  position: position,
  infoWindow: InfoWindow(title: address, snippet: 'go here'),
  icon: markericon
);

setState(() {
  _markers[markerId] = marker;
});}

希望它对你有用。


1
投票

**试试这个,

_createMarkerImageFromAsset("assets/locationMarker.png");

 Future <BitmapDescriptor> _createMarkerImageFromAsset(String iconPath) async {
    ImageConfiguration configuration = ImageConfiguration();
     bitmapImage = await BitmapDescriptor.fromAssetImage(
        configuration,iconPath);
    return bitmapImage;
  }

将位图图像设置为标记

 Marker(
        markerId: MarkerId('value'),
        icon: bitmapImage,
        position: LatLng(),
       );

1
投票
final bitmapIcon = await BitmapDescriptor.fromAssetImage(ImageConfiguration(size: Size(48,48)), 'assets/images/marker.png');
Marker(
        markerId: MarkerId('marker_2'),
        position: LatLng(_position.target.latitude, _position.target.longitude),
        draggable: true,
        icon: bitmapIcon,
      )

尝试上面的代码,使用异步编程。


1
投票

实际上只有 google_maps 的示例存储库的注释代码才有效...因为 flutter sdk 在 API 中有一些更改(我目前在 1.8 中) 所以,这就是函数,与 kapil 在 API 中进行一些更改的答案相同,您只需要更改图像路由的“assets/red_square.png”行即可。

Future<BitmapDescriptor> _getAssetIcon(BuildContext context) async { final Completer<BitmapDescriptor> bitmapIcon = Completer<BitmapDescriptor>(); final ImageConfiguration config = createLocalImageConfiguration(context); const AssetImage('assets/red_square.png') .resolve(config) .addListener(ImageStreamListener((ImageInfo image, bool sync) async { final ByteData bytes = await image.image.toByteData(format: ImageByteFormat.png); final BitmapDescriptor bitmap = BitmapDescriptor.fromBytes(bytes.buffer.asUint8List()); bitmapIcon.complete(bitmap); })); return await bitmapIcon.future; }

可能如果你创建一个 BitMapDescriptor 变量,你只需要在添加标记之前第一次调用这个函数,但不要忘记“等待”。

还建议将另外 2 个较大尺寸的图像放入名称为(2.0x 和 3.0x)的文件夹中,您可以在

示例图像

中看到分辨率 不要忘记在 pubspec.yaml 中取消注释“/assets”


1
投票

首先,创建一个变量,

late BitmapDescriptor customIcon;

然后创建一个方法
customMarkers

并添加以下代码。

void customMarker() {
  BitmapDescriptor.fromAssetImage(ImageConfiguration(),'assets/images/filled_circle.png').
  then((value) => {
  customIcon = value
 });
}

之后在初始化状态中调用 
customMarker

方法,以便在创建地图之前加载您的图像。

 @override
  void initState() {
    // your code here
    customMarker();
  }

现在,当应用程序启动时,图像将存储在您的变量中,并在您的 
Marker

icon
参数中使用该变量,如下所示:
Marker(
  icon : customIcon,)



0
投票

MarkerOptions( position: LatLng(41.4219999, 63.0862462), infoWindowText: InfoWindowText("Yur Title", "Your Content"), icon: BitmapDescriptor.fromAsset('images/your_image.png',), ),



0
投票
flutter_map

MapBox 插件 我尝试使用Google Maps来做到这一点,成功地在地图上渲染动态Web资源,但性能非常低。 使用 MapBox 非常棒,您可以立即使用小部件作为标记。


0
投票
BitmapDescriptor.fromBytes

import 'package:flutter/services.dart';

final asset = await rootBundle.load('assets/images/marker.png');
final icon = BitmapDescriptor.fromBytes(asset.buffer.asUint8List());

      markers.add(
        Marker(
          markerId: MarkerId('id'),
          icon: icon,
          position: LatLng(lat, lng),
        ),
      );

      if (mounted) {
        setState(() {});
      }

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