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
34 changes: 34 additions & 0 deletions flutter_map/lib/flutter_map.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
library leaflet_flutter;

import 'dart:async';

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/geo/crs/crs.dart';
import 'package:flutter_map/src/map/flutter_map_state.dart';
import 'package:flutter_map/src/map/map.dart';
Expand All @@ -13,6 +16,8 @@ export 'src/layer/tile_layer.dart';
export 'src/layer/marker_layer.dart';
export 'src/layer/polyline_layer.dart';
export 'src/geo/crs/crs.dart';
export 'src/geo/latlng_bounds.dart';
export 'package:flutter_map/src/core/point.dart';

class FlutterMap extends StatefulWidget {
/// A set of layers' options to used to create the layers on the map
Expand Down Expand Up @@ -45,11 +50,20 @@ class FlutterMap extends StatefulWidget {
abstract class MapController {
/// Moves the map to a specific location and zoom level
void move(LatLng center, double zoom);
void fitBounds(
LatLngBounds bounds, {
FitBoundsOptions options,
});
bool get ready;
Future<Null> get onReady;
LatLng get center;
double get zoom;

factory MapController() => new MapControllerImpl();
}

typedef TapCallback(LatLng point);
typedef PositionCallback(MapPosition position);

class MapOptions {
final Crs crs;
Expand All @@ -60,6 +74,7 @@ class MapOptions {
final bool debug;
final bool interactive;
final TapCallback onTap;
final PositionCallback onPositionChanged;
LatLng center;

MapOptions({
Expand All @@ -72,7 +87,26 @@ class MapOptions {
this.debug = false,
this.interactive = true,
this.onTap,
this.onPositionChanged,
}) {
if (center == null) center = new LatLng(50.5, 30.51);
}
}

class FitBoundsOptions {
final Point<double> padding;
final double maxZoom;
final double zoom;

const FitBoundsOptions({
this.padding = const Point<double>(0.0, 0.0),
this.maxZoom = 17.0,
this.zoom,
});
}

class MapPosition {
final LatLng center;
final double zoom;
MapPosition({this.center, this.zoom});
}
4 changes: 4 additions & 0 deletions flutter_map/lib/src/core/bounds.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ class Bounds<T extends num> {
);
}

Point<T> get size {
return this.max - this.min;
}

String toString() => "Bounds($min, $max)";
}
7 changes: 7 additions & 0 deletions flutter_map/lib/src/core/center_zoom.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:latlong/latlong.dart';

class CenterZoom {
final LatLng center;
final double zoom;
CenterZoom({this.center, this.zoom});
}
4 changes: 4 additions & 0 deletions flutter_map/lib/src/geo/crs/crs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ abstract class Crs {
return 256 * math.pow(2, zoom);
}

num zoom(double scale) {
return math.log(scale / 256) / math.ln2;
}

Bounds getProjectedBounds(double zoom) {
if (this.infinite) return null;

Expand Down
19 changes: 18 additions & 1 deletion flutter_map/lib/src/geo/latlng_bounds.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import 'package:latlong/latlong.dart';
class LatLngBounds {
LatLng sw;
LatLng ne;
LatLngBounds(LatLng corner1, LatLng corner2) {
LatLngBounds([LatLng corner1, LatLng corner2]) {
extend(corner1);
extend(corner2);
}

void extend(LatLng latlng) {
if (latlng == null) {
return;
}
_extend(latlng, latlng);
}

Expand All @@ -28,4 +31,18 @@ class LatLngBounds {
ne.longitude = math.max(ne2.longitude, ne.longitude);
}
}

double get west => southWest.longitude;
double get south => southWest.latitude;
double get east => northEast.longitude;
double get north => northEast.latitude;

LatLng get southWest => sw;
LatLng get northEast => ne;
LatLng get northWest => new LatLng(north, west);
LatLng get southEast => new LatLng(south, east);

bool get isValid {
return sw != null && ne != null;
}
}
2 changes: 0 additions & 2 deletions flutter_map/lib/src/layer/tile_layer.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:latlong/latlong.dart';
Expand Down
84 changes: 81 additions & 3 deletions flutter_map/lib/src/map/map.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,43 @@
import 'dart:async';
import 'dart:math' as math;

import 'package:flutter_map/src/core/center_zoom.dart';
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';

class MapControllerImpl implements MapController {
MapState state;
Completer<Null> _readyCompleter = new Completer<Null>();
MapState _state;

Future<Null> get onReady => _readyCompleter.future;
void set state(MapState state) {
_state = state;
if (!_readyCompleter.isCompleted) {
_readyCompleter.complete();
}
}

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

void fitBounds(
LatLngBounds bounds, {
FitBoundsOptions options =
const FitBoundsOptions(padding: const Point(24.0, 24.0)),
}) {
_state.fitBounds(bounds, options);
}

bool get ready => _state != null;

LatLng get center => _state.center;
double get zoom => _state.zoom;
}

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

Expand Down Expand Up @@ -60,6 +84,18 @@ class MapState {
_lastCenter = center;
_pixelOrigin = getNewPixelOrigin(center);
_onMoveSink.add(null);

if (options.onPositionChanged != null) {
options.onPositionChanged(new MapPosition(center: center, zoom: zoom));
}
}

void fitBounds(LatLngBounds bounds, FitBoundsOptions options) {
if (!bounds.isValid) {
throw ("Bounds are not valid.");
}
var target = _getBoundsCenterZoom(bounds, options);
move(target.center, target.zoom);
}

LatLng getCenter() {
Expand All @@ -69,6 +105,42 @@ class MapState {
return layerPointToLatLng(_centerLayerPoint);
}

CenterZoom _getBoundsCenterZoom(
LatLngBounds bounds, FitBoundsOptions options) {
var paddingTL = options.padding;
var paddingBR = options.padding;

var zoom = getBoundsZoom(bounds, paddingTL + paddingBR, inside: false);
zoom = math.min(options.maxZoom, zoom);

var paddingOffset = (paddingBR - paddingTL) / 2;
var swPoint = project(bounds.southWest, zoom);
var nePoint = project(bounds.northEast, zoom);
var center = unproject((swPoint + nePoint) / 2 + paddingOffset, zoom);
return new CenterZoom(
center: center,
zoom: zoom,
);
}

double getBoundsZoom(LatLngBounds bounds, Point<double> padding,
{bool inside = false}) {
var zoom = this.zoom ?? 0.0;
var min = this.options.minZoom ?? 0.0;
var max = this.options.maxZoom ?? double.infinity;
var nw = bounds.northWest;
var se = bounds.southEast;
var size = this.size - padding;
var boundsSize = new Bounds(project(se, zoom), project(nw, zoom)).size;
var scaleX = size.x / boundsSize.x;
var scaleY = size.y / boundsSize.y;
var scale = inside ? math.max(scaleX, scaleY) : math.min(scaleX, scaleY);

zoom = getScaleZoom(scale, zoom);

return math.max(min, math.min(max, zoom));
}

Point project(LatLng latlng, [double zoom]) {
if (zoom == null) {
zoom = _zoom;
Expand Down Expand Up @@ -97,6 +169,12 @@ class MapState {
return crs.scale(toZoom) / crs.scale(fromZoom);
}

double getScaleZoom(double scale, double fromZoom) {
var crs = options.crs;
fromZoom = fromZoom == null ? _zoom : fromZoom;
return crs.zoom(scale * crs.scale(fromZoom));
}

Bounds getPixelWorldBounds(double zoom) {
return options.crs.getProjectedBounds(zoom == null ? _zoom : zoom);
}
Expand Down
2 changes: 1 addition & 1 deletion flutter_map/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ dependencies:
sdk: flutter
latlong: ^0.4.0
tuple: ^1.0.0
quiver: ^0.28.0
quiver: ^0.29.0
transparent_image: ^0.1.0
Loading