Flutter地理JSON地图渲染插件flutter_map_geojson的使用

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

Flutter地理JSON地图渲染插件flutter_map_geojson的使用

简介

GeoJson作为一种用于表示地理特征的数据格式,正逐渐成为获取空间数据(如点、线和多边形)的事实标准。其格式规范定义在RFC7946中,详情可参见https://www.rfc-editor.org/rfc/rfc7946

flutter_map_geojson包解析GeoJson数据,并创建由flutter_map包定义的空间对象,如MarkerPolylinePolygon等。通过默认回调函数完成这些对象的创建,但用户也可以根据需要自定义这些回调函数以实现更复杂的功能,比如指定颜色、线条宽度、标签文本和其他参数。

特性

该GeoJson解析器会创建包含以下内容的列表:

  • Marker:由GeoJson中的Point转换而来。
  • CircleMarker:虽然不在官方GeoJson规范中,但为了方便而加入,用于表示圆形区域。可以通过属性指定半径。
  • Polyline:由LineString转换而来。
  • Polygon:由Polygon或多边形集合MultiPolygon转换而来。

支持的几何类型包括但不限于:

  • Point(点)
  • Circle(圆)
  • Multipoint(多点)
  • LineString(线串)
  • MultiLineString(多线串)
  • Polygon(多边形)
  • MultiPolygon(多边形集合)

入门指南

添加依赖

首先,在pubspec.yaml文件中添加flutter_map_geojson包:

dependencies:
  flutter_map_geojson: ^1.0.8

然后在Dart代码中导入此库:

import 'package:flutter_map_geojson/flutter_map_geojson.dart';

使用方法

下面是一个完整的示例demo,演示如何使用flutter_map_geojson来加载并显示GeoJson数据到Flutter应用中。

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_geojson/flutter_map_geojson.dart';
// ignore: depend_on_referenced_packages
import 'package:latlong2/latlong.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Map GeoJson Demo'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  // 实例化解析器,使用默认设置
  GeoJsonParser geoJsonParser = GeoJsonParser(
    defaultMarkerColor: Colors.red,
    defaultPolygonBorderColor: Colors.red,
    defaultPolygonFillColor: Colors.red.withOpacity(0.1),
    defaultCircleMarkerColor: Colors.red.withOpacity(0.25),
  );

  bool loadingData = false;

  // 定义过滤函数,可以根据属性筛选特定要素
  bool myFilterFunction(Map<String, dynamic> properties) {
    if (properties['section'].toString().contains('Point M-4')) {
      return false;
    } else {
      return true;
    }
  }

  // 定义点击标记时的回调函数
  void onTapMarkerFunction(Map<String, dynamic> map) {
    print('onTapMarkerFunction: $map');
  }

  Future<void> processData() async {
    // 解析测试用的GeoJson字符串
    geoJsonParser.parseGeoJsonAsString(testGeoJson);
  }

  @override
  void initState() {
    geoJsonParser.setDefaultMarkerTapCallback(onTapMarkerFunction);
    geoJsonParser.filterFunction = myFilterFunction;
    loadingData = true;
    processData().then((_) {
      setState(() {
        loadingData = false;
      });
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('GeoJson Processing time: ${Stopwatch()..start()}'),
          duration: const Duration(milliseconds: 5000),
          behavior: SnackBarBehavior.floating,
          backgroundColor: Colors.green,
        ),
      );
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: FlutterMap(
        mapController: MapController(),
        options: const MapOptions(
          initialCenter: LatLng(45.993807, 14.483972),
          initialZoom: 14,
        ),
        children: [
          TileLayer(
            urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
            subdomains: const ['a', 'b', 'c'],
          ),
          if (!loadingData)
            PolygonLayer(polygons: geoJsonParser.polygons),
          if (!loadingData)
            PolylineLayer(polylines: geoJsonParser.polylines),
          if (!loadingData)
            MarkerLayer(markers: geoJsonParser.markers),
          if (!loadingData)
            CircleLayer(circles: geoJsonParser.circles),
          if (loadingData)
            const Center(child: CircularProgressIndicator()),
        ],
      ),
    );
  }
}

示例GeoJson数据

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            [
              [0, 0],
              [14.48295359322937, 45.997073943280554],
              [14.48544268319519, 45.99498698835544],
              [14.485614344572143, 45.992124750758606],
              [14.485356852506714, 45.99033577708827],
              [14.478318736051635, 45.98801002486849],
              [14.475314661954956, 45.99528512959203]
            ]
          ],
          [
            [
              [14.486300990079956, 45.997670201660156],
              [14.493510767911987, 45.99933969094237],
              [14.49668650338562, 45.99361551797875],
              [14.488532587980346, 45.991409168229445],
              [14.486043498014526, 45.990872475261],
              [14.486043498014526, 45.99516587329015],
              [14.4832110852948, 45.99737207327347],
              [14.486300990079956, 45.997670201660156]
            ],
            [
              [14.48706543480164, 45.99650302788219],
              [14.490992188799442, 45.997486860913625],
              [14.492451310503544, 45.99505705971195],
              [14.488138318407596, 45.99395392456707],
              [14.48706543480164, 45.99650302788219]
            ],
            [
              [14.4890395406366, 45.99229686071988],
              [14.493502736437382, 45.993429843946096],
              [14.49281609092957, 45.99435410255712],
              [14.488524556505741, 45.99319132308913],
              [14.4890395406366, 45.99229686071988]
            ]
          ]
        ]
      },
      "properties": {
        "gid": 14,
        "obmocje": "Test polygon"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPoint",
        "coordinates": [
          [14.482672, 45.989040],
          [14.489469, 45.990370]
        ]
      },
      "properties": {
        "section": "Multipoint M-10"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [14.481, 45.982]
      },
      "properties": {
        "section": "Point M-4"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Circle",
        "coordinates": [14.481, 45.982]
      },
      "properties": {
        "section": "Multipoint M-10",
        "radius": 250
      }
    }
  ]
}

以上代码展示了如何配置flutter_map_geojson插件以及如何将其与flutter_map结合使用,以展示来自GeoJson的数据。此外,还介绍了如何自定义标记点击事件的处理逻辑和根据要素属性进行筛选的方法。


更多关于Flutter地理JSON地图渲染插件flutter_map_geojson的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter地理JSON地图渲染插件flutter_map_geojson的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 flutter_map_geojson 插件在 Flutter 应用中渲染地理 JSON 地图的示例代码。这个插件允许你将 GeoJSON 数据渲染到 flutter_map 地图上。

首先,确保你的 pubspec.yaml 文件中包含以下依赖项:

dependencies:
  flutter:
    sdk: flutter
  flutter_map: ^0.14.0  # 请检查最新版本
  flutter_map_geojson: ^0.3.0  # 请检查最新版本

然后运行 flutter pub get 来获取这些依赖项。

接下来,创建一个 Flutter 应用并在你的 Dart 文件中使用以下代码:

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:flutter_map_geojson/flutter_map_geojson.dart';
import 'dart:convert';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter GeoJSON Map'),
        ),
        body: MapScreen(),
      ),
    );
  }
}

class MapScreen extends StatelessWidget {
  final String geoJsonData = '''
  {
    "type": "FeatureCollection",
    "features": [
      {
        "type": "Feature",
        "geometry": {
          "type": "Point",
          "coordinates": [102.0, 0.5]
        },
        "properties": {
          "name": "Sample Point"
        }
      },
      {
        "type": "Feature",
        "geometry": {
          "type": "LineString",
          "coordinates": [
            [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
          ]
        },
        "properties": {
          "name": "Sample Line"
        }
      },
      {
        "type": "Feature",
        "geometry": {
          "type": "Polygon",
          "coordinates": [
            [
              [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]
            ]
          ]
        },
        "properties": {
          "name": "Sample Polygon"
        }
      }
    ]
  }
  ''';

  @override
  Widget build(BuildContext context) {
    return FlutterMap(
      options: MapOptions(
        center: LatLng(0.0, 100.0),
        zoom: 4.0,
      ),
      layers: [
        TileLayerOptions(
          urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
          subdomains: ['a', 'b', 'c'],
        ),
        GeoJsonLayer(
          geoJsonData: jsonDecode(geoJsonData),
          pointBuilder: (context, document) {
            return Marker(
              width: 8.0,
              height: 8.0,
              point: LatLng(document['geometry']['coordinates'][1], document['geometry']['coordinates'][0]),
              builder: (context) => Container(
                child: Icon(
                  Icons.location_on,
                  color: Colors.red,
                ),
              ),
            );
          },
          lineBuilder: (context, document) {
            return Polyline(
              points: document['geometry']['coordinates']
                  .map((coord) => LatLng(coord[1], coord[0]))
                  .toList(),
              color: Colors.blue,
              width: 2.0,
            );
          },
          polygonBuilder: (context, document) {
            return PolygonLayerOptions(
              polygons: document['geometry']['coordinates']
                  .map((outer) => Polygon(
                        points: outer
                            .map((coord) => LatLng(coord[1], coord[0]))
                            .toList(),
                        borderColor: Colors.green,
                        borderWidth: 2.0,
                        color: Colors.greenAccent.withOpacity(0.5),
                      ))
                  .toList(),
            );
          },
        ),
      ],
    );
  }
}

代码解释

  1. 依赖项:在 pubspec.yaml 中添加 flutter_mapflutter_map_geojson 依赖项。
  2. GeoJSON 数据:在 MapScreen 类中定义一个包含 GeoJSON 数据的字符串 geoJsonData
  3. FlutterMap:创建一个 FlutterMap 组件,设置地图的中心点和缩放级别。
  4. TileLayer:添加一个 OpenStreetMap 的瓦片图层。
  5. GeoJsonLayer:使用 GeoJsonLayer 组件渲染 GeoJSON 数据。
    • pointBuilder:用于渲染点(Marker)。
    • lineBuilder:用于渲染线(Polyline)。
    • polygonBuilder:用于渲染多边形(PolygonLayerOptions)。

这段代码展示了如何将 GeoJSON 数据渲染到 Flutter 地图上,包括点、线和多边形。你可以根据需要调整 GeoJSON 数据和样式。

回到顶部