如何在Flutter中在两个Google地图标记之间进行缩放

16

我正在使用google_maps_flutter软件包,并尝试找出一种方法来在已知位置的两个放置标记之间缩放相机。 欢迎提供任何指针或示例代码。

3个回答

23

要在Google地图中缩放两个Lat Lng边界之间的区域,您可以按照以下步骤进行:

首先,在pubspec.yaml中导入以下库,否则在旧版本中,您可能无法看到与Google地图控制器一起使用的"getVisibleRegion()"方法。

google_maps_flutter: ^0.5.12

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  Completer<GoogleMapController> _controller = Completer();
  GoogleMapController mapController;
  LatLng _lastMapPosition = _center;

  static const LatLng _center = const LatLng(45.521563, -122.677433);

  final Set<Marker> _markers = {};

  void _onMapCreated(GoogleMapController controller) {
    mapController = controller;
    _controller.complete(controller);

    LatLng latLng_1 = LatLng(40.416775, -3.70379);
    LatLng latLng_2 = LatLng(41.385064, 2.173403);
    LatLngBounds bound = LatLngBounds(southwest: latLng_1, northeast: latLng_2);

    setState(() {
      _markers.clear();
      addMarker(latLng_1, "Madrid", "5 Star Rating");
      addMarker(latLng_2, "Barcelona", "7 Star Rating");
    });

    CameraUpdate u2 = CameraUpdate.newLatLngBounds(bound, 50);
    this.mapController.animateCamera(u2).then((void v){
      check(u2,this.mapController);
    });

  }

  void addMarker(LatLng mLatLng, String mTitle, String mDescription){
    _markers.add(Marker(
      // This marker id can be anything that uniquely identifies each marker.
      markerId: MarkerId((mTitle + "_" + _markers.length.toString()).toString()),
      position: mLatLng,
      infoWindow: InfoWindow(
        title: mTitle,
        snippet: mDescription,
      ),
      icon: BitmapDescriptor.defaultMarker,
    ));
  }

  void check(CameraUpdate u, GoogleMapController c) async {
    c.animateCamera(u);
    mapController.animateCamera(u);
    LatLngBounds l1=await c.getVisibleRegion();
    LatLngBounds l2=await c.getVisibleRegion();
    print(l1.toString());
    print(l2.toString());
    if(l1.southwest.latitude==-90 ||l2.southwest.latitude==-90)
      check(u, c);
  }


  void _onCameraMove(CameraPosition position) {
    _lastMapPosition = position.target;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Maps Sample App'),
          backgroundColor: Colors.green[700],
        ),
        body: GoogleMap(
          markers: _markers,
          onMapCreated: _onMapCreated,
          initialCameraPosition: CameraPosition(
            target: _center,
            zoom: 11.0,
          ),
          onCameraMove: _onCameraMove,
        ),
      ),
    );
  }
}

这太棒了。我会去试一下并回复你。一旦实施完毕后,谢谢大量帮助。 - Elvin Opara
这里的_center有什么作用?它是动态的吗? - Panduranga Rao Sadhu
另一种解决方案 https://github.com/flutter/flutter/issues/36653 - giorgio79
//直接动画化相机可能会导致地图大小错误,因此您应该将此指令延迟几毫秒。 Future.delayed(Duration(milliseconds: 50), () { this.mapController.animateCamera(u2).then((void v) { check(u2, this.mapController); }); }); - Osahady
L1和L2之间有什么区别?它们都获取相同的可见区域。 - temirbek

13

上面提出的解决方案很好,但是LatLngBounds有一个重要的限制:

LatLngBounds({@required this.southwest, @required this.northeast})
  : assert(southwest != null),
    assert(northeast != null),
    assert(southwest.latitude <= northeast.latitude); // <--

这意味着第一个坐标必须在第二个坐标的左下方。

我不得不修改方法以适应不同的坐标。

    void _onMapCreated(GoogleMapController controller) {
    mapController = controller;
    _controller.complete(controller);

    //offerLatLng and currentLatLng are custom

    final LatLng offerLatLng = LatLng(
    double.parse(widget.coordinates.first.latLongList.first.latitude),
    double.parse(widget.coordinates.first.latLongList.first.longitude));

    LatLngBounds bound;
    if (offerLatLng.latitude > currentLatLng.latitude &&
        offerLatLng.longitude > currentLatLng.longitude) {
      bound = LatLngBounds(southwest: currentLatLng, northeast: offerLatLng);
    } else if (offerLatLng.longitude > currentLatLng.longitude) {
      bound = LatLngBounds(
          southwest: LatLng(offerLatLng.latitude, currentLatLng.longitude),
          northeast: LatLng(currentLatLng.latitude, offerLatLng.longitude));
    } else if (offerLatLng.latitude > currentLatLng.latitude) {
      bound = LatLngBounds(
          southwest: LatLng(currentLatLng.latitude, offerLatLng.longitude),
          northeast: LatLng(offerLatLng.latitude, currentLatLng.longitude));
    } else {
      bound = LatLngBounds(southwest: offerLatLng, northeast: currentLatLng);
    }

    CameraUpdate u2 = CameraUpdate.newLatLngBounds(bound, 50);
    this.mapController.animateCamera(u2).then((void v){
      check(u2,this.mapController);
    });

  }

非常感谢您提供的这个节省大量时间的代码片段 :) - Ronald Petit
这应该是被接受的答案,非常出色的工作!谢谢! - Diego Lovera
干得好兄弟! - James 666
这比被选中的答案更好。谢谢。 - Cihan Kalmaz

8
上述建议非常好。 如果您正在使用动态源/目的地,则此代码可能适用于您:
Future<void> updateCameraLocation(
  LatLng source,
  LatLng destination,
  GoogleMapController mapController,
) async {
  if (mapController == null) return;

  LatLngBounds bounds;

  if (source.latitude > destination.latitude &&
      source.longitude > destination.longitude) {
    bounds = LatLngBounds(southwest: destination, northeast: source);
  } else if (source.longitude > destination.longitude) {
    bounds = LatLngBounds(
        southwest: LatLng(source.latitude, destination.longitude),
        northeast: LatLng(destination.latitude, source.longitude));
  } else if (source.latitude > destination.latitude) {
    bounds = LatLngBounds(
        southwest: LatLng(destination.latitude, source.longitude),
        northeast: LatLng(source.latitude, destination.longitude));
  } else {
    bounds = LatLngBounds(southwest: source, northeast: destination);
  }

  CameraUpdate cameraUpdate = CameraUpdate.newLatLngBounds(bounds, 70);

  return checkCameraLocation(cameraUpdate, mapController);
}

Future<void> checkCameraLocation(
    CameraUpdate cameraUpdate, GoogleMapController mapController) async {
  mapController.animateCamera(cameraUpdate);
  LatLngBounds l1 = await mapController.getVisibleRegion();
  LatLngBounds l2 = await mapController.getVisibleRegion();

  if (l1.southwest.latitude == -90 || l2.southwest.latitude == -90) {
    return checkCameraLocation(cameraUpdate, mapController);
  }
}

使用方法:

await updateCameraLocation(source, destination, controller);

L1和L2之间有什么区别?它们都获取相同的可见区域。 - temirbek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接