Map attribution & map layers plugin
This commit is contained in:
parent
726cd6b65d
commit
845c38bf04
9 changed files with 168 additions and 16 deletions
36
lib/attributionMapPlugin.dart
Normal file
36
lib/attributionMapPlugin.dart
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter_map/plugin_api.dart';
|
||||
|
||||
class AttributionPluginOptions extends LayerOptions {
|
||||
final String text;
|
||||
|
||||
AttributionPluginOptions({this.text = ""});
|
||||
}
|
||||
|
||||
class AttributionPlugin implements MapPlugin {
|
||||
@override
|
||||
Widget createLayer(LayerOptions options, MapState mapState) {
|
||||
if (options is AttributionPluginOptions) {
|
||||
var style = new TextStyle(
|
||||
// fontWeight: FontWeight.bold,
|
||||
fontSize: 12.0,
|
||||
color: Colors.white,
|
||||
);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: new Text(
|
||||
options.text,
|
||||
style: style,
|
||||
),
|
||||
);
|
||||
}
|
||||
throw ("Unknown options type for Attribution"
|
||||
"plugin: $options");
|
||||
}
|
||||
|
||||
@override
|
||||
bool supportsLayer(LayerOptions options) {
|
||||
return options is AttributionPluginOptions;
|
||||
}
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ class S implements WidgetsLocalizations {
|
|||
String get notPermsUbication => "We don't have permission to get your location";
|
||||
String get notifyAFire => "Notify a fire";
|
||||
String get privacyPolicy => "Privacy Policy";
|
||||
String get supportPageDescription => "You can support this initiative, spreading the word, helping us to develop our software, translating this app to your language, etc.";
|
||||
String get supportPageDescription => "You can support this initiative, spreading the word, helping us to develop our software, translating this app to your language, suggesting other public data sources of fires to use, etc.";
|
||||
String get supportThisInitiative => "Support this initiative";
|
||||
String get toDeleteThisNotification => "Slide horizontally to delete this notification";
|
||||
String get toDeleteThisPlace => "Slide horizontally to delete this place";
|
||||
|
|
@ -158,7 +158,7 @@ class es extends S {
|
|||
@override
|
||||
String get tweetAboutAFireTitle => "Twittea";
|
||||
@override
|
||||
String get supportPageDescription => "Puedes apoyar esta iniciativa, dando difusión, ayudándonos a desarrollar nuestro software, traduciendo esta aplicación a tu idioma, etc.";
|
||||
String get supportPageDescription => "Puedes apoyar esta iniciativa, dando difusión, ayudándonos a desarrollar nuestro software, traduciendo esta aplicación a tu idioma, sugeriendo otras fuentes de datos públicas de fuegos para usar, etc.";
|
||||
@override
|
||||
String get aMinute => "un minuto";
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import 'package:flutter_redux/flutter_redux.dart';
|
|||
import 'package:latlong/latlong.dart';
|
||||
import 'package:share/share.dart';
|
||||
|
||||
import 'attributionMapPlugin.dart';
|
||||
import 'colors.dart';
|
||||
import 'dummyMapPlugin.dart';
|
||||
import 'fireMarkType.dart';
|
||||
|
|
@ -22,7 +23,7 @@ import 'models/fireMapState.dart';
|
|||
import 'redux/actions.dart';
|
||||
import 'slider.dart';
|
||||
import 'zoomMapPlugin.dart';
|
||||
|
||||
import 'layerSelectorMapPlugin.dart';
|
||||
@immutable
|
||||
class _ViewModel {
|
||||
final String serverUrl;
|
||||
|
|
@ -118,18 +119,21 @@ class _genericMapState extends State<genericMap> {
|
|||
assert(_location != null);
|
||||
FireMapState mapState = view.mapState;
|
||||
FireMapStatus status = mapState.status;
|
||||
print('Build map with status: $status');
|
||||
FireMapLayer layer = mapState.layer;
|
||||
print('Build map with status: $status and layer $layer');
|
||||
|
||||
double maxZoom = 18.0; // works?
|
||||
|
||||
MapOptions mapOptions = new MapOptions(
|
||||
center: new LatLng(_location.lat, _location.lon),
|
||||
plugins: globals.isDevelopment
|
||||
? [new ZoomMapPlugin()]
|
||||
: [new DummyMapPlugin()],
|
||||
? [new ZoomMapPlugin(), new AttributionPlugin(), new LayerSelectorMapPlugin()]
|
||||
: [new DummyMapPlugin(), new AttributionPlugin(), new LayerSelectorMapPlugin()],
|
||||
// this works ?
|
||||
interactive: false,
|
||||
zoom: 13.0,
|
||||
// THIS does not works as expected
|
||||
// maxZoom: 6.0,
|
||||
maxZoom: maxZoom,
|
||||
onTap: (callback) {
|
||||
if (status == FireMapStatus.edit) {
|
||||
_location = _location.copyWith(
|
||||
|
|
@ -155,19 +159,49 @@ class _genericMapState extends State<genericMap> {
|
|||
: status == FireMapStatus.subscriptionConfirm
|
||||
? Icons.check
|
||||
: Icons.notifications_off;
|
||||
|
||||
String baseLayer;
|
||||
List<String> subdomains = [];
|
||||
String attribution;
|
||||
switch (layer) {
|
||||
case FireMapLayer.osmc:
|
||||
case FireMapLayer.osmcGrey:
|
||||
attribution = '© OpenStreetMap contributors';
|
||||
break;
|
||||
case FireMapLayer.esri:
|
||||
case FireMapLayer.esriSatellite:
|
||||
case FireMapLayer.esriTerrain:
|
||||
attribution = '© ESRI';
|
||||
}
|
||||
/* tiles from: https://github.com/dceejay/RedMap/blob/1914ed3b9ce4e8a496049849a93282730b4fff02/worldmap/index.html */
|
||||
switch (layer) {
|
||||
case FireMapLayer.osmc:
|
||||
subdomains = ['a', 'b', 'c'];
|
||||
baseLayer = 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png';
|
||||
break;
|
||||
case FireMapLayer.osmcGrey:
|
||||
subdomains = ['a', 'b', 'c'];
|
||||
baseLayer = 'https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png';
|
||||
break;
|
||||
case FireMapLayer.esri:
|
||||
baseLayer = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}';
|
||||
break;
|
||||
case FireMapLayer.esriSatellite:
|
||||
baseLayer = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}';
|
||||
break;
|
||||
case FireMapLayer.esriTerrain:
|
||||
baseLayer = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}';
|
||||
}
|
||||
FlutterMap map = new FlutterMap(
|
||||
options: mapOptions,
|
||||
mapController: mapController,
|
||||
layers: [
|
||||
new TileLayerOptions(
|
||||
maxZoom: 6.0,
|
||||
subdomains: ['a', 'b', 'c'],
|
||||
urlTemplate:
|
||||
'https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png',
|
||||
maxZoom: maxZoom,
|
||||
urlTemplate: baseLayer,
|
||||
subdomains: subdomains,
|
||||
additionalOptions: {
|
||||
// 'opacity': '0.1',
|
||||
'attribution':
|
||||
'© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
},
|
||||
),
|
||||
globals.isDevelopment
|
||||
|
|
@ -181,6 +215,9 @@ class _genericMapState extends State<genericMap> {
|
|||
mapState.falsePos,
|
||||
mapState.fireNotification != null),
|
||||
),
|
||||
// new AttributionPluginOptions(text: "© OpenStreetMap contributors"),
|
||||
new LayerSelectorMapPluginOptions(),
|
||||
new AttributionPluginOptions(text: attribution),
|
||||
],
|
||||
);
|
||||
// mapController.
|
||||
|
|
|
|||
57
lib/layerSelectorMapPlugin.dart
Normal file
57
lib/layerSelectorMapPlugin.dart
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import 'package:comunes_flutter/comunes_flutter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter_map/plugin_api.dart';
|
||||
import 'package:flutter_simple_dependency_injection/injector.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
|
||||
import 'models/appState.dart';
|
||||
import 'redux/actions.dart';
|
||||
|
||||
class LayerSelectorMapPluginOptions extends LayerOptions {
|
||||
final String text;
|
||||
|
||||
LayerSelectorMapPluginOptions({this.text = ""});
|
||||
}
|
||||
|
||||
// https://github.com/apptreesoftware/flutter_map/blob/master/flutter_map_example/lib/pages/plugin_api.dart
|
||||
class LayerSelectorMapPlugin extends MapPlugin {
|
||||
Widget LayerSelectorButton(Store<AppState> store) {
|
||||
return new FloatingActionButton(
|
||||
backgroundColor: Colors.black26,
|
||||
mini: true,
|
||||
child: Icon(Icons.layers, /* size: 40.0, color: Colors.black45, */ ),
|
||||
onPressed: () {
|
||||
store.dispatch(new ToggleMapLayerAction());
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget createLayer(LayerOptions options, MapState mapState) {
|
||||
Store<AppState> store = Injector.getInjector().get<Store<AppState>>();
|
||||
if (options is LayerSelectorMapPluginOptions) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) =>
|
||||
Stack(fit: StackFit.expand, children: <Widget>[
|
||||
Positioned(
|
||||
top: constraints.maxHeight - 60,
|
||||
left: 10.0,
|
||||
child: new CenteredRow(
|
||||
children: <Widget>[
|
||||
new Column(
|
||||
children: <Widget>[LayerSelectorButton(store)],
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
]));
|
||||
}
|
||||
throw ("Unknown options type for LayerSelectorMapPlugin"
|
||||
"plugin: $options");
|
||||
}
|
||||
|
||||
@override
|
||||
bool supportsLayer(LayerOptions options) {
|
||||
return options is LayerSelectorMapPluginOptions;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,12 @@ import 'package:fires_flutter/models/fireNotification.dart';
|
|||
import 'package:meta/meta.dart';
|
||||
|
||||
enum FireMapStatus { view, subscriptionConfirm, unsubscribe, edit, viewFireNotification }
|
||||
enum FireMapLayer { osmcGrey, esriSatellite, osmc, esri, esriTerrain }
|
||||
|
||||
@immutable
|
||||
class FireMapState {
|
||||
final FireMapStatus status;
|
||||
final FireMapLayer layer;
|
||||
final int numFires;
|
||||
final FireNotification fireNotification;
|
||||
final List<dynamic> fires;
|
||||
|
|
@ -16,6 +18,7 @@ class FireMapState {
|
|||
|
||||
const FireMapState.initial()
|
||||
: this.status = FireMapStatus.view,
|
||||
this.layer = FireMapLayer.osmcGrey,
|
||||
this.yourLocation = null,
|
||||
this.fireNotification = null,
|
||||
this.numFires = 0,
|
||||
|
|
@ -25,6 +28,7 @@ class FireMapState {
|
|||
|
||||
FireMapState(
|
||||
{this.status: FireMapStatus.view,
|
||||
this.layer: FireMapLayer.osmcGrey,
|
||||
this.yourLocation,
|
||||
this.numFires,
|
||||
this.fires,
|
||||
|
|
@ -34,6 +38,7 @@ class FireMapState {
|
|||
|
||||
FireMapState copyWith({
|
||||
FireMapStatus status,
|
||||
FireMapLayer layer,
|
||||
YourLocation yourLocation,
|
||||
FireNotification fireNotication,
|
||||
int numFires,
|
||||
|
|
@ -48,6 +53,7 @@ class FireMapState {
|
|||
fires: fires ?? this.fires,
|
||||
falsePos: falsePos ?? this.falsePos,
|
||||
industries: industries ?? this.industries,
|
||||
layer: layer ?? this.layer,
|
||||
status: status ?? this.status);
|
||||
}
|
||||
|
||||
|
|
@ -57,6 +63,7 @@ class FireMapState {
|
|||
other is FireMapState &&
|
||||
runtimeType == other.runtimeType &&
|
||||
status == other.status &&
|
||||
layer == other.layer &&
|
||||
numFires == other.numFires &&
|
||||
fireNotification == other.fireNotification &&
|
||||
fires == other.fires &&
|
||||
|
|
@ -67,6 +74,7 @@ class FireMapState {
|
|||
@override
|
||||
int get hashCode =>
|
||||
status.hashCode ^
|
||||
layer.hashCode ^
|
||||
numFires.hashCode ^
|
||||
fireNotification.hashCode ^
|
||||
fires.hashCode ^
|
||||
|
|
@ -76,7 +84,7 @@ class FireMapState {
|
|||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FireMapState{status: $status, numFires: $numFires, fires: ${fires
|
||||
return 'FireMapState{status: $status, layer: $layer, numFires: $numFires, fires: ${fires
|
||||
.length}, falsePos: ${falsePos.length}, industries: ${industries
|
||||
.length}, yourLocation: $yourLocation, fireNotification: $fireNotification}';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,3 +53,5 @@ class EditCancelYourLocationAction extends FiresMapActions {
|
|||
YourLocation loc;
|
||||
EditCancelYourLocationAction(this.loc);
|
||||
}
|
||||
|
||||
class ToggleMapLayerAction extends FiresMapActions {}
|
||||
|
|
@ -20,6 +20,8 @@ final fireMapReducer = combineReducers<FireMapState>([
|
|||
_editConfirmYourLocationMap),
|
||||
new TypedReducer<FireMapState, EditCancelYourLocationAction>(
|
||||
_editCancelYourLocationMap),
|
||||
new TypedReducer<FireMapState, ToggleMapLayerAction>(
|
||||
_toggleMapLayer),
|
||||
new TypedReducer<FireMapState, UpdateYourLocationMapAction>(
|
||||
_updateYourLocationMap)
|
||||
]);
|
||||
|
|
@ -89,3 +91,13 @@ FireMapState _editCancelYourLocationMap(
|
|||
|
||||
FireMapStatus restoreStatusAfterSave(loc) =>
|
||||
loc.subscribed ? FireMapStatus.unsubscribe : FireMapStatus.view;
|
||||
|
||||
FireMapState _toggleMapLayer(
|
||||
FireMapState state, ToggleMapLayerAction action) {
|
||||
FireMapLayer currentLayer = state.layer;
|
||||
List<FireMapLayer> list = FireMapLayer.values;
|
||||
int currentPos = list.indexOf(currentLayer);
|
||||
currentPos++;
|
||||
FireMapLayer next = list.elementAt(currentPos >= list.length ? 0: currentPos);
|
||||
return state.copyWith(layer: next);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue