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

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

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

vector_map_tiles 是一个用于 flutter_map 的插件,它允许在Flutter应用程序中使用矢量地图瓦片。这个插件可以加载来自Mapbox或Stadia Maps等源的矢量瓦片,并将它们渲染为flutter_map上的一层。

安装

要安装vector_map_tiles,请访问官方文档获取详细的安装指南。通常情况下,你只需要在pubspec.yaml文件中添加依赖项:

dependencies:
  vector_map_tiles: ^最新版本号

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

使用方法

读取地图样式

首先,你需要从网络或本地读取地图样式文件(通常是JSON格式)。这里以从网络读取为例:

Future<Style> _readStyle() => StyleReader(
      uri: 'https://tiles.stadiamaps.com/styles/osm_bright.json?api_key={key}',
      apiKey: stadiaMapsApiKey,
      logger: const Logger.console())
    .read();

创建地图

接下来,创建一个FlutterMap实例并配置其选项,包括中心点、缩放级别和交互方式等。然后添加VectorTileLayer作为子组件:

FlutterMap(
  mapController: _controller,
  options: MapOptions(
    center: style.center ?? LatLng(49.246292, -123.116226),
    zoom: style.zoom ?? 10,
    maxZoom: 22,
    interactiveFlags: InteractiveFlag.drag |
        InteractiveFlag.flingAnimation |
        InteractiveFlag.pinchMove |
        InteractiveFlag.pinchZoom |
        InteractiveFlag.doubleTapZoom,
  ),
  children: [
    VectorTileLayer(
      theme: style.theme,
      sprites: style.sprites,
      tileProviders: style.providers,
    ),
  ],
)

自定义主题

你可以通过ThemeReader().read(_myTheme())来构建自定义的主题。

指定其他瓦片来源

如果你想要使用不同的瓦片提供者,可以通过指定URL模板来实现:

VectorTileLayer(tileProviders: TileProviders(
  {'openmaptiles': _tileProvider()},
))

VectorTileProvider _tileProvider() => NetworkVectorTileProvider(
  urlTemplate: 'https://tiles.example.com/openmaptiles/{z}/{x}/{y}.pbf?api_key=$myApiKey',
  maximumZoom: 14,
);

支持的瓦片格式

示例代码

下面是一个完整的示例应用,展示了如何使用vector_map_tiles插件:

import 'package:flutter/material.dart';
import 'package:flutter/material.dart' as material show Theme;
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:vector_map_tiles/vector_map_tiles.dart';
import 'package:vector_tile_renderer/vector_tile_renderer.dart' hide TileLayer;

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'vector_map_tiles Example',
      theme: ThemeData.light(),
      home: const MyHomePage(title: 'vector_map_tiles Example'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final MapController _controller = MapController();
  Style? _style;
  Object? _error;

  @override
  void initState() {
    super.initState();
    _initStyle();
  }

  void _initStyle() async {
    try {
      _style = await _readStyle();
    } catch (e, stack) {
      print(e);
      print(stack);
      _error = e;
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    final children = <Widget>[];
    if (_error != null) {
      children.add(Expanded(child: Text(_error!.toString())));
    } else if (_style == null) {
      children.add(const Center(child: CircularProgressIndicator()));
    } else {
      children.add(Flexible(child: _map(_style!)));
      children.add(Row(mainAxisAlignment: MainAxisAlignment.center, children: [_statusText()]));
    }
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: children,
        ),
      ),
    );
  }

  Future<Style> _readStyle() => StyleReader(
        uri: 'mapbox://styles/mapbox/streets-v12?access_token={key}',
        apiKey: mapboxApiKey, // 确保你已经定义了这个变量
        logger: const Logger.console(),
      ).read();

  Widget _map(Style style) => FlutterMap(
        mapController: _controller,
        options: MapOptions(
          initialCenter: style.center ?? const LatLng(49.246292, -123.116226),
          initialZoom: style.zoom ?? 10,
          maxZoom: 22,
          backgroundColor: material.Theme.of(context).canvasColor,
        ),
        children: [
          VectorTileLayer(
            tileProviders: style.providers,
            theme: style.theme,
            sprites: style.sprites,
            maximumZoom: 22,
            tileOffset: TileOffset.mapbox,
            layerMode: VectorTileLayerMode.vector,
          )
        ],
      );

  Widget _statusText() => Padding(
        padding: const EdgeInsets.only(top: 8, bottom: 8),
        child: StreamBuilder(
          stream: _controller.mapEventStream,
          builder: (context, snapshot) {
            return Text(
                'Zoom: ${_controller.camera.zoom.toStringAsFixed(2)} Center: ${_controller.camera.center.latitude.toStringAsFixed(4)},${_controller.camera.center.longitude.toStringAsFixed(4)}');
          },
        ),
      );
}

