Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to switch map layers #629

Closed
S-Man42 opened this issue May 25, 2020 · 15 comments
Closed

How to switch map layers #629

S-Man42 opened this issue May 25, 2020 · 15 comments

Comments

@S-Man42
Copy link

S-Man42 commented May 25, 2020

Hi,

I have two map layers: OSM and MapBox Satellite:

 layers: [
   TileLayerOptions(
        urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        subdomains: ['a', 'b', 'c'],
        tileProvider: CachedNetworkTileProvider()
    ),
    TileLayerOptions(
        urlTemplate: 'https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}@2x.jpg90?access_token={accessToken}',
        additionalOptions: {
          'accessToken': '...'
        },
        tileProvider: CachedNetworkTileProvider()
    )
  ]

Is there a way to add a layer switch to switch between both layers?

As workaround I tried to add a button with setState() in onPressed(). However, althought the build() is called, the underlying map is not changing:


_showSatellite = false;
...
layers: [
  _showSatellite ? TileLayerOptions(/*mapbox*/) : TileLayerOptions(/*osm*/)
]

...

Button(
  onPressed: () {
    setState() {
      _showSatellite = !_showSatellite;
    }
  }
)

Any help is appreciated :) Thanks in advance!

Edit: It seems that the layer changes. When I pan or zoom, the switch layer is shown. So, I need a way to refresh the currently shown tiles anyway...

@Swepilot
Copy link

I had the same requirement/issue yesterday and while I know my solution is not optimal in ANY way, it solved the problem for now:

Add the two TileLayerOptions every time but set Opacity: 0 for the one that you don't want to be displayed and Opacity: 1.for the one you want displayed. And call SetState() of course.

(I'm still looking for a way to "force redraw" the entire map at once and not just moving it.)

@Swepilot
Copy link

Looks like something might be coming soon: #619

@ibrierley
Copy link
Collaborator

Can't you programmatically include just the required map url and do a move() or whatever into your layers list?

Not quite sure I follow why you need both loaded in a layer, and not just the one that's switched to ?

@Swepilot
Copy link

Not quite sure I follow why you need both loaded in a layer, and not just the one that's switched to ?

I'm my case I need the map layers to update instantly (switching between light/dark mode) without user to having move the map to get the tiles from the selected layer. I will try to use move() in the background to see if that provides the required result.

@S-Man42
Copy link
Author

S-Man42 commented May 26, 2020

Phew... there's really no native way to switch map layers without a dirty hack?

The move() will not repaint the current tiles which are cached. Only new tiles come from the switched layer. That seems not to be a good choice:
grafik

However, loading two map layers although only one is displayed seems to be a performance and download data issue. I think, I shouldn't do that.

@dariomadeira
Copy link

The same thing happens to me, I have not found a solution to the problem.

@maRci002
Copy link
Contributor

maRci002 commented May 26, 2020

PR #584 resolves this problem.

You can avoid drop all tiles and reload behavior too see

@S-Man42
Copy link
Author

S-Man42 commented May 26, 2020

Looks great! @johnpryan It would be great to get this merged!

@dariomadeira
Copy link

I could not fix the error
I use:
flutter_map: git: url: git://github.com/johnpryan/flutter_map.git ref: c590ab12edbf5b6fce30b13a42e974c0abadd506
and
overrideTilesWhenUrlChanges: true, tileFadeInDuration: 0, tileFadeInStartWhenOverride: 1.0,
and everything remains the same, Help! Thanks!

@maRci002
Copy link
Contributor

@dariomadeira what happens if you use c590ab12edbf5b6fce30b13a42e974c0abadd506 flutter map but you don't provide any settings like this: overrideTilesWhenUrlChanges: true, tileFadeInDuration: 0, tileFadeInStartWhenOverride: 1.0,. By default overrideTilesWhenUrlChanges is false and the map still reloads the tiles but first it drops all old tiles and loads new ones (not overrides them one by one) if it works then tileFadeInStartWhenOverride: true maybe has some bugs.

@dariomadeira
Copy link

@maRci002 I don't understand how to fix the error, in my pubspec.yaml I have:
flutter_map: git: url: git://github.com/johnpryan/flutter_map.git ref: c590ab12edbf5b6fce30b13a42e974c0abadd506

and my code is:

import 'package:flutter/material.dart';
import 'package:qrreaderapp/src/models/scan_model.dart';
import 'package:flutter_map/flutter_map.dart';
// import 'package:latlong/latlong.dart';

class MapaPage extends StatefulWidget {
  //const MapaPage({Key key}) : super(key: key);

  @override
  _MapaPageState createState() => _MapaPageState();
}

class _MapaPageState extends State<MapaPage> {
  
  final map = MapController();
  String tipoMapa = "streets-v11";

  @override
  Widget build(BuildContext context) {

    final ScanModel scan = ModalRoute.of(context).settings.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text("Coordenadas QR"),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.my_location),
            onPressed: (){
              map.move(scan.getLatLng(), 15);
            },
          ),
        ],
      ),
      body: _crearFlutterMap(scan),
      floatingActionButton: _crearBotonFlotante(context),
    );
  }

  Widget _crearFlutterMap(ScanModel scan) {
    return FlutterMap(
      mapController: map,
      options: MapOptions(
        center: scan.getLatLng(),
        zoom: 15,
      ),
      layers: [
        _crearMapa(),
        _crearMarcadores(scan),
      ],
    );
  }

  _crearMapa() {
    return TileLayerOptions(
      urlTemplate :  "https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}" ,
      additionalOptions: {
        'accessToken': '<MyToken>',
        'id': 'mapbox/$tipoMapa',
      }
    );
  }

  _crearMarcadores(ScanModel scan) {
    return MarkerLayerOptions(
      markers: <Marker> [
        Marker(
          width: 100.0,
          height: 100.0,
          point: scan.getLatLng(),
          builder: (context) => Container(
            child: Icon(Icons.location_on, color: Theme.of(context).primaryColor, size: 70.0),
          )
        ),
      ]
    );
  }

  Widget _crearBotonFlotante(BuildContext context) {
    return FloatingActionButton(
      onPressed:(){
        setState(() {
          if (tipoMapa == "streets-v11") {
            tipoMapa = "outdoors-v11";
          } else if (tipoMapa == "outdoors-v11") {
            tipoMapa = "light-v10";
          } else if (tipoMapa == "light-v10") {
            tipoMapa = "dark-v10";
          } else if (tipoMapa == "dark-v10") {
            tipoMapa = "satellite-v9";
          } else if (tipoMapa == "satellite-v9") {
            tipoMapa = "satellite-streets-v11";
          } else {
            tipoMapa = "streets-v11";
          }
        });
      },
      child: Icon(Icons.repeat),
      backgroundColor: Theme.of(context).primaryColor,
    );
  }
}

