Flutter地图展示插件mapbox_maps_flutter的使用
Flutter地图展示插件 mapbox_maps_flutter
的使用
概述
Mapbox Maps SDK Flutter SDK 是由 Mapbox 官方开发的解决方案,允许开发者在 Android 和 iOS 应用中嵌入高度定制的地图。该 SDK 支持最新的 Mapbox Maps SDK 版本(v11.9.0),并且提供了丰富的功能。
注意:Web 和桌面平台不支持此 SDK。
支持的 API
以下是 SDK 支持的功能列表:
功能 | Android | iOS |
---|---|---|
样式 | ✅ | ✅ |
相机位置 | ✅ | ✅ |
相机动画 | ✅ | ✅ |
事件 | ✅ | ✅ |
手势 | ✅ | ✅ |
用户位置 | ✅ | ✅ |
圆形图层 | ✅ | ✅ |
填充图层 | ✅ | ✅ |
填充挤出图层 | ✅ | ✅ |
线条图层 | ✅ | ✅ |
光栅图层 | ✅ | ✅ |
符号图层 | ✅ | ✅ |
山影图层 | ✅ | ✅ |
热力图层 | ✅ | ✅ |
天空图层 | ✅ | ✅ |
GeoJson 数据源 | ✅ | ✅ |
图像数据源 | ✅ | ✅ |
矢量数据源 | ✅ | ✅ |
光栅数据源 | ✅ | ✅ |
光栅dem数据源 | ✅ | ✅ |
圆形注释 | ✅ | ✅ |
点注释 | ✅ | ✅ |
线注释 | ✅ | ✅ |
填充注释 | ✅ | ✅ |
快照工具 | ✅ | ✅ |
离线模式 | ✅ | ✅ |
要求
- iOS 12 或更高版本
- Android SDK 21 或更高版本
- Flutter SDK 3.22.3/Dart SDK 3.4.4 或更高版本
安装
配置凭证
为了运行 Mapbox Maps Flutter SDK,你需要配置 Mapbox Access Token。你可以通过以下方式设置:
MapboxOptions.setAccessToken(ACCESS_TOKEN);
可以通过命令行参数传递 Access Token:
flutter build <platform> --dart-define ACCESS_TOKEN=...
或者在运行应用时传递:
flutter run --dart-define ACCESS_TOKEN=...
也可以在 launch.json
中持久化存储 token:
"configurations": [
{
...
"args": [
"--dart-define", "ACCESS_TOKEN=..."
],
}
]
然后在应用中从环境变量中获取 token:
String ACCESS_TOKEN = String.fromEnvironment("ACCESS_TOKEN");
添加依赖
在 pubspec.yaml
文件中添加依赖:
dependencies:
mapbox_maps_flutter: ^2.5.0
配置权限
你需要授予位置权限才能使用 Mapbox Maps Flutter SDK 的位置组件。可以使用现有的库来请求位置权限,例如 permission_handler
:
await Permission.locationWhenInUse.request();
还需要在两个平台上声明权限:
Android
在 AndroidManifest.xml
中添加以下权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
iOS
在 Runner/Info.plist
中添加以下键值对,并解释为什么需要访问位置:
<key>NSLocationWhenInUseUsageDescription</key>
<string>[Your explanation here]</string>
添加地图
导入 mapbox_maps_flutter
库并添加一个简单的地图:
import 'package:flutter/material.dart';
import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart';
void main() {
runApp(MaterialApp(home: MapWidget()));
}
MapWidget Widget
MapWidget
提供了自定义地图的选项,可以设置 MapOptions
、CameraOptions
、styleURL
等。
MapboxMap 控制器
MapboxMap
控制器实例通过 MapWidget.onMapCreated
回调提供。它允许控制地图、相机、样式等。
示例代码:
class FullMap extends StatefulWidget {
const FullMap();
@override
State createState() => FullMapState();
}
class FullMapState extends State<FullMap> {
MapboxMap? mapboxMap;
_onMapCreated(MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: MapWidget(
key: ValueKey("mapWidget"),
onMapCreated: _onMapCreated,
cameraOptions: CameraOptions(
center: Point(coordinates: Position(-80.1263, 25.7845)).toJson(),
zoom: 12.0),
));
}
}
用户位置
要观察用户的当前位置并在地图上显示位置指示器,可以使用 MapboxMap.location
。
示例代码:
mapboxMap.location.updateSettings(LocationComponentSettings(
locationPuck: LocationPuck(
locationPuck3D: LocationPuck3D(
modelUri:
"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Duck/glTF-Embedded/Duck.gltf"))));
标记和注释
有几种方法可以在地图上添加注释:
- 使用
AnnotationManager
APIs 创建圆形、点、多边形和折线注释。 - 使用样式图层。
示例代码:
mapboxMap.annotations.createPointAnnotationManager().then((pointAnnotationManager) async {
final ByteData bytes = await rootBundle.load('assets/symbols/custom-icon.png');
final Uint8List list = bytes.buffer.asUint8List();
var options = <PointAnnotationOptions>[];
for (var i = 0; i < 5; i++) {
options.add(PointAnnotationOptions(
geometry: createRandomPoint().toJson(), image: list));
}
pointAnnotationManager?.createMulti(options);
});
地图样式
可以通过 MapWidget.styleUri
设置初始样式 URI,或在运行时使用 MapboxMap.loadStyleURI
加载样式:
mapboxMap.loadStyleURI(Styles.LIGHT);
示例代码:
var data = await rootBundle.loadString('assets/polyline.geojson');
await mapboxMap.style.addSource(GeoJsonSource(id: "line", data: data));
await mapboxMap.style.addLayer(LineLayer(
id: "line_layer",
sourceId: "line",
lineJoin: LineJoin.ROUND,
lineCap: LineCap.ROUND,
lineOpacity: 0.7,
lineColor: Colors.red.value,
lineWidth: 8.0));
相机和动画
可以设置起始相机位置:
MapWidget(
key: ValueKey("mapWidget"),
cameraOptions: CameraOptions(
center: Point(coordinates: Position(-80.1263, 25.7845)).toJson(),
zoom: 12.0),
);
或在运行时更新相机位置:
MapboxMap.setCamera(CameraOptions(
center: Point(coordinates: Position(-80.1263, 25.7845)).toJson(),
zoom: 12.0));
启动 flyTo
动画:
mapboxMap?.flyTo(
CameraOptions(
anchor: ScreenCoordinate(x: 0, y: 0),
zoom: 17,
bearing: 180,
pitch: 30),
MapAnimationOptions(duration: 2000, startDelay: 0));
用户交互
用户可以通过标准手势与地图进行交互。可以检索或更新 GestureSettings
使用 MapboxMap.gestures
。
示例代码:
MapWidget(
key: ValueKey("mapWidget"),
onTapListener: (point) {
print("Tapped at $point");
},
onLongTapListener: (point) {
print("Long tapped at $point");
},
onScrollListener: (delta) {
print("Scrolled by $delta");
},
);
完整示例 Demo:
import 'package:flutter/material.dart';
import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
MapboxOptions.setAccessToken("YOUR_ACCESS_TOKEN");
runApp(MaterialApp(home: MapsDemo()));
}
class MapsDemo extends StatelessWidget {
static const String ACCESS_TOKEN = "YOUR_ACCESS_TOKEN";
void _pushPage(BuildContext context, Example page) async {
Navigator.of(context).push(MaterialPageRoute<void>(
builder: (_) => Scaffold(
appBar: AppBar(title: Text(page.title)),
body: page,
)));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('MapboxMaps examples')),
body: ACCESS_TOKEN.isEmpty || ACCESS_TOKEN.contains("YOUR_TOKEN")
? buildAccessTokenWarning()
: ListView.separated(
itemCount: _allPages.length,
separatorBuilder: (_, __) => const Divider(height: 1),
itemBuilder: (_, int index) {
final example = _allPages[index];
return ListTile(
leading: example.leading,
title: Text(example.title),
subtitle: (example.subtitle?.isNotEmpty == true)
? Text(
example.subtitle!,
maxLines: 2,
overflow: TextOverflow.ellipsis,
)
: null,
onTap: () => _pushPage(context, _allPages[index]),
);
},
),
);
}
Widget buildAccessTokenWarning() {
return Container(
color: Colors.red[900],
child: SizedBox.expand(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
"Please pass in your access token with",
"--dart-define=ACCESS_TOKEN=ADD_YOUR_TOKEN_HERE",
"passed into flutter run or add it to args in vscode's launch.json",
]
.map((text) => Padding(
padding: EdgeInsets.all(8),
child: Text(text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.white)),
))
.toList(),
),
),
);
}
}
请确保将 YOUR_ACCESS_TOKEN
替换为你的实际 Mapbox Access Token。
更多关于Flutter地图展示插件mapbox_maps_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter地图展示插件mapbox_maps_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter应用中使用mapbox_maps_flutter
插件来展示地图的示例代码。这个示例展示了如何设置Mapbox地图,并加载一个基本的地图视图。
首先,你需要在你的pubspec.yaml
文件中添加mapbox_maps_flutter
依赖:
dependencies:
flutter:
sdk: flutter
mapbox_maps_flutter: ^0.14.0 # 请检查最新版本号并替换
然后,运行flutter pub get
来安装依赖。
接下来,你需要配置Mapbox的访问令牌。你可以在Mapbox官网创建一个账户,并获取一个访问令牌。将访问令牌添加到你的Android和iOS项目中。
对于Android,在android/app/src/main/AndroidManifest.xml
中添加:
<meta-data
android:name="com.mapbox.mapboxsdk.android.TelemetryEnabled"
android:value="true" />
<meta-data
android:name="com.mapbox.mapboxsdk.android.AccessToken"
android:value="YOUR_MAPBOX_ACCESS_TOKEN" /> <!-- 替换为你的访问令牌 -->
对于iOS,在ios/Runner/Info.plist
中添加:
<key>MGLMapboxAccessToken</key>
<string>YOUR_MAPBOX_ACCESS_TOKEN</string> <!-- 替换为你的访问令牌 -->
然后,你可以在你的Flutter应用中创建一个展示Mapbox地图的页面。以下是一个完整的示例代码:
import 'package:flutter/material.dart';
import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Mapbox Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MapboxMapPage(),
);
}
}
class MapboxMapPage extends StatefulWidget {
@override
_MapboxMapPageState createState() => _MapboxMapPageState();
}
class _MapboxMapPageState extends State<MapboxMapPage> {
final MapboxMapController _controller = MapboxMapController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Mapbox Map'),
),
body: Center(
child: MapboxMap(
mapboxMapController: _controller,
initialCameraPosition: CameraPosition(
target: LatLng(37.7749, -122.4194), // 旧金山
zoom: 12.0,
),
styleFromMapbox: MapStyle.streets, // 使用Mapbox的街道风格
myLocationEnabled: true, // 启用定位
),
),
);
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个显示Mapbox地图的页面。MapboxMap
小部件用于渲染地图,并设置了初始的相机位置(旧金山)和地图样式(街道风格)。我们还启用了定位功能,以便用户可以看到他们当前的位置(如果设备上有定位权限并启用)。
请确保你已经替换了YOUR_MAPBOX_ACCESS_TOKEN
为你的实际Mapbox访问令牌,并且已经处理了定位权限的请求(如果需要)。
这个示例应该能帮助你快速开始在Flutter应用中使用mapbox_maps_flutter
插件展示地图。如果你有更复杂的需求,比如添加标记、绘制多边形等,你可以参考mapbox_maps_flutter
的官方文档和示例代码。