以上就是关于vector_map_tiles的基本介绍和用法示例。更多高级功能和详细信息,请参阅官方GitHub仓库中的文档和例子。


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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用vector_map_tiles插件的示例代码。这个插件允许你使用矢量地图瓦片来显示地图,并且支持自定义样式和交互。

首先,你需要在你的pubspec.yaml文件中添加vector_map_tiles依赖:

dependencies:
  flutter:
    sdk: flutter
  vector_map_tiles: ^最新版本号  # 请替换为当前最新版本号

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

接下来,是一个简单的Flutter应用示例,展示如何使用vector_map_tiles插件来显示一个矢量地图:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Vector Map Tiles Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MapScreen(),
    );
  }
}

class MapScreen extends StatefulWidget {
  @override
  _MapScreenState createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  late VectorMapController mapController;

  @override
  void initState() {
    super.initState();
    // 初始化地图控制器
    mapController = VectorMapController(
      mapStyle: MapStyle.streets, // 使用内置的街道样式
      onMapReady: () {
        // 地图加载完成后的回调
        print('Map is ready');
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Vector Map Tiles Example'),
      ),
      body: Center(
        child: VectorMapWidget(
          controller: mapController,
          // 配置地图源,这里使用OpenStreetMap的矢量瓦片
          tileProvider: TileProvider(
            urlTemplate: 'https://tiles.openstreetmap.org/{z}/{x}/{y}.pbf',
            attribution: '© OpenStreetMap contributors',
          ),
          // 初始地图中心点和缩放级别
          initialCameraPosition: CameraPosition(
            target: LatLng(40.7128, -74.0060), // 纽约市的坐标
            zoom: 10.0,
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    // 释放地图控制器资源
    mapController.dispose();
    super.dispose();
  }
}

注意事项:

  1. URL模板urlTemplate指定了矢量瓦片的URL模板。在这个例子中,我们使用的是OpenStreetMap的矢量瓦片服务。如果你使用其他服务,请确保URL模板正确。

  2. MapStylemapStyle用于指定地图的样式。vector_map_tiles插件可能支持多种内置样式,你可以查阅插件的文档来获取更多信息。

  3. CameraPositioninitialCameraPosition指定了地图的初始视图位置和缩放级别。

  4. TileProviderattribution字段用于指定地图数据的来源和版权信息,这是一个良好的实践。

  5. 生命周期管理:在dispose方法中调用mapController.dispose()来释放资源,这是管理Flutter中资源的好习惯。

请确保你已经正确配置了网络权限,以便你的应用可以访问矢量瓦片服务。如果你使用的是Android设备,你需要在AndroidManifest.xml中添加网络权限:

<uses-permission android:name="android.permission.INTERNET"/>

这个示例代码只是一个基本的入门示例,vector_map_tiles插件还提供了更多高级功能,如自定义样式、添加覆盖物、处理交互事件等。你可以查阅插件的官方文档来获取更多信息和示例。

回到顶部