...not just because of all the new teams features—but because panning and zooming across the infinite canvas of map tiles has become smoother, snappier, and just more modern. We made these improvements by switching our underlying map rendering engine to MapLibre GL JS (the open-source fork of Mapbox GL JS). MapLibre is a mature, fully-featured renderer that’s part of a rich mapping ecosystem, along with tools we support such as Tippecanoe for tile generation and PMTiles for hosting. We intend to take advantage of more and more of MapLibre’s capabilities over time—but the immediate goal we’ve achieved is to make Felt maps more beautiful during zoom operations.
I joined Felt in Fall of 2022 excited to be part of an incredible team of mapping experts, and especially to work with Isaac Besora on our rendering. With my background working at Mapbox on the Mapbox GL renderer, I am naturally a fan of its underlying technology, and here at Felt I’m looking forward to finding new ways to push the state of the art for web mapping. Here’s my first step on that path.
More immersive maps with MapLibre
You’ve always been able to make beautiful cartographic visualizations in Felt, so why was I so excited to help Felt switch to MapLibre? The modern norm for web mapping is:
- Vector-based—so that maps can have interactive, dynamic styling;
- Rendered on the GPU—so that every frame of an interaction, at every angle and zoom, can look the way the cartographer designed.
Once you’re used to maps that render on every frame, anything less feels kind of, well…old.
We had a lightweight renderer that supported vector-tile inputs and dynamic styling, but it output raster tiles that didn’t support the “every frame” experience we wanted. MapLibre solved this problem.
Crisp across all zoom levels
So what exactly was our problem with raster tiles? The raster format is great for imagery and other types of pixel-based data, but it doesn’t work so well for drawing crisp lines and text. With raster maps, the map is only pixel perfect when you’re exactly at an integer zoom level. At fractional zooms, the browser is applying a raster resize operation that necessarily leaves you with a fuzzy, pixelated look—worse the further you are away from the base zoom. You can try to design interactions to push people towards using integer zooms, but no one wants to be bossed around by their mapping software.
Pay attention to curved edges on points and text in the two pictures below—can you see the difference in pixelation?
More continuity during interactive zoom operations
Felt’s goal is to set the new standard for making and sharing maps that pull users into meaningful interactive experiences. The core of map interactivity is panning and zooming, but with raster maps, zooming necessarily introduces discontinuities whenever items on the map have to resize. Every time there’s a sudden size discontinuity, it breaks the illusion that you’re looking at the world with a magic eye.
Watch the points and the labels in the zoom Felt Beta animation below and you can see them getting discretely rescaled every time an integer zoom level is crossed. Below that, in the Felt 1.0 animation, you can see a MapLibre zoom operation in which points and labels maintain their scale (or continuously interpolate between scales).
No migration headaches with FSL
Changing the underlying renderer for a piece of mapping software sounds like a recipe for migration headaches and backwards compatibility issues. We were spared that outcome thanks to Felt’s purpose built and intuitive styling grammar, Felt Style Language (FSL). Whether you’re using layers from our data library or styling your own data, under the hood all Felt maps are defined in FSL. Having this abstraction on top of our renderer turned out to be very useful when it came time to migrate to MapLibre, because it meant we barely had to touch our application logic, and we didn’t have to modify any existing maps. All we had to do was teach FSL to output to a new target: the MapLibre Style Specification.
The bulk of the migration was just a matter of mapping from FSL properties to MapLibre Style Spec properties. Here’s an example from our Line visualization:
…and then for each type of FSL primitive, we implemented a function that translates it to the equivalent MapLibre expression. For example, if you had an FSL interpolator statement that looked like this:
The FSL parser would turn that into an internal object that could then output the equivalent MapLibre expression:
Take Felt 1.0 for a spin
If you’ve already made maps with Felt, revisit them now and play around with them—I’m pretty sure you’ll notice how much smoother they feel, even though at first glance they’ll look nearly the same. If you have a big, heavy file full of interesting data lying around, try throwing it at the new MapLibre renderer via Upload Anything and let us know how it turns out. I can’t wait to see the beautiful maps that are going to come out of this. Try it now.