Flutter地理坐标转换插件dart_crs的使用
Flutter地理坐标转换插件dart_crs的使用
该插件扩展了 proj4dart
,通过嵌入由国际地球测量学委员会地学分委会维护的 EPSG 地理参数数据集。EPSG 数据集版本为 v11.001。
功能
- 获取 EPSG 坐标参考系统定义的 WKT(Well-Known Text)。
- 在两个 EPSG 坐标参考系统之间转换坐标。
- 使用任何 EPSG 定义的代码创建一个命名的 proj4dart 投影。
开始使用
要使用此插件,在 pubspec.yaml
文件中添加 dart_crs
作为依赖项。例如:
dependencies:
dart_crs: '^1.0.2'
使用示例
创建坐标参考系统
CoordinateReferenceSystem crsLatLong = await CRSFactory.createCRS('EPSG:4326');
转换坐标
CoordinateTransform transform =
await CRSFactory.createCoordinateTransformFromCodes('EPSG:4326', 'EPSG:3183');
Point geoPoint = Point(-45.2395, 60.1425);
Point? gr96Point = transform!.transform(geoPoint);
Point? inversePoint = transform!.inverse(gr96Point!);
提取 WKT 定义
String wkt1 = await WKTReader().fetchWkt('EPSG:4326');
完整示例代码
以下是一个完整的 Flutter 应用程序示例,演示如何使用 dart_crs
插件进行地理坐标转换。
import 'package:dart_crs/dart_crs.dart';
import 'package:flutter/material.dart';
import 'package:proj4dart/proj4dart.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.teal,
textStyle:
const TextStyle(color: Colors.white, fontSize: 14.0))),
),
home: const MyHomePage(title: 'Dart_Crs Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
CoordinateTransform? transform;
TextEditingController xController = TextEditingController();
TextEditingController yController = TextEditingController();
TextEditingController xTransformController = TextEditingController();
TextEditingController yTransformController = TextEditingController();
TextEditingController sourceCRSController = TextEditingController();
TextEditingController targetCRSController = TextEditingController();
Point? sourcePoint;
Point? targetPoint;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: PreferredSize(
preferredSize: const Size.fromHeight(50.0),
child: AppBar(
centerTitle: true,
backgroundColor: Theme.of(context).colorScheme.primary,
title: Text(widget.title,
style: const TextStyle(
fontSize: 22.0,
color: Colors.white,
fontWeight: FontWeight.bold)),
),
),
body: Container(
padding: const EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 30),
const Text('Coordinate Reference Systems',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
const SizedBox(height: 20.0),
Row(
children: [
Expanded(
child: TextField(
controller: sourceCRSController,
decoration: const InputDecoration(
label: Text('Source CRS',
style: TextStyle(
fontSize: 14.0, fontWeight: FontWeight.w500)),
contentPadding:
EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
border: OutlineInputBorder(),
hintText: 'EPSG:xxxx',
hintStyle: TextStyle(fontSize: 13),
enabled: true,
),
),
),
const SizedBox(width: 15.0),
Expanded(
child: TextField(
controller: targetCRSController,
decoration: const InputDecoration(
label: Text('Target CRS',
style: TextStyle(
fontSize: 14.0, fontWeight: FontWeight.w500)),
contentPadding:
EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
border: OutlineInputBorder(),
hintText: 'EPSG:xxxx',
hintStyle: TextStyle(fontSize: 13),
),
),
),
],
),
const SizedBox(height: 30),
const Text('Source Coordinates',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
const SizedBox(height: 20.0),
Row(
children: [
Expanded(
child: TextField(
controller: xController,
decoration: const InputDecoration(
label: Text('X (East) Coordinate',
style: TextStyle(
fontSize: 14.0, fontWeight: FontWeight.w500)),
contentPadding:
EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
border: OutlineInputBorder(),
hintText: 'Enter Coordinate',
hintStyle: TextStyle(fontSize: 13),
enabled: true,
),
),
),
const SizedBox(width: 15.0),
Expanded(
child: TextField(
controller: yController,
decoration: const InputDecoration(
label: Text('Y (North) Coordinate',
style: TextStyle(
fontSize: 14.0, fontWeight: FontWeight.w500)),
contentPadding:
EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
border: OutlineInputBorder(),
hintText: 'Enter Coordinate',
hintStyle: TextStyle(fontSize: 13),
),
),
),
],
),
const SizedBox(height: 30),
const Text('Transformed Coordinates',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
const SizedBox(height: 20.0),
Row(
children: [
Expanded(
child: TextField(
readOnly: true,
controller: xTransformController,
decoration: const InputDecoration(
label: Text('X (East) Coordinate',
style: TextStyle(
fontSize: 14.0, fontWeight: FontWeight.w500)),
contentPadding:
EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
border: OutlineInputBorder(),
// hintText: 'Enter Coordinate',
// hintStyle: TextStyle(fontSize: 13),
enabled: true,
),
),
),
const SizedBox(width: 15.0),
Expanded(
child: TextField(
controller: yTransformController,
decoration: const InputDecoration(
label: Text('Y (North) Coordinate',
style: TextStyle(
fontSize: 14.0, fontWeight: FontWeight.w500)),
contentPadding:
EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
border: OutlineInputBorder(),
// hintText: 'Enter Coordinate',
// hintStyle: TextStyle(fontSize: 13),
),
),
),
],
),
const SizedBox(height: 40),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
child: const Text('Forward',
style: TextStyle(color: Colors.white, fontSize: 14.0)),
onPressed: () async {
final sourceCRS = sourceCRSController.text.toUpperCase();
if (!validateCRS(sourceCRS)) {
FocusManager.instance.primaryFocus?.unfocus();
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Invalid or missing source SRS')));
return;
}
final targetCRS = targetCRSController.text.toUpperCase();
if (!validateCRS(targetCRS)) {
FocusManager.instance.primaryFocus?.unfocus();
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Invalid or missing target SRS')));
return;
}
try {
transform ??=
await CRSFactory.createCoordinateTransformFromCodes(
sourceCRS, targetCRS);
final x = double.parse(xController.value.text);
final y = double.parse(yController.value.text);
sourcePoint = Point(x: x, y: y);
targetPoint = transform!.transform(sourcePoint!);
setState(() {
if (targetPoint != null) {
xTransformController.text =
targetPoint!.x.toStringAsPrecision(11);
yTransformController.text =
targetPoint!.y.toStringAsPrecision(11);
}
});
} on InvalidArgumentException {
if (context.mounted) {
FocusManager.instance.primaryFocus?.unfocus();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content:
Text('Invalid or missing source or target SRS')));
return;
}
}
},
),
const SizedBox(width: 30.0),
ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24.0),
side: const BorderSide(color: Colors.teal))),
),
child: const Text('Inverse',
style: TextStyle(color: Colors.white, fontSize: 16.0)),
onPressed: () async {
if (targetPoint != null) {
targetPoint = transform!.inverse(targetPoint!);
setState(() {
if (targetPoint != null) {
xTransformController.text =
targetPoint!.x.toStringAsPrecision(11);
yTransformController.text =
targetPoint!.y.toStringAsPrecision(11);
}
});
}
},
),
],
),
],
),
),
);
}
bool validateCRS(String crsCode) {
final lc = crsCode.toLowerCase();
return lc.startsWith("epsg:");
}
}
更多关于Flutter地理坐标转换插件dart_crs的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter地理坐标转换插件dart_crs的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用dart_crs
插件来进行地理坐标转换的代码示例。dart_crs
插件用于在不同坐标参考系统(CRS)之间进行转换,这在处理地理数据时非常有用。
首先,确保你已经在pubspec.yaml
文件中添加了dart_crs
依赖:
dependencies:
flutter:
sdk: flutter
dart_crs: ^最新版本号 # 替换为实际可用的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,下面是一个简单的示例,演示如何使用dart_crs
进行地理坐标转换。这个示例假设我们要从WGS84(EPSG:4326)转换到Web Mercator(EPSG:3857):
import 'package:flutter/material.dart';
import 'package:dart_crs/dart_crs.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('地理坐标转换示例'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('输入WGS84坐标 (例如: 经度 116.397128, 纬度 39.916527)'),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 示例坐标:北京的经纬度
double lon = 116.397128;
double lat = 39.916527;
// 创建WGS84坐标
Coordinate wgs84Coordinate = Coordinate(lon, lat, CoordinateReferenceSystem.EPSG_4326);
// 转换到Web Mercator
Coordinate mercatorCoordinate = wgs84Coordinate.transformTo(CoordinateReferenceSystem.EPSG_3857);
// 输出转换后的坐标
print('WGS84坐标: ($lon, $lat)');
print('Web Mercator坐标: (${mercatorCoordinate.x}, ${mercatorCoordinate.y})');
},
child: Text('转换坐标'),
),
],
),
),
),
);
}
}
在这个示例中,我们做了以下几件事:
- 定义依赖:在
pubspec.yaml
中添加dart_crs
依赖。 - 创建Flutter应用:在
MyApp
中,我们定义了一个简单的UI,包含一个按钮用于触发坐标转换。 - 定义WGS84坐标:使用
Coordinate
类创建一个WGS84坐标(EPSG:4326)。 - 转换坐标:使用
transformTo
方法将WGS84坐标转换为Web Mercator坐标(EPSG:3857)。 - 输出结果:在控制台打印转换前后的坐标。
请注意,dart_crs
插件的具体API和使用方式可能会随着版本更新而变化,因此建议查阅最新的dart_crs文档(如果可用)以获取最准确的信息。
希望这个示例能帮你理解如何在Flutter项目中使用dart_crs
进行地理坐标转换!