Flutter矢量瓦片地图插件vector_tile的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter矢量瓦片地图插件vector_tile的使用

vector_tile 是一个用于解析和编码矢量瓦片(Vector Tiles)的Dart包,遵循Mapbox Vector Tile规范2.1。本文将介绍如何在Flutter项目中使用该插件来处理矢量瓦片数据。

功能特性

  • ✅ 解析 .mvt.pbf 文件到原始矢量瓦片格式。
  • ✅ 将原始矢量瓦片特征解码为GeoJson格式(仅支持GeoJson Feature类型)。
  • ✅ 将原始矢量瓦片解码为GeoJson FeatureCollection格式。
  • ✅ 从原始格式数据创建并编码矢量瓦片文件。
  • ❌ 从GeoJson格式数据创建并编码矢量瓦片文件。(TODO)

示例代码

解析与解码

下面是一个示例,展示了如何解析.pbf.mvt文件,并将其转换为GeoJson格式:

import 'package:vector_tile/vector_tile.dart';
import 'dart:io';

void main() async {
  // 读取矢量瓦片文件
  final tileData = await File('../data/sample-12-3262-1923.pbf').readAsBytes();
  
  // 解析字节数据为矢量瓦片对象
  final tile = await VectorTile.fromBytes(bytes: tileData);
  
  // 获取特定图层
  final layer = tile.layers.firstWhere((layer) => layer.name == 'transportation');

  // 遍历图层中的每个特征
  layer.features.forEach((feature) {
    // 解码几何数据
    feature.decodeGeometry();

    // 根据几何类型进行处理
    if (feature.geometryType == GeometryType.Point) {
      var geojson = feature.toGeoJson<GeoJsonPoint>(x: 3262, y: 1923, z: 12);

      print(geojson?.properties);
      print(geojson?.geometry?.coordinates);
    }
  });
}

编码

以下是如何创建矢量瓦片并将其编码为protobuf文件的示例:

import 'package:vector_tile/raw/raw_vector_tile.dart';
import 'dart:io';

void main() async {
  // 创建值列表
  var values = [
    createVectorTileValue(intValue: Int64(65)),
    createVectorTileValue(stringValue: 'basketball'),
  ];

  // 创建特征列表
  var features = [
    createVectorTileFeature(
      id: Int64(31162829580),
      tags: [0, 96, 1, 348],
      type: VectorTile_GeomType.POINT,
      geometry: [9, 8058, 1562],
    ),
  ];

  // 创建图层
  var layers = [
    createVectorTileLayer(
      name: 'building',
      extent: 4096,
      version: 2,
      keys: ['render_height', 'render_min_height'],
      values: values,
      features: features,
    ),
  ];

  // 创建矢量瓦片
  var tile = createVectorTile(layers: layers);

  // 将矢量瓦片保存到磁盘
  await File('./gen/tile.pbf').writeAsBytes(tile.writeToBuffer());
}

API

VectorTile

  • T toGeoJson<T extends GeoJson>({int x, int y, int z}): 将 VectorTile 转换为 GeoJson FeatureCollection。每个Feature都会包含经度/纬度坐标计算,并且会返回具体的 GeoJson 类型。

VectorTileFeature

  • decodeGeometry(): 解码几何数据,这些数据将在调用 getGeoJson 方法时使用。
  • T toGeoJson<T extends GeoJson>({int x, int y, int z}): 将 VectorTile Feature 转换为 GeoJson Feature 格式,包括经度/纬度坐标计算。

完整示例Demo

为了更好地理解如何在Flutter应用中集成矢量瓦片,这里提供一个完整的示例项目结构:

# pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  vector_tile: ^0.0.7
  path_provider: ^2.0.11
// lib/main.dart
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:vector_tile/vector_tile.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Vector Tile Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Vector Tile Demo'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              await _parseAndDecodeTile();
            },
            child: Text('Parse and Decode Tile'),
          ),
        ),
      ),
    );
  }

  Future<void> _parseAndDecodeTile() async {
    final directory = await getApplicationDocumentsDirectory();
    final filePath = '${directory.path}/sample-12-3262-1923.pbf';

    // 假设文件已经存在于本地存储中
    final tileData = await File(filePath).readAsBytes();
    final tile = await VectorTile.fromBytes(bytes: tileData);
    final layer = tile.layers.firstWhere((layer) => layer.name == 'transportation');

    layer.features.forEach((feature) {
      feature.decodeGeometry();

      if (feature.geometryType == GeometryType.Point) {
        var geojson = feature.toGeoJson<GeoJsonPoint>(x: 3262, y: 1923, z: 12);
        print(geojson?.properties);
        print(geojson?.geometry?.coordinates);
      }
    });
  }
}

通过上述步骤,您可以在Flutter项目中成功解析和处理矢量瓦片数据。希望这对您有所帮助!


更多关于Flutter矢量瓦片地图插件vector_tile的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter矢量瓦片地图插件vector_tile的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用vector_tile插件来显示矢量瓦片地图的示例代码。这个示例假设你已经安装了vector_tile插件以及相关的依赖项,并且你的Flutter环境已经配置正确。

首先,确保你的pubspec.yaml文件中包含了vector_tile插件的依赖项:

dependencies:
  flutter:
    sdk: flutter
  vector_tile: ^x.y.z  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖项。

接下来,在你的Flutter项目中创建一个显示矢量瓦片地图的页面。以下是一个基本的示例代码:

import 'package:flutter/material.dart';
import 'package:vector_tile/vector_tile.dart';
import 'dart:typed_data';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong2.dart';
import 'package:vector_tiles_plugin/vector_tiles_plugin.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MapPage(),
    );
  }
}

class MapPage extends StatefulWidget {
  @override
  _MapPageState createState() => _MapPageState();
}

class _MapPageState extends State<MapPage> {
  final DefaultCacheManager _cacheManager = DefaultCacheManager();

  @override
  void initState() {
    super.initState();
    // 初始化缓存管理器
    _cacheManager.openCache();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Vector Tile Map'),
      ),
      body: FlutterMap(
        options: MapOptions(
          center: LatLng(0.0, 0.0), // 设置地图中心点
          zoom: 2.0, // 设置初始缩放级别
        ),
        layers: [
          TileLayerOptions(
            tileProvider: VectorTileProvider(
              urlTemplate: "https://your-vector-tile-server/{z}/{x}/{y}.pbf", // 替换为你的矢量瓦片服务URL
              cacheManager: _cacheManager,
              tileDecoder: (Uint8List bytes) async {
                VectorTile tile = VectorTile.decode(bytes);
                // 这里可以添加对解码后的tile的处理逻辑,比如提取图层、样式等
                return tile;
              },
              renderer: (VectorTile tile, int z, int x, int y) {
                // 自定义渲染逻辑,这里仅作为示例,实际项目中需要更复杂的渲染处理
                List<Polyline> polylines = [];
                for (var layer in tile.layers) {
                  for (var feature in layer.features) {
                    for (var geometry in feature.geometries) {
                      if (geometry is LineString) {
                        List<LatLng> points = geometry.coordinates.map((coord) => LatLng(coord.latitude, coord.longitude)).toList();
                        polylines.add(Polyline(
                          points: points,
                          color: Colors.blue,
                          width: 2.0,
                        ));
                      }
                    }
                  }
                }
                return polylines;
              },
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _cacheManager.close();
    super.dispose();
  }
}

注意事项:

  1. 矢量瓦片服务URL:替换urlTemplate中的URL为你的矢量瓦片服务地址。
  2. 渲染逻辑:上面的示例代码仅展示了如何渲染简单的LineString几何类型。在实际应用中,你可能需要处理更多的几何类型(如PointPolygon)以及更复杂的样式和图层管理。
  3. 依赖项:除了vector_tile插件,这个示例还使用了flutter_mapflutter_cache_manager插件。flutter_map用于地图显示,flutter_cache_manager用于缓存瓦片数据。你需要确保这些依赖项也已正确安装。
  4. 错误处理:在实际应用中,你应该添加适当的错误处理逻辑,比如处理网络请求失败、瓦片解码错误等情况。

这个示例提供了一个基础框架,你可以根据具体需求进行扩展和修改。

回到顶部