Google Maps Flutter:设置上下内边距后精准获取地图中心坐标
如何精准获取设置内边距后的Google Map中心坐标
已知无上下内边距时,Google Map的中心坐标为LatLng(37.7749, -122.4194),当给地图设置顶部内边距50.0px、底部内边距200.0px后,当前通过计算经纬度偏移的方式实现,但精度不足,相关代码如下:
import 'dart:async'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MapSample(), ); } } class MapSample extends StatefulWidget { const MapSample({Key? key}) : super(key: key); @override State<MapSample> createState() => MapSampleState(); } class MapSampleState extends State<MapSample> { bool _desirePadding = true; late GoogleMapController _mapController; @override Widget build(BuildContext context) { LatLng myCoordinate = const LatLng(37.7749, -122.4194); // Center coordinate double desiredTopPadding = 50.0; // Desired top padding value in pixels double desiredBottomPadding = 200.0; // Desired bottom padding value in pixels // Calculate the my lower coordinate double topPaddingInDegrees = (desiredTopPadding / (156543.03392 * cos(myCoordinate.latitude * pi / 180.0))); double bottomPaddingInDegrees = (desiredBottomPadding / (156543.03392 * cos(myCoordinate.latitude * pi / 180.0))); double myLowerCoordinateLatitude = myCoordinate.latitude - (bottomPaddingInDegrees - topPaddingInDegrees); debugPrint("MY LOWER COORDINATE $myLowerCoordinateLatitude"); return Scaffold( body: GoogleMap( initialCameraPosition: CameraPosition( target: myCoordinate, zoom: 17.0, ), padding: _desirePadding == true ? EdgeInsets.only( top: desiredTopPadding, bottom: desiredBottomPadding) : const EdgeInsets.only(top: 0, bottom: 0), onMapCreated: (GoogleMapController controller) async { _mapController = controller; await Future.delayed(const Duration(milliseconds: 1000)); _mapController .animateCamera(CameraUpdate.newCameraPosition(CameraPosition( target: myCoordinate, zoom: 17.0, ))); }, markers: { Marker( infoWindow: const InfoWindow(title: "My Coordinate"), markerId: const MarkerId('myMaker'), position: myCoordinate, ), Marker( infoWindow: const InfoWindow(title: "My Lower Coordinate"), markerId: const MarkerId('lowerMarker'), position: LatLng(myLowerCoordinateLatitude, myCoordinate.longitude), ), }, ), floatingActionButton: Wrap( direction: Axis.vertical, children: <Widget>[ Container( margin: const EdgeInsets.all(10), child: FloatingActionButton.extended( onPressed: () async { final c = CameraPosition( target: _desirePadding ? myCoordinate : LatLng( myLowerCoordinateLatitude, myCoordinate.longitude), zoom: 17.0); _mapController.animateCamera(CameraUpdate.newCameraPosition(c)); }, label: _desirePadding ? const Text('To My Coordinate') : const Text('To My Lower Coordinate'), icon: const Icon(Icons.directions_boat), ), ), Container( margin: const EdgeInsets.all(10), child: FloatingActionButton.extended( onPressed: () { setState(() { _desirePadding = !_desirePadding; }); }, backgroundColor: Colors.deepPurpleAccent, label: _desirePadding ? const Text('Set Padding To Bottom: 0, Top: 0') : Text( 'Set Padding To Bottom: $desiredBottomPadding, Top: $desiredTopPadding'), icon: const Icon(Icons.add), )), // Add more buttons here ], ), ); } }
精准获取中心坐标的方法
原方法依赖固定地球周长系数计算偏移,未考虑地图缩放层级、设备屏幕像素密度以及实时投影变化,导致精度不足。推荐以下两种精准方案:
方案一:直接获取当前相机目标坐标
当地图设置padding并完成相机移动后,通过GoogleMapController的getCameraPosition()方法直接获取当前相机中心坐标,这是最可靠的方式:
// 在需要获取坐标的时机调用(比如相机动画完成后) CameraPosition currentCamera = await _mapController.getCameraPosition(); LatLng paddedCenter = currentCamera.target; debugPrint("设置内边距后的中心坐标: $paddedCenter");
方案二:通过地图投影计算可视区域中心
利用地图投影将屏幕可视区域的中心像素坐标转换为经纬度,步骤如下:
- 获取地图组件的实际尺寸
- 计算padding后的有效可视区域中心像素点
- 通过
Projection将像素点转为经纬度
示例代码:
// 确保地图渲染完成后执行 await Future.delayed(const Duration(milliseconds: 500)); final Projection projection = await _mapController.getProjection(); final Size mapSize = MediaQuery.of(context).size; // 计算有效可视区域的高度 double visibleHeight = mapSize.height - desiredTopPadding - desiredBottomPadding; // 可视区域中心的像素坐标(相对于地图组件左上角) Offset centerPixel = Offset( mapSize.width / 2, desiredTopPadding + visibleHeight / 2, ); // 转换为经纬度 LatLng paddedCenter = projection.fromScreenLocation(centerPixel); debugPrint("计算得到的中心坐标: $paddedCenter");
优化原代码示例
将原代码的onMapCreated方法修改为如下,即可获取精准坐标:
onMapCreated: (GoogleMapController controller) async { _mapController = controller; await Future.delayed(const Duration(milliseconds: 1000)); await _mapController.animateCamera(CameraUpdate.newCameraPosition(CameraPosition( target: myCoordinate, zoom: 17.0, ))); // 获取设置padding后的真实中心坐标 CameraPosition currentCamera = await _mapController.getCameraPosition(); debugPrint("实际中心坐标: ${currentCamera.target}"); },
内容的提问来源于stack exchange,提问作者Cemang Anas
相关产品推荐
相关产品推荐

