Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 56 additions & 44 deletions flutter_map/lib/flutter_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,76 @@ library leaflet_flutter;
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map/src/core/point.dart';
import 'package:flutter_map/src/gestures/gestures.dart';
import 'package:flutter_map/src/geo/crs/crs.dart';
import 'package:flutter_map/src/map/flutter_map_state.dart';
import 'package:flutter_map/src/map/map.dart';
import 'package:latlong/latlong.dart';

export 'src/layer/layer.dart';
export 'src/layer/tile_layer.dart';
export 'src/layer/marker_layer.dart';
export 'src/layer/polyline_layer.dart';
export 'src/map/map.dart';
export 'src/geo/crs/crs.dart';

class FlutterMap extends StatefulWidget {
/// A set of layers' options to used to create the layers on the map
///
/// Usually a list of [TileLayerOptions], [MarkerLayerOptions] and
/// [PolylineLayerOptions].
final List<LayerOptions> layers;

/// [MapOptions] to create a [MapState] with
///
/// Please note: If both [options] and [mapState] are set, mapState's options
/// will take precedence, but the [:onTap:] callback of the options will be
/// used!
final MapOptions options;
FlutterMap({this.options, this.layers});
State<StatefulWidget> createState() {
return new _FlutterMapState();
}

/// A [MapController], used to control the map
final MapControllerImpl _mapController;

FlutterMap({
Key key,
this.options,
this.layers,
MapController mapController,
}) : _mapController = mapController ?? new MapController(),
super(key: key);

FlutterMapState createState() => new FlutterMapState(_mapController);
}

class _FlutterMapState extends MapGestureMixin {
MapOptions get options => widget.options;
MapState mapState;
abstract class MapController {
/// Moves the map to a specific location and zoom level
void move(LatLng center, double zoom);

initState() {
super.initState();
mapState = new MapState(options);
}
factory MapController() => new MapControllerImpl();
}

Widget build(BuildContext context) {
return new LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
mapState.size =
new Point<double>(constraints.maxWidth, constraints.maxHeight);
var layerWidgets = widget.layers.map(_createLayer).toList();
return new GestureDetector(
onScaleStart: handleScaleStart,
onScaleUpdate: handleScaleUpdate,
onScaleEnd: handleScaleEnd,
onTapUp: handleTapUp,
child: new Container(
child: new Stack(
children: layerWidgets,
),
),
);
});
}
typedef TapCallback(LatLng point);

class MapOptions {
final Crs crs;
final double zoom;
final double minZoom;
final double maxZoom;
final List<LayerOptions> layers;
final bool debug;
final bool interactive;
final TapCallback onTap;
LatLng center;

Widget _createLayer(LayerOptions options) {
if (options is TileLayerOptions) {
return new TileLayer(options: options, mapState: mapState);
}
if (options is MarkerLayerOptions) {
return new MarkerLayer(options, mapState);
}
if (options is PolylineLayerOptions) {
return new PolylineLayer(options, mapState);
}
return null;
MapOptions({
this.crs: const Epsg3857(),
this.center,
this.zoom = 13.0,
this.minZoom,
this.maxZoom,
this.layers,
this.debug = false,
this.interactive = true,
this.onTap,
}) {
if (center == null) center = new LatLng(50.5, 30.51);
}
}
1 change: 1 addition & 0 deletions flutter_map/lib/src/gestures/gestures.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_map/src/core/point.dart';
import 'package:flutter_map/src/map/map.dart';
import 'package:latlong/latlong.dart';
import 'package:flutter_map/flutter_map.dart';

Expand Down
1 change: 1 addition & 0 deletions flutter_map/lib/src/layer/marker_layer.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_map/src/map/map.dart';
import 'package:latlong/latlong.dart';
import 'package:flutter_map/flutter_map.dart';

Expand Down
1 change: 1 addition & 0 deletions flutter_map/lib/src/layer/polyline_layer.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_map/src/map/map.dart';
import 'package:latlong/latlong.dart';
import 'package:flutter_map/flutter_map.dart';
import 'dart:ui';
Expand Down
52 changes: 52 additions & 0 deletions flutter_map/lib/src/map/flutter_map_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map/src/core/point.dart';
import 'package:flutter_map/src/gestures/gestures.dart';
import 'package:flutter_map/src/map/map.dart';

class FlutterMapState extends MapGestureMixin {
final MapControllerImpl mapController;
MapOptions get options => widget.options ?? new MapOptions();
MapState mapState;

FlutterMapState(this.mapController);

initState() {
super.initState();
mapState = new MapState(options);
mapController.state = mapState;
}

Widget build(BuildContext context) {
return new LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
mapState.size =
new Point<double>(constraints.maxWidth, constraints.maxHeight);
var layerWidgets = widget.layers.map(_createLayer).toList();
return new GestureDetector(
onScaleStart: handleScaleStart,
onScaleUpdate: handleScaleUpdate,
onScaleEnd: handleScaleEnd,
onTapUp: handleTapUp,
child: new Container(
child: new Stack(
children: layerWidgets,
),
),
);
});
}

