Flutter坐标计算插件coordinate_calculator的使用

Flutter坐标计算插件coordinate_calculator的使用

coordinate_calculator 插件用于在 Flutter 应用中进行坐标计算。本文将详细介绍如何安装和使用该插件,并提供一个完整的示例来展示其功能。

使用

首先,在 pubspec.yaml 文件中添加 coordinate_calculator 插件依赖:

dependencies:
  coordinate_calculator:
    git: 
      url: https://github.com/DeliriousLee/CoordinateCalculator.git

然后在 Dart 文件中导入该插件:

import 'package:coordinate_calculator/coordinate_calculator.dart';

接下来,我们可以使用插件提供的方法来计算两个坐标之间的距离(以公里为单位):

var result = DLCoordinateManager.kilometersDistanceFrom(
    lat1: double.parse(_originLatitude.text),
    long1: double.parse(_originLong.text),
    lat2: double.parse(_destLatitude.text),
    long2: double.parse(_destLong.text));

示例

以下是一个完整的示例,展示了如何在 Flutter 应用中使用 coordinate_calculator 插件来计算两个地点之间的直线距离。

主要文件

main.dart
import 'package:coordinate_calculator/coordinate_calculator.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'coordinate_calculator Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Coordinate Calculator 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> {
  double calculatorResult = 0.0;

  final TextEditingController _originLong = TextEditingController();
  final TextEditingController _originLatitude = TextEditingController();
  final TextEditingController _destLong = TextEditingController();
  final TextEditingController _destLatitude = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 54),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            const SizedBox(height: 150),
            const Text('请填写起始目标经纬度后\n点击计算按钮',
                style: TextStyle(
                    color: Color(0xff333333),
                    fontSize: 24,
                    fontWeight: FontWeight.w700)),
            const SizedBox(height: 40),
            Row(
              children: <Widget>[
                Container(
                  child: const Text('起始经度'),
                ),
                const SizedBox(width: 10),
                _buildTextField(
                    controller: _originLong,
                    hintText: '请输入起始地经度',
                    formats: [
                      FilteringTextInputFormatter(RegExp("[0-9.]"), allow: true)
                    ]),
              ],
            ),
            Container(
              height: 1,
              color: const Color(0xffEEEEEE),
            ),
            Row(
              children: <Widget>[
                Container(
                  child: const Text('起始纬度'),
                ),
                const SizedBox(width: 10),
                _buildTextField(
                    controller: _originLatitude,
                    hintText: '请输入起始地纬度',
                    formats: [
                      FilteringTextInputFormatter(RegExp("[0-9.]"), allow: true)
                    ]),
              ],
            ),
            Container(
              height: 1,
              color: const Color(0xffEEEEEE),
            ),
            const SizedBox(height: 20),
            Row(
              children: <Widget>[
                Container(
                  child: const Text('目标经度'),
                ),
                const SizedBox(width: 10),
                _buildTextField(
                    controller: _destLong,
                    hintText: '请输入目的地经度',
                    formats: [
                      FilteringTextInputFormatter(RegExp("[0-9.]"), allow: true)
                    ]),
              ],
            ),
            Container(
              height: 1,
              color: const Color(0xffEEEEEE),
            ),
            Row(
              children: <Widget>[
                Container(
                  child: const Text('目标纬度'),
                ),
                const SizedBox(width: 10),
                _buildTextField(
                    controller: _destLatitude,
                    hintText: '请输入目的地纬度',
                    formats: [
                      FilteringTextInputFormatter(RegExp("[0-9.]"), allow: true)
                    ]),
              ],
            ),
            Container(
              height: 1,
              color: const Color(0xffEEEEEE),
            ),
            SizedBox(height: 32),
            GestureDetector(
              onTap: () {
                if (_originLong.text.isEmpty ||
                    _originLatitude.text.isEmpty ||
                    _destLatitude.text.isEmpty ||
                    _destLong.text.isEmpty) {
                  return;
                }
                var result = DLCoordinateManager.kilometersDistanceFrom(
                    lat1: double.parse(_originLatitude.text),
                    long1: double.parse(_originLong.text),
                    lat2: double.parse(_destLatitude.text),
                    long2: double.parse(_destLong.text));
                calculatorResult = result;
                setState(() {});
              },
              child: Container(
                padding: EdgeInsets.symmetric(vertical: 8),
                child: Center(
                  child: Text('点击计算',
                      style: TextStyle(
                          color: Colors.white,
                          fontSize: 16,
                          fontWeight: FontWeight.w500)),
                ),
                width: double.infinity,
                decoration: BoxDecoration(
                    color: Colors.blue,
                    borderRadius: BorderRadius.all(Radius.circular(8))),
              ),
            ),
            SizedBox(height: 20),
            Text('起始到目的地的距离为${calculatorResult} km',
                style: TextStyle(
                    color: Color(0xff333333),
                    fontSize: 24,
                    fontWeight: FontWeight.w700))
          ],
        ),
      ),
    );
  }

  Widget _buildTextField({
    required TextEditingController controller,
    String? hintText,
    TextInputType? keyboard,
    List<TextInputFormatter>? formats,
    bool visible = true,
  }) {
    return Flexible(
      child: SizedBox(
        height: 36,
        child: TextField(
          inputFormatters: formats,
          keyboardType: keyboard,
          obscureText: !visible,
          cursorColor: Colors.blue,
          style: const TextStyle(
              color: Color(0xff333333),
              fontSize: 16,
              fontWeight: FontWeight.w500),
          decoration: InputDecoration(
            contentPadding: const EdgeInsets.symmetric(vertical: 1),
            hintText: hintText,
            hintStyle: const TextStyle(
                color: Color(0xff999999),
                fontSize: 12,
                fontWeight: FontWeight.w500),
            enabledBorder: const OutlineInputBorder(
                borderSide: BorderSide(width: 0.0, color: Colors.transparent)),
            focusedBorder: const OutlineInputBorder(
                borderSide: BorderSide(width: 0.0, color: Colors.transparent)),
          ),
          controller: controller,
        ),
      ),
    );
  }
}

