Maps Zen — Visualize
Thursday, September 10, 2015
Editor's Note: Gone are the days when users were impressed with a marker on a map. The Maps Zen blog post series covers integrations of Google Maps APIs to help your apps provide great maps user experiences. What’s a zen pattern? Simply put, a design pattern that results in harmonious user experiences.
Markers are much more useful than identifying points on a map. Markers can also be used as a way to visually convey information about a place. If a user is searching for a well rated restaurant, they’d fire up your app to find that there’s a bunch of restaurants in their vicinity. But it’s not easy to tell which ones are actually worth visiting. To see the ratings for each place, they’d end up having to tap each one first.
Here’s an how marker selection and marker animations can be a great way to show this information. In this example, markers that lack colour rate poorly and the vibrant colorful markers are the highly rated ones. There’s also animated steam on some markers also helping to highlight the best rated restaurants!
To achieve the steam animation, the marker icon is being changed by calling the setIcon() method periodically. A delay of 32ms roughly corresponds to 30 marker icon updates a second — animating the icon at 30 frames per second.
mAnimHandler.post(new Runnable() {
@Override
public void run() {
marker.setIcon(mSteamFrames.nextFrame());
// Next frame in 32 ms
mAnimHandler.postDelayed(this, 32);
}
});
To desaturate the marker icons, a ColorMatrixColorFilter from the Android framework being used. First, setup the color filter based on the restaurant rating scale via a ColorMatrix. In this case, any restaurant that has a 3 star rating will be presented as having an entirely grayscale icon. Restaurants with a 4.5 star or higher rating will be presented in full color. The restaurant scale is set it to a Paint object and the filter is applied to the marker image using a canvas.
ColorMatrix desatMatrix = new ColorMatrix();
desatMatrix.setSaturation(restaurantRating);
ColorFilter paintColorFilter = new
ColorMatrixColorFilter(desatMatrix);
Paint paint = new Paint();
paint.setColorFilter(paintColorFilter);
Canvas canvas = new Canvas(newImage);
canvas.drawBitmap(oldImage, 0, 0, paint);
Markers are great for showing points on a map but sometimes you can end up with too many. In this case, we have too well rated many restaurants around us - sure, it’s a nice problem to have but it’s not helping the user choose a restaurant. In such situations, you need to display many markers but still keep the view comprehensible. We’re going to look at two ways to overcome these issues.
The first is through the use of marker clustering. As the zoom levels of the map change, markers are aggregated making for a much more digestible view. Now as the map zooms out, markers will combine, showing how many restaurants are in the surrounding areas.
This visual effect may seem like a lot of work, but it is not. The Android Maps Util library provides a four-step implementation of marker clustering:
1. Add the library to your gradle config.
compile 'com.google.maps.android:android-maps-utils:0.3+'
2. Implement ClusterItem interface in your main data class.
public interface ClusterItem {
LatLng getPosition();
}
3. Instantiate the cluster manager and register it for a couple of map listeners.
mClusterManager = new ClusterManager<>(this, mMap);
mMap.setOnCameraChangeListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);
4. Replace your marker management code with calls to the cluster manager - the cluster manager will manage adding and removing the markers for you.
mClusterManager.addItem(clusterItem);
5. You can optionally customise the effect further by providing custom aggregate markers (showing images instead of a count for example).
Let’s look at the second method to show marker aggregation - it looks really cool! Here, the count of markers are replaced with a heat map showing the concentration of these markers.
Achieving this effect is also just four simple steps using the Android Maps Utils library, thanks to its heatmaps.
1. Add the library to your gradle config.
compile 'com.google.maps.android:android-maps-utils:0.3+'
2. Instantiate a HeatMapTileProvider and pass it your LatLngs.
mHeatmapTileProvider = new HeatmapTileProvider.Builder()
.data(mLatLngCollection)
.build();
3. Use it to create a map overlay.
mTileOverlay = mMap.addTileOverlay(
new TileOverlayOptions().tileProvider(mHeatmapTileProvider));
4. You can optionally customize this further by specifying the gradient and the radius of the heatmap.
It’s worth keeping in mind that information overload is a common problem with mobile apps. Location apps, in particular suffer from poor user experiences when dealing lots of places. The Android Maps Utils library offers beautiful visualizations enabling you to build amazing maps.