the result:

https://imgur.com/zpIm8gP

I am new to Flutter, sorry for my English and thank you very much!

@maRci002
Copy link
Contributor

@dariomadeira I see the problem now. I haven't checked additionalOptions if it's conetent is changed or not, I'll fix it soon.

Till use this as workaround:

      urlTemplate :  "https://api.mapbox.com/styles/v1/mapbox/$tipoMapa/tiles/{z}/{x}/{y}?access_token={accessToken}" ,
      additionalOptions: {
        'accessToken': '<MyToken>',
      }

@dariomadeira
Copy link

@maRci002
Thank you very much for answering!

@Swepilot
Copy link

Swepilot commented Jun 5, 2020

@maRci002 Thanks for implementing this. I'm now using 381afd0 and it works great to have the map refreshed when changing the map with a different urlTemplate. However, I have a MarkerLayerOptions layer as well where I have an option to show/hide this marker layer. When toggling this marker layer the map layer also gets redrawn even though the urlTemplate has not been changed. Is this by design or am I doing something wrong?

If I use 0.9.0 I can toggle the marker layer without the map being reloaded.

@Xennis
Copy link
Contributor

Xennis commented Sep 5, 2020

@dariomadeira I see the problem now. I haven't checked additionalOptions if it's conetent is changed or not, I'll fix it soon.

Till use this as workaround:

      urlTemplate :  "https://api.mapbox.com/styles/v1/mapbox/$tipoMapa/tiles/{z}/{x}/{y}?access_token={accessToken}" ,
      additionalOptions: {
        'accessToken': '<MyToken>',
      }

Dear @maRci002 I've tried to fix that here #740 . Can you take a look into that MR and give feedback if that's correct?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants