Flutter Earth Globe is an interactive 3D sphere widget for Flutter applications. This widget is designed to be easy to use and highly customizable, making it ideal for any application that requires a visually appealing representation of a planet.
This package was inspired by Globe.GL and Sphere.
To install Flutter Earth Globe, follow these steps:
Add the package to your Flutter project's pubspec.yaml file:
dependencies:
flutter_earth_globe: ^2.1.0
or just run
flutter pub add flutter_earth_globe
Import the package in your Dart code:
import 'package:flutter_earth_globe/flutter_earth_globe.dart';
⚠️ Important: When building or running for web, you must use the
--wasmflag for the shaders to work correctly. Without this flag, you may experience rendering issues or strange visual behavior.
# Run for web with WASM
flutter run -d chrome --wasm
# Build for web with WASM
flutter build web --wasm
Here is a basic example of how to integrate the Flutter Earth Globe into your Flutter app:
import 'package:flutter/material.dart';
import 'package:flutter_earth_globe/flutter_earth_globe.dart';
import 'package:flutter_earth_globe/flutter_earth_globe_controller.dart';
class MyGlobe extends StatefulWidget {
@override
_MyGlobeState createState() => _MyGlobeState();
}
class _MyGlobeState extends State<MyGlobe> {
late FlutterEarthGlobeController _controller;
@override
void initState() {
super.initState();
_controller = FlutterEarthGlobeController(
rotationSpeed: 0.05,
isBackgroundFollowingSphereRotation: true,
background: Image.asset('assets/2k_stars.jpg').image,
surface: Image.asset('assets/2k_earth-day.jpg').image,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: FlutterEarthGlobe(
controller: _controller,
radius: 120,
),
),
);
}
}
Flutter Earth Globe supports multiple types of objects that can be placed on or around the globe:
Points are markers placed on the globe's surface at specific coordinates.
_controller.addPoint(Point(
id: '1',
coordinates: const GlobeCoordinates(51.5072, 0.1276),
label: 'London',
isLabelVisible: true,
style: const PointStyle(color: Colors.red, size: 6),
onTap: () => print('London tapped!'),
onHover: () => print('Hovering over London'),
));
| Property | Type | Required | Description |
|---|---|---|---|
id | String | ✅ | Unique identifier for the point |
coordinates | GlobeCoordinates | ✅ | Latitude and longitude position |
label | String? | ❌ | Text label displayed near the point |
labelBuilder | Widget Function()? | ❌ | Custom widget builder for the label |
isLabelVisible | bool | ❌ | Whether to show the label (default: false) |
style | PointStyle | ❌ | Visual style of the point |
onTap | VoidCallback? | ❌ | Callback when point is tapped |
onHover | VoidCallback? | ❌ | Callback when point is hovered |
| Property | Type | Default | Description |
|---|---|---|---|
size | double | 4.0 | Size of the point in pixels |
color | Color | white | Color of the point |
altitude | double | 0.0 | Height above the globe surface |
transitionDuration | int | 500 | Fade in/out animation duration (ms) |
merge | bool | false | Whether to merge with nearby points |
// Add a point
_controller.addPoint(point);
// Update an existing point
_controller.updatePoint('point-id', label: 'New Label', style: newStyle);
// Remove a point
_controller.removePoint('point-id');
// Clear all points
_controller.clearPoints();
// Get a point by ID
Point? point = _controller.getPoint('point-id');
Connections are animated arcs between two coordinates on the globe.
_controller.addPointConnection(PointConnection(
id: 'connection-1',
start: const GlobeCoordinates(51.5072, 0.1276), // London
end: const GlobeCoordinates(40.7128, -74.0060), // New York
label: 'London - New York',
isLabelVisible: true,
style: PointConnectionStyle(
type: PointConnectionType.dashed,
color: Colors.cyan,
lineWidth: 2,
dashAnimateTime: 2000,
animateOnAdd: true,
),
));
| Property | Type | Required | Description |
|---|---|---|---|
id | String | ✅ | Unique identifier for the connection |
start | GlobeCoordinates | ✅ | Starting coordinates |
end | GlobeCoordinates | ✅ | Ending coordinates |
label | String? | ❌ | Text label displayed at the midpoint |
labelBuilder | Widget Function()? | ❌ | Custom widget builder for the label |
isLabelVisible | bool | ❌ | Whether to show the label (default: false) |
curveScale | double | ❌ | Height of the arc curve (default: 0.5) |
style | PointConnectionStyle | ❌ | Visual style of the connection |
onTap | VoidCallback? | ❌ | Callback when connection is tapped |
onHover | VoidCallback? | ❌ | Callback when connection is hovered |
| Property | Type | Default | Description |
|---|---|---|---|
type | PointConnectionType | solid | Line type: solid, dashed, or dotted |
color | Color | white | Color of the connection line |
lineWidth | double | 1.0 | Width of solid lines |
dashSize | double | 4.0 | Length of dashes |
dotSize | double | 1.0 | Size of dots |
spacing | double | 8.0 | Space between dashes/dots |
dashAnimateTime | int | 0 | Time (ms) for dash to travel the arc (0 = disabled) |
transitionDuration | int | 500 | Fade in/out duration (ms) |
animateOnAdd | bool | true | Animate arc growth when added |
growthAnimationDuration | int | 1000 | Arc growth animation duration (ms) |
// Solid line
PointConnectionStyle(type: PointConnectionType.solid)
// Dashed line with animation
PointConnectionStyle(
type: PointConnectionType.dashed,
dashSize: 4,
spacing: 6,
dashAnimateTime: 2000,
)
// Dotted line
PointConnectionStyle(
type: PointConnectionType.dotted,
dotSize: 2,
spacing: 4,
)
// Add a connection
_controller.addPointConnection(connection);
// Update an existing connection
_controller.updatePointConnection('connection-id',
label: 'New Label',
style: newStyle,
);
// Remove a connection
_controller.removePointConnection('connection-id');
// Clear all connections
_controller.clearPointConnections();
Satellites are objects that orbit around the globe with customizable orbital parameters.
// Geostationary satellite
_controller.addSatellite(Satellite(
id: 'geo-sat-1',
coordinates: GlobeCoordinates(0, -75.2),
altitude: 0.35,
label: 'GOES-16',
isLabelVisible: true,
style: SatelliteStyle(
size: 6,
color: Colors.yellow,
shape: SatelliteShape.circle,
hasGlow: true,
),
));
// Orbiting satellite (ISS-like)
_controller.addSatellite(Satellite(
id: 'iss',
coordinates: GlobeCoordinates(0, 0),
altitude: 0.06,
label: 'ISS',
orbit: SatelliteOrbit(
inclination: 51.6,
period: Duration(seconds: 30),
),
style: SatelliteStyle(
size: 8,
shape: SatelliteShape.satelliteIcon,
showOrbitPath: true,
),
));
| Property | Type | Required | Description |
|---|---|---|---|
id | String | ✅ | Unique identifier for the satellite |
coordinates | GlobeCoordinates | ✅ | Position (used if no orbit defined) |
altitude | double | ✅ | Height above globe surface (0.0 - 1.0+) |
label | String? | ❌ | Text label for the satellite |
labelBuilder | Widget Function()? | ❌ | Custom widget builder for the label |
isLabelVisible | bool | ❌ | Whether to show the label (default: false) |
orbit | SatelliteOrbit? | ❌ | Orbital parameters for animation |
style | SatelliteStyle | ❌ | Visual style of the satellite |
| Property | Type | Default | Description |
|---|---|---|---|
size | double | 4.0 | Size of the satellite |
color | Color | white | Color of the satellite |
shape | SatelliteShape | circle | Shape: circle, square, triangle, star, satelliteIcon |
hasGlow | bool | false | Enable glow effect |
glowColor | Color? | null | Color of the glow (defaults to satellite color) |
glowIntensity | double | 0.5 | Intensity of the glow effect |
sizeAttenuation | bool | true | Scale size based on distance |
showOrbitPath | bool | false | Show the orbital path |
orbitPathColor | Color | white30 | Color of the orbit path |
orbitPathWidth | double | 1.0 | Width of the orbit path |
orbitPathDashed | bool | false | Use dashed line for orbit path |
| Property | Type | Default | Description |
|---|---|---|---|
inclination | double | 0.0 | Orbital inclination in degrees |
period | Duration | 90 min | Time for one complete orbit |
raan | double | 0.0 | Right ascension of ascending node |
initialPhase | double | 0.0 | Starting phase in degrees |
eccentricity | double | 0.0 | Orbital eccentricity (0 = circular) |
// Add a satellite
_controller.addSatellite(satellite);
// Update an existing satellite
_controller.updateSatellite('satellite-id',
label: 'New Label',
style: newStyle,
);
// Remove a satellite
_controller.removeSatellite('satellite-id');
// Clear all satellites
_controller.clearSatellites();
// Load surface texture
_controller.loadSurface(Image.asset('assets/2k_earth-day.jpg').image);
// Load night texture (for day/night cycle)
_controller.loadNightSurface(Image.asset('assets/2k_earth-night.jpg').image);
// Load background
_controller.loadBackground(
Image.asset('assets/2k_stars.jpg').image,
isBackgroundFollowingSphereRotation: true,
);
Flutter Earth Globe supports two day/night modes:
Uses separate day and night textures for maximum visual quality:
final _controller = FlutterEarthGlobeController(
surface: Image.asset('assets/2k_earth-day.jpg').image,
nightSurface: Image.asset('assets/2k_earth-night.jpg').image,
isDayNightCycleEnabled: true,
dayNightMode: DayNightMode.textureSwap,
dayNightBlendFactor: 0.15,
);
Applies a color overlay to simulate night without needing a separate texture - perfect for planets without a dedicated night texture:
final _controller = FlutterEarthGlobeController(
surface: Image.asset('assets/2k_mars.jpg').image,
isDayNightCycleEnabled: true,
dayNightMode: DayNightMode.simulated,
simulatedNightColor: const Color(0xFF0a1628), // Deep blue night
simulatedNightIntensity: 0.7, // 0.0 - 1.0
);
// Start animated cycle
_controller.startDayNightCycle(cycleDuration: Duration(seconds: 30));
// Stop animation
_controller.stopDayNightCycle();
// Manual sun position
_controller.setSunPosition(longitude: 45.0, latitude: 10.0);
// Use real-time sun position
_controller.setUseRealTimeSunPosition(true);
// Switch modes at runtime
_controller.setDayNightMode(DayNightMode.simulated);
_controller.setSimulatedNightColor(Colors.indigo.shade900);
_controller.setSimulatedNightIntensity(0.8);
The atmospheric glow is fully customizable:
final _controller = FlutterEarthGlobeController(
// Atmosphere settings
showAtmosphere: true,
atmosphereColor: Colors.cyan, // Glow color
atmosphereOpacity: 0.8, // 0.0 - 1.0
atmosphereThickness: 0.15, // Relative to globe radius
atmosphereBlur: 25.0, // Blur radius
);
// Update at runtime
_controller.setAtmosphereColor(Colors.orange); // Mars-like atmosphere
_controller.setAtmosphereOpacity(0.6);
Tip: Match the atmosphere color to your planet's texture for a cohesive look - blue for Earth, orange for Mars, pale yellow for Venus.
_controller.setSphereStyle(SphereStyle(
shadowColor: Colors.orange.withAlpha(204),
shadowBlurSigma: 20,
));
| Property | Type | Default | Description |
|---|---|---|---|
surface | ImageProvider? | null | Day surface texture |
nightSurface | ImageProvider? | null | Night surface texture |
background | ImageProvider? | null | Background texture |
rotationSpeed | double | 0.0 | Auto-rotation speed |
zoom | double | 0.0 | Initial zoom level |
minZoom | double | -1.0 | Minimum zoom level |
maxZoom | double | 5.0 | Maximum zoom level |
isZoomEnabled | bool | true | Enable zoom gestures |
zoomSensitivity | double | 0.8 | Zoom gesture sensitivity |
panSensitivity | double | 1.0 | Pan gesture sensitivity |
showAtmosphere | bool | true | Show atmospheric glow |
atmosphereColor | Color | blue | Atmosphere glow color |
atmosphereBlur | double | 25.0 | Atmosphere blur radius |
atmosphereThickness | double | 0.15 | Atmosphere thickness |
atmosphereOpacity | double | 0.6 | Atmosphere opacity |
isDayNightCycleEnabled | bool | false | Enable day/night cycle |
dayNightMode | DayNightMode | textureSwap | Mode: textureSwap or simulated |
dayNightBlendFactor | double | 0.15 | Day/night transition sharpness |
simulatedNightColor | Color | dark blue | Overlay color for simulated mode |
simulatedNightIntensity | double | 0.6 | Overlay intensity (0.0 - 1.0) |
useRealTimeSunPosition | bool | false | Calculate sun from real time |
// Start/stop rotation
_controller.startRotation();
_controller.stopRotation();
_controller.toggleRotation();
// Set rotation speed
_controller.setRotationSpeed(0.1);
// Rotate to specific coordinates
_controller.rotateToCoordinates(GlobeCoordinates(lat, lon));
// Set zoom
_controller.setZoom(2.0);
_controller.onLoaded = () {
print('Globe loaded!');
};
FlutterEarthGlobe(
controller: _controller,
radius: 150,
onZoomChanged: (zoom) => print('Zoom: $zoom'),
onHover: (coordinates) => print('Hover: $coordinates'),
onTap: (coordinates) => print('Tap: $coordinates'),
)
We would like to thank all the contributors who have helped make this project a success. Your contributions, big or small, make a significant impact on the development and improvement of this project.
If you would like to contribute, please feel free to fork the repository, make your changes, and submit a pull request.
git checkout -b feature/YourFeature).git commit -am 'Add some feature').git push origin feature/YourFeature).We are excited to see your contributions and are looking forward to growing this project with the community!
You can also support the library by liking it on pub, staring in on Github and reporting any bugs you encounter.
This project is licensed under the MIT License - see the LICENSE file for details.