示例效果

以下是运行上述代码后的示例效果图:

示例效果图

示例效果图

大圆公式

大圆公式用于计算地球上两点之间的距离。公式如下:

d = acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon1 - lon2))

等价且较少出现舍入误差的公式为:

d = 2 * asin(sqrt((sin((lat1 - lat2) / 2))^2 + 
                   cos(lat1) * cos(lat2) * (sin((lon1 - lon2) / 2))^2))

更多关于Flutter坐标计算插件coordinate_calculator的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter坐标计算插件coordinate_calculator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 coordinate_calculator 插件进行坐标计算的 Flutter 代码示例。这个插件通常用于地理坐标(经纬度)之间的转换和计算,比如距离计算等。

首先,确保你已经在 pubspec.yaml 文件中添加了 coordinate_calculator 依赖:

dependencies:
  flutter:
    sdk: flutter
  coordinate_calculator: ^x.y.z  # 请替换为最新版本号

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

以下是一个简单的 Flutter 应用示例,展示如何使用 coordinate_calculator 插件来计算两个地理坐标之间的距离:

import 'package:flutter/material.dart';
import 'package:coordinate_calculator/coordinate_calculator.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Coordinate Calculator Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _lat1Controller = TextEditingController();
  final TextEditingController _lon1Controller = TextEditingController();
  final TextEditingController _lat2Controller = TextEditingController();
  final TextEditingController _lon2Controller = TextEditingController();
  String _distance = '';

  void _calculateDistance() {
    double lat1 = double.tryParse(_lat1Controller.text) ?? 0.0;
    double lon1 = double.tryParse(_lon1Controller.text) ?? 0.0;
    double lat2 = double.tryParse(_lat2Controller.text) ?? 0.0;
    double lon2 = double.tryParse(_lon2Controller.text) ?? 0.0;

    // 使用 coordinate_calculator 计算距离
    double distance = haversine(lat1, lon1, lat2, lon2);
    
    setState(() {
      _distance = '${distance.toStringAsFixed(2)} km';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Coordinate Calculator Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            TextField(
              controller: _lat1Controller,
              decoration: InputDecoration(labelText: 'Latitude 1'),
              keyboardType: TextInputType.numberWithOptions(decimal: true),
            ),
            SizedBox(height: 16),
            TextField(
              controller: _lon1Controller,
              decoration: InputDecoration(labelText: 'Longitude 1'),
              keyboardType: TextInputType.numberWithOptions(decimal: true),
            ),
            SizedBox(height: 16),
            TextField(
              controller: _lat2Controller,
              decoration: InputDecoration(labelText: 'Latitude 2'),
              keyboardType: TextInputType.numberWithOptions(decimal: true),
            ),
            SizedBox(height: 16),
            TextField(
              controller: _lon2Controller,
              decoration: InputDecoration(labelText: 'Longitude 2'),
              keyboardType: TextInputType.numberWithOptions(decimal: true),
            ),
            SizedBox(height: 24),
            ElevatedButton(
              onPressed: _calculateDistance,
              child: Text('Calculate Distance'),
            ),
            SizedBox(height: 16),
            Text(
              'Distance: $_distance',
              style: TextStyle(fontSize: 18),
            ),
          ],
        ),
      ),
    );
  }
}

