Comments (25)
@HusseinCopol You'd use that in your dart code like this:
const _themeData = /* { all of this is your json } */;
final mapTheme = ThemeReader().read(_themeData); // You can also supply logger: Logger.console() to the ThemeReader to spot parsing issues with your theme.
Then in your VectorTileLayerOptions
, you can provide your theme by setting theme: mapTheme
.
ThemeReader
needs import 'package:vector_tile_renderer/vector_tile_renderer.dart';
which is a dependency of this library so it should be available.
from flutter-vector-map-tiles.
@FaFre I couldn't wait - with some profiling I made a few changes inspired by your suggestion greensopinion/dart-vector-tile-renderer@548c0cc
from flutter-vector-map-tiles.
I'm just adding a few bits here, after recent thoughts on the removal of raster discussion...some has already been covered I think, so apologies, just getting it out of my head before it pops out again. Some may have already been done! But writing it down in case someone wants to explore (I don't think I've got quite time to dabble atm, but will if I do).
Generally in Flutter, canvas paths are typically very slow to render with strokewidths sub 1px (especially when zoomed) as it uses a different algorithm for linecaps etc. Sometimes there may be a path say at 1.2px...when pinchzooming, could anything between 1-2px be rendered at 0.99px for example (I experimented a bit with this in the renderer, and maybe it helped a little, in some cases, but not sure how the renderer would know if pinchzooming, or if thats better done outside the rendering code and figured before any calls to it)
Generally calls to drawPath should be minimised. Can paths with the same style be grouped into one superpath (with a Move inbetween them), cache that path and draw (may be fiddly if using expressions that change per zoom, but could be done in inbeween zoom level changes). This may be similar to the addPolygon idea, but we can also group multiple lines as well.
TextLayouts are typically expensive, so can that be cached (I know thats been discussed a bit before, not sure where that is currently), I was thinking about a simple storage of a previous frame type cache even. If a labels textlayout (based on latlng point and name for example) was stored in a hash of previous display frame/update, it should be able to be reused (I think!).
I played with the idea of "overZooming" (I think there's another term for it, but it eludes me). So let's say we are at zoom 14. We draw the tiles at zoom 13, which means you only need a quarter of the tiles (some loss of lines maybe, but for tiles that have too much data it can help a bit). (Does this also play into the mapbox tilesize of 512 vs 256, not sure ?)
Instead of drawPath, during a pinchzoom, can Canvas drawPoints with a PointMode of lines/polygon be used ? It may not need to calculate linecaps etc do maybe faster (similar to earlier...if a strokeWidth is < 4 say, do we care about accuracy of joins ? Now, I did try this a year or two ago, and the odd time got an out of mem error, but I think this was referencing GPU memory for point storage, and it may well be all of that is fixed now.
If pinchzooming, could rendering be interrupted if a new zoom level comes in (bit fiddly this one...one may end up with blank tiles, not sure I like this...) ?
Out of interest, is there a way for the rendering code to know that a pinchzoom is taking place ? I couldn't quite tell from the code if that's possible or not...
from flutter-vector-map-tiles.
Hi, thanks for the kudos!
Performance is a real problem when it comes to vector tiles. So great to hear that you're interested in contributing.
There are a few things that you can do to tune the codebase as-is:
- Check that you're using
RenderMode.mixed
, which uses raster tiles (rendered from vector data) while zooming, and then renders again with vector tiles when zooming is finished. - Check your tile data to verify that it doesn't include unnecessary information that would render outside of the tile bounds.
- Tune your map theme to avoid rendering unnecessary polygons/lines
- Check your memory usage - if the app is freezing, it's possible that you are using too much memory and hitting the upper limits.
I've done the above and come up with a decent frame rate while zooming/panning. There is some jitter (i.e. skipped frames) especially in dense regions (e.g. London, UK) however the user experience is still pretty good.
At one point I did experience freezing as you mentioned. I made some changes to the codebase to avoid rendering outside of the tile area for labels on the Canvas, and that made a huge difference. There's potentially more that could be done here (e.g. with polygons/lines) I wonder if your tiles contain shapes outside of the tile rendering area? That could be a good place to start with a contribution.
The Flutter memory view is really helpful to see if you're hitting an upper memory limit.
from flutter-vector-map-tiles.
Thanks for your fast reply, I will experiment and try to get into the code more. With Memory view didn't see immediate problems - so I started debugging it with the performance view (see below). I will write updates in this issue if I manage to get some improvements.
from flutter-vector-map-tiles.
I've done some more work in this area since I was noticing jank on iPad.
It's still not perfect, but these two commits make a big difference:
Also, I've found that tuning the map style to reduce detail at different zoom levels can help. For example, the style that I'm using has minzoom=14 for road_minor, and minzoom=15 for road_minor_casing. By having casing for minor roads only render at zoom level 15 and above, there's half as much work to do at zoom level < 15.
from flutter-vector-map-tiles.
Cool, I will try it out. I should get to experiment with it more during the upcoming week
from flutter-vector-map-tiles.
from flutter-vector-map-tiles.
I've done some more work in this area since I was noticing jank on iPad.
It's still not perfect, but these two commits make a big difference:
Also, I've found that tuning the map style to reduce detail at different zoom levels can help. For example, the style that I'm using has minzoom=14 for road_minor, and minzoom=15 for road_minor_casing. By having casing for minor roads only render at zoom level 15 and above, there's half as much work to do at zoom level < 15.
Hi.
I have performance issues too , how do i tune my map style to reduce details?
thanks
from flutter-vector-map-tiles.
how do i tune my map style to reduce details?
to do that you'll need to edit the map style, which you could do with a text editor but it's easier with something like https://maputnik.github.io
The fewer things showing on a map, the less computationally expensive it is (i.e. the faster it will render.) There are a few ways to achieve fewer things while still having beautiful maps:
-
Consider rendering finer details only at higher zoom levels. For example, if your style shows buildings, consider having them show up only when the map is zoomed level 14, 15 or higher. That can be achieved with the
minzoom
property. The same applies for things like trails, alleys, and minor roads. -
Consider reducing the level of detail of roads by eliminating borders at lower zoom levels. Most styles that I've seen render roads twice at different widths to give the effect of a border. By eliminating road borders, there's less work in rendering those tiles.
I hope that helps. If it's still not enough, you could use raster rendering which will provide the styling advantages of vector tiles, but without the crisp edges.
from flutter-vector-map-tiles.
how do i tune my map style to reduce details?
to do that you'll need to edit the map style, which you could do with a text editor but it's easier with something like https://maputnik.github.io
The fewer things showing on a map, the less computationally expensive it is (i.e. the faster it will render.) There are a few ways to achieve fewer things while still having beautiful maps:
1. Consider rendering finer details only at higher zoom levels. For example, if your style shows buildings, consider having them show up only when the map is zoomed level 14, 15 or higher. That can be achieved with the `minzoom` property. The same applies for things like trails, alleys, and minor roads. 2. Consider reducing the level of detail of roads by eliminating borders at lower zoom levels. Most styles that I've seen render roads twice at different widths to give the effect of a border. By eliminating road borders, there's less work in rendering those tiles.
I hope that helps. If it's still not enough, you could use raster rendering which will provide the styling advantages of vector tiles, but without the crisp edges.
thanks.i have one more question! maputnik gave me a JSON file and where do i use it? the map controller didn't have any styling property (like google map controller ) .
from flutter-vector-map-tiles.
I've found that most of the time spent rendering is looping over the theme layers so to increase performance, you can start by throwing out all layers from your theme, that you won't need. For example I built an app with a map scoped in Germany but the default theme from Mapbox includes a theme layer for US highway symbols. After trimming down the layers from a few hundred to just over a dozen which suffice in my case, performance went from 5 FPS went around 50 when zooming, moving and rotating.
Of course if you have layers that should only show at specific zoom levels, using the minzoom/maxzoom properties works as well.
from flutter-vector-map-tiles.
I read the rendering code today, it was really a pleasure. Great work @greensopinion !
I was also doing some canvas painting, but on top of the standard flutter_map tile layer. In my case I had a big performance improvement when actually adding lines via addPolygon()
to the Path
. It's a lot faster compared to lineTo()
when having larger linestrings. However, I tried it out and couldn't feel a notably difference when applying to this project. Maybe it's a little bit faster, but I haven't done any benchmarking. I think because the tiled linestrings are already very small, so most CPU time is taken by the painting overhead.
When interested, take a look here: FaFre/dart-vector-tile-renderer@f43fffe
But I think having 1-4 long running isolates and distribute the tile rendering jobs to them will bring a huge performance improvement. Downside, isolates are not supported for web.
from flutter-vector-map-tiles.
I read the rendering code today, it was really a pleasure. Great work @greensopinion !
Thanks @FaFre, great to hear.
I was also doing some canvas painting, but on top of the standard flutter_map tile layer. In my case I had a big performance improvement when actually adding lines via
addPolygon()
to thePath
. It's a lot faster compared tolineTo()
when having larger linestrings. However, I tried it out and couldn't feel a notably difference when applying to this project. Maybe it's a little bit faster, but I haven't done any benchmarking. I think because the tiled linestrings are already very small, so most CPU time is taken by the painting overhead.When interested, take a look here: FaFre/dart-vector-tile-renderer@f43fffe
Feel free to issue a pull request - this is worth adding regardless of performance since it simplifies the code.
But I think having 1-4 long running isolates and distribute the tile rendering jobs to them will bring a huge performance improvement. Downside, isolates are not supported for web.
What do you have in mind for rendering jobs? From what I understand, calls to Canvas can only be done on the UI thread.
from flutter-vector-map-tiles.
regarding canvas on UI thread, there is a Flutter issue for this FYI
flutter/flutter#75755
from flutter-vector-map-tiles.
Ohh too bad. I thought through the rasterization it could be also done in an isolate, but it seems like that it's not even possible to instantiate a Canvas
inside an isolate. However, with the new release they put a lot of focus on isolates. Hopefully it will be possible soon.
from flutter-vector-map-tiles.
I've had a run at some performance related changes. There's more work to do, but there are some noticeable improvements in the latest release.
- eliminated unnecessary re-rendering of tiles while panning
- reduced CPU overhead of text labels
- reduced memory overhead
- improved cache hit rate
from flutter-vector-map-tiles.
The latest release has more performance improvements.
Some performance issues remain, clearly showing up as jank with the default theme.
Current recommendations:
- Tune your theme:
- reduce unnecessary map elements (such as buildings, minor roads, labels) at lower zoom levels using
minzoom
- avoid rendering unnecessary polygons/lines
- reduce unnecessary map elements (such as buildings, minor roads, labels) at lower zoom levels using
- Check that you're using
RenderMode.mixed
, which uses raster tiles (rendered from vector data) while zooming, and then renders again with vector tiles when zooming is finished. - Check your tile data to verify that it doesn't include unnecessary information that would render outside of the tile bounds.
- Check your memory usage and avoid large cache sizes - if the app is freezing, it's possible that you are using too much memory and hitting the upper limits.
from flutter-vector-map-tiles.
Closing based on recent optimizations including issues #21. Feel free to open a new issue if there continues to be a problem.
from flutter-vector-map-tiles.
A lot of work has been done to improve performance. There is still room for more improvement, however in testing I've found that RenderMode.mixed
is no longer needed for my use-case. See #21 for related discussion.
from flutter-vector-map-tiles.
from flutter-vector-map-tiles.
Thinking out loud, I may be barking up the wrong street, so this may not apply! I was thinking about why I didn't really get any major text performance issues later on when experimenting with vector tiles.
When I was doing Vector stuff, in the end, I ended up not using Positioned Widgets (maybe a hybrid is interesting..can't remember if I tried this). I suspect what may be happening is that every zoom change, all the text layouts need to be recalculated, and then readjusted inversely according to the scale (and text layout is very expensive iirc).
However, in reality, we don't need to do any of this at all (unless we are either literally resizing the text to fit in with a road width for example, or curving text along a road). At all times, typically we want the text to be the same size (visually to the human eye). So we don't need to recalculate any of this, one can just reuse the old layout and draw on one none transformed Canvas.
For example...all on one single upper Canvas
///pos = tile position..
matrix = Matrix4.identity();
matrix..translate(pos.point.x.toDouble(), pos.point.y.toDouble())
..scale(pos.scale);
...
for (Label label in labels) {
label.transformedPoint =
MatrixUtils.transformPoint(matrix, label.point);
// collision detection, maybe every x frames
//canvas.save(); // only if map rotated
canvas.translate(
transformedPoint.dx, transformedPoint.dy);
//canvas.rotate(-widgetRotation * 0.0174533); // only if map rotated
//canvas.restore(); // only if map rotated
Apologies again, if this is a redherring.
from flutter-vector-map-tiles.
Where is this RenderMode being set? could not find it anywhere with latest version of the package
from flutter-vector-map-tiles.
Where is this RenderMode being set? could not find it anywhere with latest version of the package
RenderMode was removed, see discussion on #31 and implementation on #52
from flutter-vector-map-tiles.
@HusseinCopol You'd use that in your dart code like this:
const _themeData = /* { all of this is your json } */; final mapTheme = ThemeReader().read(_themeData); // You can also supply logger: Logger.console() to the ThemeReader to spot parsing issues with your theme.Then in your
VectorTileLayerOptions
, you can provide your theme by settingtheme: mapTheme
.
ThemeReader
needsimport 'package:vector_tile_renderer/vector_tile_renderer.dart';
which is a dependency of this library so it should be available.
With this implementation you have to make sure that chosen theme and map providers are same. In my case I have been using Stadia map provider and picked a theme from GeoApify. I started facing problems because of incompatibilities. Then I switched to GeoApify map provider with the following link inside _urlTemplate()
https://maps.geoapify.com/v1/tile/klokantech-basic/{z}/{x}/{y}.pbf?apiKey=YOUR_API_KEY
I have picked theme style from here
https://maps.geoapify.com/v1/styles/klokantech-basic/style.json?apiKey=YOUR_API_KEY
This has completed my implementation ... rest anyone can pick a theme from the plugin's gallery and can add to application by making sure both providers and theme are from same source.
Also one more important thing here is source for me, which says default
and inside this plugin's example app we have openmaptiles
, Question is why I am using 'default' source? Because this source is mentioned inside style json file we pick. I have attached few screenshots below.
from flutter-vector-map-tiles.
Related Issues (20)
- Not accepting map styles from other sources HOT 1
- Differences in Styles for Mapbox.
- Update flutter_map dependency to 6.1.x HOT 4
- Web support HOT 1
- Question about working with tile server.
- [StyleReader] Converting JSON into a Style HOT 4
- DEpendency problems when upgrading to 6.0.2 HOT 2
- display with rotation is not the same between vector and raster modes in version 7.0.0 HOT 3
- is expressmaps supported? HOT 1
- Package available for web? HOT 2
- Raster Tiles Usage HOT 1
- would something like https://github.com/fleaflet/flutter_map_cancellable_tile_provider help in performance HOT 1
- very low performance HOT 1
- Override background color of VectorTileLayer HOT 1
- Google maps support - Issue HOT 3
- Can't display pg_tileserv and postgis tiles HOT 1
- How to rotate and zoom the map like a native map experience
- Raster mode tile cancellation HOT 1
- new version available
- providers.isNotEmpty error
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flutter-vector-map-tiles.