使用flutter-map加载百度地图瓦片时瓦片显示混乱,求问题排查及解决方案
使用flutter-map加载百度地图瓦片时瓦片显示混乱,求问题排查及解决方案
嘿,我帮你排查了下你用flutter_map加载百度瓦片的代码,发现了几个关键问题,正是这些问题导致瓦片显示混乱。咱们一步步来分析和解决:
1. 忘记开启TMS模式
百度地图的瓦片Y轴是向上递增的,和标准TMS瓦片的坐标规则一致;而flutter_map默认的TileLayer是遵循Google/OSM的规则(Y轴向下递增)。你在Leaflet代码里特意开了tms: true来适配这个差异,但在flutter_map的代码里却把这个参数注释掉了——这直接导致请求的Y坐标完全反转,瓦片自然会错位乱排。
2. CRS配置的两个关键错误
(1)Y轴反转未配置
flutter_map的Proj4Crs支持通过yAxisFlip参数快速反转Y轴,正好匹配百度地图的Y轴向上规则。你的代码里完全没加这个参数,投影转换时Y轴方向就错了。
(2)CRS代码冲突
你把自定义的百度投影命名为EPSG:3857_Baidu,但创建Proj4Crs时却用了默认的EPSG:3857作为code——这会覆盖flutter_map自带的EPSG:3857坐标系,很容易引发莫名其妙的投影转换问题,应该用自定义的code比如BAIDU:MC。
3. 边界范围(Bounds)配置不准确
你设置的bounds范围和百度瓦片的实际坐标范围不匹配,应该调整为覆盖百度墨卡托投影的完整有效范围,避免瓦片加载时的坐标越界。
修正后的完整代码
import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; import 'package:proj4dart/proj4dart.dart' as proj4; import 'dart:math' show pow; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { // 注册百度专属的墨卡托投影 final baiduProjection = proj4.Projection.add( 'BAIDU:MC', '+proj=merc +a=6378206 +b=6356802.624 +lat_ts=0.0 +lon_0=0.0 +x_0=0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs', ); // 计算百度瓦片的分辨率(和Leaflet保持一致) final resolutions = _calculateBaiduScales(); // 创建适配百度的CRS final baiduCrs = Proj4Crs.fromFactory( code: 'BAIDU:MC', // 自定义code,避免覆盖默认EPSG:3857 proj4Projection: baiduProjection, resolutions: resolutions, origins: const [Point(0, 0)], bounds: const Rect.fromLTRB( 0, 0, 20037508.342789244 * 2, 20037508.342789244 * 2, ), // 匹配百度瓦片的坐标范围 yAxisFlip: true, // 关键:反转Y轴适配百度规则 ); return MaterialApp( home: Scaffold( body: FlutterMap( options: MapOptions( center: const LatLng(41, 115), maxZoom: 19.0, minZoom: 2.0, zoom: 3.0, crs: baiduCrs, ), children: [ TileLayer( urlTemplate: 'http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1', subdomains: const ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], tms: true, // 必须开启,适配百度瓦片Y轴规则 ), ], ), ), ); } static List<double> _calculateBaiduScales() { const level = 19; final scales = <double>[]; scales.add(pow(2, 18).toDouble()); for (var i = 1; i < level; i++) { scales.add(pow(2, (18 - i)).toDouble()); } return scales; } }
额外注意事项
如果在真机测试时出现瓦片加载失败,记得在配置文件里添加百度域名的访问权限:
- Android:在
AndroidManifest.xml里添加<uses-permission android:name="android.permission.INTERNET"/>,并配置网络安全规则允许访问*.bdimg.com; - iOS:在
Info.plist里添加NSAppTransportSecurity的例外规则,允许HTTP访问百度域名(因为百度的瓦片URL是HTTP的)。
内容来源于stack exchange




