Calculating the Distance Between Two Points on Google Maps in Flutter

yousaf@345
4 min readMay 18, 2024

--

In this article, we will dive like how to calculate the distance between two points on a Google Map using Flutter. We’ll walk through the implementation of a Flutter application that allows users to place markers on a map and calculates the distance between these markers. By the end of this article, you’ll have a clear understanding of how to integrate Google Maps with Flutter and perform distance calculations using the Haversine formula.

Getting Started

Before we dive into the code, ensure you have the necessary setup:
1. Flutter SDK installed.
2. A Google Maps API key.
3. The google_maps_flutter package added to your pubspec.yaml file.

Here’s a brief overview of the dependencies:

dependencies:
flutter:
sdk: flutter
google_maps_flutter: ^2.6.1

The Complete Code

Below is the complete code for the DistanceBetweenTwoPoints widget:

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'dart:math';
class DistanceBetweenTwoPoints extends StatefulWidget {
@override
State<DistanceBetweenTwoPoints> createState() => DistanceBetweenTwoPointsState();
}
class DistanceBetweenTwoPointsState extends State<DistanceBetweenTwoPoints> {
GoogleMapController? mapController;
LatLng? _startPoint;
LatLng? _endPoint;
Set<Marker> markers = {};
void addMarker(LatLng latLng) {
if (_startPoint == null) {
_startPoint = latLng;
markers.add(Marker(markerId: MarkerId('start'), position: _startPoint!));
} else if (_endPoint == null) {
_endPoint = latLng;
markers.add(Marker(markerId: MarkerId('end'), position: _endPoint!));
} else {
// Reset if both points are already set
markers.clear();
_startPoint = latLng;
_endPoint = null;
markers.add(Marker(markerId: MarkerId('start'), position: _startPoint!));
}
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Distance Between Two Points'),
),
body: Stack(
children: [
SizedBox(
height: 750,
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: const CameraPosition(
target: LatLng(37.7749, -122.4194),
zoom: 6.0,
),
markers: markers,
onTap: addMarker,
),
),
Align(
alignment: Alignment.bottomCenter,
child: ElevatedButton(
onPressed: _calculateDistance,
child: const Text("Calculate Distance"),
),
)
],
),
);
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
void _calculateDistance() {
if (_startPoint == null || _endPoint == null) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Error'),
content: const Text('Please select both start and end points.'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('OK'),
),
],
),
);
return;
}
double distance = calculateDistance(_startPoint!.latitude, _startPoint!.longitude,
_endPoint!.latitude, _endPoint!.longitude);
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Distance'),
content: Text('The distance between the points is ${distance.toStringAsFixed(2)} km'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('OK'),
),
],
),
);
}
double calculateDistance(double startLatitude, double startLongitude, double endLatitude, double endLongitude) {
const double earthRadius = 6371.0; // Earth's radius in kilometers
double dLat = _degreesToRadians(endLatitude - startLatitude);
double dLon = _degreesToRadians(endLongitude - startLongitude);
double a = sin(dLat / 2) * sin(dLat / 2) +
cos(_degreesToRadians(startLatitude)) *
cos(_degreesToRadians(endLatitude)) *
sin(dLon / 2) *
sin(dLon / 2);
double c = 2 * atan2(sqrt(a), sqrt(1 - a));
return earthRadius * c;
}
double _degreesToRadians(double degrees) {
return degrees * pi / 180;
}
}

Code Explanation

Importing Packages

We start by importing the necessary packages:

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'dart:math';

flutter/material.dart: Provides the Flutter material design widgets.
google_maps_flutter/google_maps_flutter.dart: Allows embedding Google Maps in the Flutter app.
dart:math: Provides mathematical functions and constants.

Widget Structure

We define a stateful widget DistanceBetweenTwoPoints:

class DistanceBetweenTwoPoints extends StatefulWidget {
@override
State<DistanceBetweenTwoPoints> createState() => DistanceBetweenTwoPointsState();
}

The state class DistanceBetweenTwoPointsState contains all the logic and UI components.

Managing Map and Markers

We declare variables for managing the map controller, start and end points, and markers:

GoogleMapController? mapController;
LatLng? _startPoint;
LatLng? _endPoint;
Set<Marker> markers = {};

Adding Markers

The addMarker function handles adding markers to the map:

void addMarker(LatLng latLng) {
if (_startPoint == null) {
_startPoint = latLng;
markers.add(Marker(markerId: MarkerId('start'), position: _startPoint!));
} else if (_endPoint == null) {
_endPoint = latLng;
markers.add(Marker(markerId: MarkerId('end'), position: _endPoint!));
} else {
markers.clear();
_startPoint = latLng;
_endPoint = null;
markers.add(Marker(markerId: MarkerId('start'), position: _startPoint!));
}
setState(() {});
}

Building the UI

The build method constructs the UI:

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Distance Between Two Points'),
),
body: Stack(
children: [
SizedBox(
height: 750,
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: const CameraPosition(
target: LatLng(37.7749, -122.4194),
zoom: 6.0,
),
markers: markers,
onTap: addMarker,
),
),
Align(
alignment: Alignment.bottomCenter,
child: ElevatedButton(
onPressed: _calculateDistance,
child: const Text("Calculate Distance"),
),
)
],
),
);
}

The GoogleMap widget displays the map.
The ElevatedButton triggers the distance calculation.

Map Creation and Distance Calculation

The _onMapCreated and _calculateDistance methods handle map creation and distance calculation:

void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
void _calculateDistance() {
if (_startPoint == null || _endPoint == null) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Error'),
content: const Text('Please select both start and end points.'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('OK'),
),
],
),
);
return;
}
double distance = calculateDistance(_startPoint!.latitude, _startPoint!.longitude,
_endPoint!.latitude, _endPoint!.longitude);
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Distance'),
content: Text('The distance between the points is ${distance.toStringAsFixed(2)} km'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('OK'),
),
],
),
);
}

Calculating the Distance

The calculateDistance method uses the Haversine formula to calculate the distance between two points:

double calculateDistance(double startLatitude, double startLongitude,
double endLatitude, double endLongitude) {
const double earthRadius = 6371.0; // Earth's radius in kilometers

double dLat = _degreesToRadians(endLatitude - startLatitude);
double dLon = _degreesToRadians(endLongitude - startLongitude);

double a = sin(dLat / 2) * sin(dLat / 2) +
cos(_degreesToRadians(startLatitude)) *
cos(_degreesToRadians(endLatitude)) *
sin(dLon / 2) *
sin(dLon / 2);
double c = 2 * atan2(sqrt(a), sqrt(1 - a));

return earthRadius * c;
}

double _degreesToRadians(double degrees) {
return degrees * pi / 180;
}

--

--