Widget _createLayer(LayerOptions options) {
if (options is TileLayerOptions) {
return new TileLayer(options: options, mapState: mapState);
}
if (options is MarkerLayerOptions) {
return new MarkerLayer(options, mapState);
}
if (options is PolylineLayerOptions) {
return new PolylineLayer(options, mapState);
}
return null;
}
}
67 changes: 26 additions & 41 deletions flutter_map/lib/src/map/map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,22 @@ import 'package:latlong/latlong.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map/src/core/bounds.dart';
import 'package:flutter_map/src/core/point.dart';
import 'package:flutter_map/src/geo/crs/crs.dart';

typedef TapCallback(LatLng point);

class MapOptions {
final Crs crs;
final double zoom;
final double minZoom;
final double maxZoom;
final List<LayerOptions> layers;
final bool debug;
final bool interactive;
final TapCallback onTap;
LatLng center;

MapOptions({
this.crs: const Epsg3857(),
this.center,
this.zoom = 13.0,
this.minZoom,
this.maxZoom,
this.layers,
this.debug = false,
this.interactive = true,
this.onTap,
}) {
if (center == null) center = new LatLng(50.5, 30.51);

class MapControllerImpl implements MapController {
MapState state;

void move(LatLng center, double zoom) {
state.move(center, zoom);
}
}

class MapState {
class MapState {
final MapOptions options;
final StreamController<Null> _onMoveSink;

double zoom;
double _zoom;
double get zoom => _zoom;

LatLng _lastCenter;
Point _pixelOrigin;
bool _initialized = false;
Expand All @@ -52,7 +33,7 @@ class MapState {
Point get size => _size;
set size(Point s) {
_size = s;
_pixelOrigin = getNewPixelOrigin(this._lastCenter);
_pixelOrigin = getNewPixelOrigin(_lastCenter);
if (!_initialized) {
_init();
_initialized = true;
Expand All @@ -62,18 +43,22 @@ class MapState {
LatLng get center => getCenter() ?? options.center;

void _init() {
this.zoom = options.zoom;
_zoom = options.zoom;
move(options.center, zoom);
}

void move(LatLng center, double zoom, [dynamic data]) {
void dispose() {
_onMoveSink.close();
}

void move(LatLng center, double zoom) {
if (zoom == null) {
zoom = this.zoom;
zoom = _zoom;
}

this.zoom = zoom;
this._lastCenter = center;
this._pixelOrigin = this.getNewPixelOrigin(center);
_zoom = zoom;
_lastCenter = center;
_pixelOrigin = getNewPixelOrigin(center);
_onMoveSink.add(null);
}

Expand All @@ -86,14 +71,14 @@ class MapState {

Point project(LatLng latlng, [double zoom]) {
if (zoom == null) {
zoom = this.zoom;
zoom = _zoom;
}
return options.crs.latLngToPoint(latlng, zoom);
}

LatLng unproject(Point point, [double zoom]) {
if (zoom == null) {
zoom = this.zoom;
zoom = _zoom;
}
return options.crs.pointToLatLng(point, zoom);
}
Expand All @@ -107,13 +92,13 @@ class MapState {
}

double getZoomScale(double toZoom, double fromZoom) {
var crs = this.options.crs;
fromZoom = fromZoom == null ? this.zoom : fromZoom;
var crs = options.crs;
fromZoom = fromZoom == null ? _zoom : fromZoom;
return crs.scale(toZoom) / crs.scale(fromZoom);
}

Bounds getPixelWorldBounds(double zoom) {
return options.crs.getProjectedBounds(zoom == null ? this.zoom : zoom);
return options.crs.getProjectedBounds(zoom == null ? _zoom : zoom);
}

Point getPixelOrigin() {
Expand Down
Loading