// haversine 函数计算两个地理坐标之间的距离(单位:公里)
double haversine(double lat1, double lon1, double lat2, double lon2) {
  final R = 6371e3; // 地球半径,单位:米
  final φ1 = lat1.toRadians();
  final φ2 = lat2.toRadians();
  final Δφ = (lat2 - lat1).toRadians();
  final Δλ = (lon2 - lon1).toRadians();

  final a = sin(Δφ / 2) * sin(Δφ / 2) +
      cos(φ1) * cos(φ2) * sin(Δλ / 2) * sin(Δλ / 2);
  final c = 2 * atan2(sqrt(a), sqrt(1 - a));

  return R * c; // 距离,单位:米,转换为公里需要除以1000
}

请注意,这里我们实际上并没有直接使用 coordinate_calculator 插件提供的 haversine 函数,而是手动实现了它,以便展示其背后的数学原理。coordinate_calculator 插件内部已经实现了这些功能,你可以直接使用它提供的 API。然而,由于插件的具体 API 可能会随着版本更新而变化,请参考插件的官方文档以获取最新的使用方法。

如果你希望直接使用插件提供的函数,可以替换 _calculateDistance 方法中的自定义 haversine 函数调用为插件提供的相应方法。例如:

void _calculateDistance() {
  double lat1 = double.tryParse(_lat1Controller.text) ?? 0.0;
  double lon1 = double.tryParse(_lon1Controller.text) ?? 0.0;
  double lat2 = double.tryParse(_lat2Controller.text) ?? 0.0;
  double lon2 = double.tryParse(_lon2Controller.text) ?? 0.0;

  // 假设插件提供了一个名为 haversine 的函数
  // double distance = CoordinateCalculator.haversine(lat1, lon1, lat2, lon2);
  // 注意:上面的代码是假设性的,请查阅插件文档获取正确的方法调用方式

  // 由于我们不知道插件的确切 API,这里我们仍然使用自定义的 haversine 函数
  double distance = haversine(lat1, lon1, lat2, lon2) / 1000; // 转换为公里

  setState(() {
    _distance = '${distance.toStringAsFixed(2)} km';
  });
}

请查阅 coordinate_calculator 插件的文档以获取最新的 API 使用方法,并根据需要调整代码。

回到顶部