Flutter地图编辑插件edit_map的使用
Flutter地图编辑插件edit_map的使用
Edit Map
允许用户与各种二维形状进行交互的地图。
灵感来源于FlutterGallery 2D Transformations。
请支持项目:点个❤️并收藏仓库
资源
入门指南
只需导入EditMap
小部件并开始交互:
class _MyHomeView extends StatefulWidget {
const _MyHomeView({Key? key, required this.mapImageFile}) : super(key: key);
final File mapImageFile;
[@override](/user/override)
State<_MyHomeView> createState() => _MyHomeViewState();
}
class _MyHomeViewState extends State<_MyHomeView> {
bool isDraggableDeskShown = false;
List<DeskPayload> desks = [];
DeskPayload? lastModifiedObject;
int index = 0;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
InkWell(
onTap: () {
setState(() {
if (lastModifiedObject != null) {
desks = desks.toList()..add(lastModifiedObject!);
lastModifiedObject = null;
}
isDraggableDeskShown = false;
});
},
child: const Center(
child: Text('Save'),
),
),
InkWell(
onTap: () {
setState(() {
isDraggableDeskShown = true;
});
},
child: const AspectRatio(
aspectRatio: 1,
child: Center(
child: Text(
'+',
style: TextStyle(color: Colors.white, fontSize: 34),
),
),
),
)
],
),
body: SizedBox.expand(
child: EditMap(
isEditMode: true,
mapImage: widget.mapImageFile,
deskParamsList: desks,
selectedDesk: isDraggableDeskShown
? DeskPayload(deskParams: const DeskParams(id: '1'))
: null,
onDeskMoved: (Offset deskPosition) {
if (kDebugMode) {
print(
'---desk moved---\nx:${deskPosition.dx}\ny:${deskPosition.dy}');
}
WidgetsBinding.instance.addPostFrameCallback((_) async {
setState(() {
lastModifiedObject = DeskPayload(
deskParams: DeskParams(
id: (++index).toString(),
area: Area(position: deskPosition),
),
);
});
});
},
),
),
);
}
}
示例代码
以下是完整的示例代码,展示了如何在应用中使用edit_map
插件:
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:edit_map/edit_map.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<File> _loadImage() async {
Response response = await Dio().get(
'https://firebasestorage.googleapis.com/v0/b/workplacer-1deda.appspot.com/o/data%2Fuser%2F0%2Fhash.apps.workplacer%2Fcache%2Fimage_picker4792814428577454194.png?alt=media&token=aca939cc-28fa-4f9e-abfb-be3bd3e2a933',
options: Options(responseType: ResponseType.bytes),
);
final tempDirectory = await getTemporaryDirectory();
final file = File('${tempDirectory.path}/office-plan.jgp');
final raf = file.openSync(mode: FileMode.write);
raf.writeFromSync(response.data);
await raf.close();
return Future.value(file);
}
[@override](/user/override)
Widget build(BuildContext context) {
return FutureBuilder(
future: _loadImage(),
builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
if (snapshot.data != null && snapshot.hasData) {
return _MyHomeView(mapImageFile: snapshot.data!);
}
return const Center(
child: CircularProgressIndicator(
// valueColor: AlwaysStoppedAnimation<Color>(),
),
);
},
);
}
}
class _MyHomeView extends StatefulWidget {
const _MyHomeView({Key? key, required this.mapImageFile}) : super(key: key);
final File mapImageFile;
[@override](/user/override)
State<_MyHomeView> createState() => _MyHomeViewState();
}
class _MyHomeViewState extends State<_MyHomeView> {
bool isDraggableDeskShown = false;
List<DeskPayload> desks = [];
DeskPayload? lastModifiedObject;
int index = 0;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: lastModifiedObject != null
? Slider.adaptive(
value: lastModifiedObject!.area.rotation / 1500,
activeColor: Colors.black,
onChanged: (double value) {
// TODO 修复旋转后的点击问题
final angle = double.parse(value.toStringAsFixed(2)) * 1500;
if (angle != lastModifiedObject!.area.rotation) {
lastModifiedObject =
lastModifiedObject!.copyWith(rotation: angle);
setState(() {});
}
},
max: 0.24,
)
: null,
actions: [
InkWell(
onTap: () {
if (lastModifiedObject != null) {
desks = desks.toList()..add(lastModifiedObject!);
lastModifiedObject = null;
setState(() {});
}
},
child: const Center(
child: Text('Save'),
),
),
InkWell(
onTap: () {
lastModifiedObject =
DeskPayload(deskParams: DeskParams(id: (index++).toString()));
setState(() {});
},
child: const AspectRatio(
aspectRatio: 1,
child: Center(
child: Text(
'+',
style: TextStyle(color: Colors.white, fontSize: 34),
),
),
),
)
],
),
body: SizedBox.expand(
child: EditMap(
isEditMode: true,
mapImage: widget.mapImageFile,
deskParamsList: desks,
selectedDesk: lastModifiedObject,
onDeskMoved: (Offset deskPosition) {
if (kDebugMode) {
print(
'---desk moved---\nx:${deskPosition.dx}\ny:${deskPosition.dy}');
}
WidgetsBinding.instance.addPostFrameCallback((_) async {
setState(() {
lastModifiedObject =
lastModifiedObject?.copyWith(position: deskPosition);
});
});
},
),
),
);
}
}
更多关于Flutter地图编辑插件edit_map的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter地图编辑插件edit_map的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用edit_map
插件的一个基本示例。请注意,edit_map
插件并不是Flutter官方或广泛认可的插件,因此具体API和用法可能会有所不同。假设你有一个类似功能的插件或自定义实现,以下代码展示了如何集成和使用一个地图编辑功能。
首先,确保你已经在pubspec.yaml
文件中添加了必要的依赖项。由于edit_map
不是公认的插件名,这里假设我们使用flutter_map
作为基础地图插件,并自定义编辑功能:
dependencies:
flutter:
sdk: flutter
flutter_map: ^0.14.0 # 使用最新版本
latlong2: ^0.8.0 # flutter_map的依赖
然后,运行flutter pub get
来获取依赖项。
接下来,创建一个Flutter页面来展示和编辑地图。这里我们将使用flutter_map
来显示地图,并通过一些交互组件来实现编辑功能。为了简化,我们假设编辑功能包括添加和移动标记(markers)。
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:positioned_tap_detector/positioned_tap_detector.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 MapController _mapController = MapController();
List<Marker> _markers = [];
LatLng? _tappedPosition;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Map Editor'),
),
body: Stack(
children: [
FlutterMap(
mapController: _mapController,
options: MapOptions(
center: LatLng(0, 0),
zoom: 2.0,
),
layers: [
TileLayerOptions(
urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
subdomains: ['a', 'b', 'c'],
),
MarkerLayerOptions(markers: _markers),
],
),
PositionedTapDetector(
onTapDown: (details) {
final RenderBox? box = context.findRenderObject() as RenderBox?;
final Offset tapPosition = details.globalPosition;
final Offset localPosition = box!.globalToLocal(tapPosition);
final point = _mapController.project(tapPosition);
setState(() {
_tappedPosition = LatLng(point.y, point.x);
_markers.add(
Marker(
width: 80.0,
height: 80.0,
point: _tappedPosition!,
builder: (ctx) => Container(
child: Icon(
Icons.location_on,
color: Colors.red,
size: 40,
),
),
),
);
});
},
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Reset markers for simplicity in this demo
setState(() {
_markers = [];
});
},
tooltip: 'Reset Markers',
child: Icon(Icons.clear),
),
);
}
}
在这个示例中:
- 我们使用了
flutter_map
来显示地图。 PositionedTapDetector
用于检测地图上的点击位置,并将点击位置转换为地图坐标(LatLng
)。- 每次点击地图时,都会在点击位置添加一个标记。
- 浮动操作按钮(FAB)用于重置所有标记。
请注意,这只是一个基础示例,实际的地图编辑功能可能需要更多的定制,例如拖动标记、保存和加载编辑内容等。你可能需要根据具体需求进一步扩展这个示例。