flutter_map
flutter_map copied to clipboard
[BUG] Changing CRS Does Not Rebuild Other Children
What is the bug?
hi there
flutter_map: 2.0.0
in my case, i have 2 diffenert crs epsg4490 and epsg3857 , let's say we set it as 4490 in the first time and has a polyline on map. when i press a button to switch crs to 3857, the polyline disappear untill i move the map.
What is the expected behaviour?
the polyline still there when change crs.
How can we reproduce this issue?
FlutterMap(
mapController: _mapController,
options: MapOptions(
crs: _currentMapIndex == 0 ? epsg4490 : const Epsg3857(),
center: LatLng(23.388149672864074, 116.7156679026907),
interactiveFlags:
InteractiveFlag.all & ~InteractiveFlag.rotate,
zoom: 14,
minZoom: 0,
maxZoom: 22),
children: [
..._buildBaseMap(),
PolylineLayerWidget(
options: PolylineLayerOptions(polylines: [
Polyline(strokeWidth: 4, color: Colors.red, points: [
LatLng(23.3884495, 116.7191143),
LatLng(23.3806962, 116.7124767),
LatLng(23.3799523, 116.7246074),
LatLng(23.3716553, 116.7208881),
])
])),
Positioned(
bottom: 20,
left: 20,
child: TextButton(
onPressed: () {
_currentMapIndex = _currentMapIndex == 0 ? 1 : 0;
setState(() {});
},
child: const Text("切换"),
),
)
],
)
Do you have a potential solution?
No response
Can you provide any other information?
No response
Platforms Affected
Android, iOS
Severity
Erroneous: Prevents normal functioning and causes errors in the console
Frequency
Consistently: Always occurs at the same time and location
Requirements
- [X] I agree to follow this project's Code of Conduct
- [X] My Flutter/Dart installation is unaltered, and
flutter doctor
finds no relevant issues - [X] I am using the latest stable version of this package
- [X] I have checked the FAQs section on the documentation website
- [X] I have checked for similar issues which may be duplicates
Hi there, and thanks for your report.
This might be because the PolylineLayerWidget
will not rebuild unless it is needs to, like all other Flutter widgets. To do this, you'll need to change the state of a property inside the widget.
May I suggest using a variable for the strokeWidth
, and when you change the CRS, set the state of that variable to 3, then back to 4.
Let me know what happens!
@JaffaKetchup sorry for being late;
i change the storkwidth when i press the switch button, polyline still not been rebuilded untill i move the map
You could probably just call mapController move with a 0.00001 different value instead of setState or something I would imagine (I feel like we should be able to force a mapController move, whatever, but it does for the moment have a check if it's not moved, not to do anything).
@ibrierley's suggestion will probably work, but I'm not sure that's fixing the underlying issue? If that's good enough for you, then that's great, if not, can you post your code from my suggestion.
@ibrierley yes, i has tried this way at the first time but no luck;
Hmm that is strange. Can you post your code from your attempt at my suggestion please?
@JaffaKetchup here is my code
FlutterMap(
mapController: _mapController,
options: MapOptions(
crs: _currentMapIndex == 0 ? epsg4490 : const Epsg3857(),
center: LatLng(23.388149672864074, 116.7156679026907),
interactiveFlags:
InteractiveFlag.all & ~InteractiveFlag.rotate,
zoom: 14,
minZoom: 0,
maxZoom: 22),
children: [
..._buildBaseMap(),
PolylineLayerWidget(
options: PolylineLayerOptions(polylines: [
Polyline(
strokeWidth: _strokeWidth,
color: Colors.red,
points: [
LatLng(23.3884495, 116.7191143),
LatLng(23.3806962, 116.7124767),
LatLng(23.3799523, 116.7246074),
LatLng(23.3716553, 116.7208881),
])
])),
Positioned(
bottom: 20,
left: 20,
child: TextButton(
onPressed: () {
_currentMapIndex = _currentMapIndex == 0 ? 1 : 0;
_strokeWidth = _currentMapIndex == 0 ? 6.0 : 3.0;
// _mapController.move(
// LatLng(_mapController.center.latitude + 0.001,
// _mapController.center.longitude + 0.001),
// _mapController.zoom);
setState(() {});
},
child: const Text("切换"),
),
)
],
)
Ok I see. Using the IDE tools, can you get your map to a situation where the polylines aren't showing, then manually use the hot reload button. What happens? Can you try this with none of our suggestions, my suggestion, and @ibrierley's suggestion.
@JaffaKetchup the same when press hot reload button
Can you paste a minimal example others can run (i.e _baseBuildMap etc is all missing)
@ibrierley https://github.com/yang6626/flutter_map_crs.git
#1333
using setState should now build all children correctly and may fix this issue as long as you setState the entire map when switching which looks like what you are doing
Hi @MooNag, i had tried 3.0.0-beta.1 and the polyline still not shown when i changing the crs untill i move the map.
Out of interest, what happens if you call setState on the widget flutter_map is in ?
Out of interest, what happens if you call setState on the widget flutter_map is in ?
hi @ibrierley here is the example https://github.com/yang6626/flutter_map_crs.git, could you help to look at it. thanks a lot.
Interesting, and good spot.
I'm a bit baffled on this one. I can see the polyline rebuild paint get called each time (and interestingly paint gets called several tiles, even without any tilelayers, but that may well be normal). But yes, indeed it doesn't display, even with a setState, but a move does make it appear, so can confirm the issue.
Looking at the flutter inspector all looks ok, and interestingly if you remove the tileLayers it doesn't display either. Can't figure if I'm missing something obvious, but it's something we should certainly understand before 3.0
Looks a bit like map.getOffsetFromOrigin(point) gets strange y values before the move...so maybe its something like an old pixelOrigin being used in these circumstances...
I note if I do _pixelOrigin = getNewPixelOrigin(_center);
inside getOffsetFromOrigin
it fixes the issue...however, thats likely just papering over the issue of at what times that should get reset ?
Thinking out loud about this a bit more, I'm wondering if we should have a kind of "reset()" method... eg
Eg a soft reset _pixelBounds = getPixelBounds(zoom); _bounds = _calculateBounds();
Full reset (basically call those things that are in initState()) ?
I have a fix for this issue. I wasn't updating pixel origin in setState of the map. It did get updated with the layout builder through updateSizeAndRotation, which (only gets called when the layout changes? I tested and it does fix the layer when I rotate the device).
I added the update to pixel origin to build of the map and the issue is now fixed. I think a recalculate method might make sense.
Maybe a reset stream, like is available on the TileLayer
would be good, for the sake of consistency?
Um not so much a reset stream, just inside of flutter map have a function with all of the values that need to update when the state of the map changes (setState, move, rotate, etc) and call that function whenever the values need to be updated. This way if new values are added or changed it only needs to happen in one spot.
Ah, sorry, I misunderstood the context. Yeah, this makes sense - reducing spaghetti and duplication is always a good idea!
@ibrierley @MooNag @JaffaKetchup guys, i have try it from @MooNag 's version and it works great. thanks all of you.