Flutter图像叠加地图插件image_overlay_map的使用
Flutter图像叠加地图插件image_overlay_map的使用
这是一个用于在Flutter中使用本地或网络图片构建地图的插件。它能够自定义标记并根据屏幕缩放重新构建标记。
指导
this.child
地图使用的图片。它会根据设备的不同自动调整大小以适应全屏。
支持本地资源或网络URL。示例演示了如何使用网络图片。
// 使用网络图片作为地图背景
_getWebMap("https://user-images.githubusercontent.com/11880676/117417895-c6f5a380-af55-11eb-8fe4-5db2f40ca82a.png")
this.size
图片的像素尺寸。
示例使用Leaflet CRS.Simple,范围为 [[height / 2, width / 2], [-height / 2, -width / 2]]
。 [0,0]
是图片中心。你可以根据你的标记数据构建一个不同的坐标系。
// 计算图片尺寸
Future<Size> _calculateImageDimension(String imageUrl) {
Completer<Size> completer = Completer();
Image image = new Image(image: CachedNetworkImageProvider(imageUrl));
image.image.resolve(ImageConfiguration()).addListener(
ImageStreamListener(
(ImageInfo image, bool synchronousCall) {
var myImage = image.image;
Size size = Size(myImage.width.toDouble(), myImage.height.toDouble());
completer.complete(size);
},
),
);
return completer.future;
}
this.markers
从标记数据构建的MarkerModel数据。
// 获取标记数据
List<MarkerModel> _getMarker(List<Facility> facilities, Size size) {
List<MarkerModel> result = [];
facilities.forEach((element) {
double dx = size.width / 2 + element.lng;
double dy = size.height / 2 - element.lat;
result.add(MarkerModel(element, Offset(dx, dy)));
});
return result;
}
this.onMarkerClicked
当标记小部件被点击时调用。
// 当标记被点击时弹出对话框
_onMarkerClicked(MarkerModel markerModel) {
return showDialog(
context: context,
builder: (BuildContext context) {
return Center(
child: Text((markerModel.data as Facility).name),
);
},
routeSettings: RouteSettings(name: "/facilityDetail"));
}
this.markerWidgetBuilder
从MarkerModel构建一个小部件。可以根据不同的缩放值构建不同的小部件。
// 构建标记小部件
Widget _getMarkerWidget(double scale, MarkerModel data) {
Facility facility = data.data;
if (facility.facilityId == 1) {
return Icon(Icons.location_on, color: Colors.blue);
}
if (scale > 3) {
return BubbleWidget(
direction: ArrowDirection.bottom,
color: Colors.orange,
strokeColor: Colors.white,
strokeWidth: 1.0,
borderRadius: 3.0,
style: BubbleStyle.stroke,
padding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
child: Text(facility.name,
maxLines: 1,
textAlign: TextAlign.left,
style: TextStyle(color: Colors.white, fontSize: 10.0)));
}
return Icon(Icons.location_on, color: Colors.redAccent);
}
this.onTab
当地图背景图片被点击时调用。
// 当地图背景图片被点击时打印日志
_onTab() {
print("onTab");
}
完整示例代码
以下是完整的示例代码,展示了如何使用 image_overlay_map
插件来创建一个具有可点击标记的地图:
import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:image_overlay_map/image_overlay_map.dart';
import 'bubble_widget.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// 这个小部件是你的应用的根。
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'image overlay map Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'map like leaflet image overlay'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
final List<Facility> _facilityList = [
Facility(1, "facility1", 0, 0), // 中心
Facility(2, "facility2", -100, 0),
Facility(3, "facility3", 100, 0),
Facility(4, "facility4", 0, -100),
Facility(5, "facility5", 0, 100),
];
[@override](/user/override)
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: <Widget>[
_getWebMap(
"https://user-images.githubusercontent.com/11880676/117417895-c6f5a380-af55-11eb-8fe4-5db2f40ca82a.png"),
],
));
}
Widget _getWebMap(String url) {
return FutureBuilder(
future: _calculateImageDimension(url),
builder: (BuildContext context, AsyncSnapshot snapShot) {
if (snapShot.connectionState == ConnectionState.done) {
if (snapShot.hasError) {
return Center(
child: Text("error happened when download image"),
);
}
return Center(
child: MapContainer(
new Image(image: CachedNetworkImageProvider(url)),
snapShot.data,
markers: _getMarker(widget._facilityList, snapShot.data),
markerWidgetBuilder: _getMarkerWidget,
onTab: _onTab,
onMarkerClicked: _onMarkerClicked),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
});
}
Future<Size> _calculateImageDimension(String imageUrl) {
Completer<Size> completer = Completer();
Image image = new Image(image: CachedNetworkImageProvider(imageUrl));
image.image.resolve(ImageConfiguration()).addListener(
ImageStreamListener(
(ImageInfo image, bool synchronousCall) {
var myImage = image.image;
Size size = Size(myImage.width.toDouble(), myImage.height.toDouble());
completer.complete(size);
},
),
);
return completer.future;
}
List<MarkerModel> _getMarker(List<Facility> facilities, Size size) {
List<MarkerModel> result = [];
facilities.forEach((element) {
double dx = size.width / 2 + element.lng;
double dy = size.height / 2 - element.lat;
result.add(MarkerModel(element, Offset(dx, dy)));
});
return result;
}
Widget _getMarkerWidget(double scale, MarkerModel data) {
Facility facility = data.data;
if (facility.facilityId == 1) {
return Icon(Icons.location_on, color: Colors.blue);
}
if (scale > 3) {
return BubbleWidget(
direction: ArrowDirection.bottom,
color: Colors.orange,
strokeColor: Colors.white,
strokeWidth: 1.0,
borderRadius: 3.0,
style: BubbleStyle.stroke,
padding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
child: Text(facility.name,
maxLines: 1,
textAlign: TextAlign.left,
style: TextStyle(color: Colors.white, fontSize: 10.0)));
}
return Icon(Icons.location_on, color: Colors.redAccent);
}
_onMarkerClicked(MarkerModel markerModel) {
return showDialog(
context: context,
builder: (BuildContext context) {
return Center(
child: Text((markerModel.data as Facility).name),
);
},
routeSettings: RouteSettings(name: "/facilityDetail"));
}
_onTab() {
print("onTab");
}
}
class Facility {
int facilityId;
String name;
double lng;
double lat;
Facility(this.facilityId, this.name, this.lng, this.lat);
}
更多关于Flutter图像叠加地图插件image_overlay_map的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图像叠加地图插件image_overlay_map的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用image_overlay_map
插件来实现图像叠加在地图上的代码示例。这个插件允许你将一张图片叠加在地图(如Google Maps或Apple Maps)之上,常用于显示特定区域的自定义覆盖图。
首先,确保你已经在pubspec.yaml
文件中添加了image_overlay_map
依赖:
dependencies:
flutter:
sdk: flutter
image_overlay_map: ^最新版本号 # 替换为实际的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来是一个简单的示例代码,展示如何使用image_overlay_map
插件:
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:image_overlay_map/image_overlay_map.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Image Overlay Map Example'),
),
body: MapWithOverlay(),
),
);
}
}
class MapWithOverlay extends StatefulWidget {
@override
_MapWithOverlayState createState() => _MapWithOverlayState();
}
class _MapWithOverlayState extends State<MapWithOverlay> {
late GoogleMapController _controller;
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
GoogleMap(
mapType: MapType.hybrid,
initialCameraPosition: CameraPosition(
target: LatLng(37.7749, -122.4194),
zoom: 12.0,
),
onMapCreated: (GoogleMapController controller) {
_controller = controller;
},
),
Positioned.fill(
child: ImageOverlayMap(
imageProvider: NetworkImage(
'https://example.com/your-overlay-image.png', // 替换为你的图片URL
),
mapController: _controller,
bounds: LatLngBounds(
northeast: LatLng(37.78, -122.41),
southwest: LatLng(37.77, -122.43),
),
),
),
],
);
}
}
解释:
-
依赖添加:
- 在
pubspec.yaml
中添加image_overlay_map
和google_maps_flutter
(用于显示Google Maps)。
- 在
-
基础布局:
- 使用
Stack
小部件来叠加地图和图像。
- 使用
-
Google Maps:
- 使用
GoogleMap
小部件显示地图,并设置初始相机位置和地图类型。 - 使用
onMapCreated
回调获取GoogleMapController
实例,以便后续操作。
- 使用
-
图像叠加:
- 使用
ImageOverlayMap
小部件将图像叠加在地图上。 imageProvider
属性指定图像源(可以是网络图片或本地图片)。mapController
属性绑定到之前获取的GoogleMapController
实例。bounds
属性定义图像覆盖的地理边界(通过LatLngBounds
指定)。
- 使用
注意事项:
- 确保你已经按照Google Maps Flutter插件的要求,获取并配置了API密钥。
- 图像URL需要是一个可访问的网络图片,或者你可以使用
AssetImage
加载本地图片。 - 根据实际需要调整
LatLngBounds
的值,以确保图像正确覆盖在目标区域。
这个示例展示了基本的图像叠加地图功能,你可以根据需要进一步自定义和扩展。