You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用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

火山引擎 最新活动