Upgrading to Leaflet 1.0 Beta 2

This post is just a migration log. I’m very excited to be learning about Leaflet Hotline, but it requires Leaflet 1.0 Beta 2. The problem is that several of the other plugins that I use on http://exploringspatial.com are not compatibleLeaflet 1.0. Here is the run down of what I ran into.

Why are there problems?

I will try to keep this post up-to-date with issues as I find them:

  • Multpolygon class is gone – The Mulitpolygon class is being replaced by enhancements to the Polygon class (see thread). If your plugin used Multipolygon, then you’ll need a new version of the plugin for Leaflet 1.0.
  • GeoJSONLayer.resetStyle(layer) is gone. I switched to layer.setStyle().
  • L.FeatureGroup.EVENTS no longer exists.
  • “Event.layer” is now called “Event.target” in mouse events.

Bing, Google and  Yandex Plugins

Pavel Shramov and Bruno Bergot provide Leaflet plugins for Bing, Google, and Yandex maps. When you switch to Leaflet 1.0 the Google Tiles layer will break (I’ve just dumped Bing for the time being since it has not been addressed). When you add a Google layer it to your Leaflet 1.0 map you will see an error in Leaflet-src.js  at line 2382 because callback is undefined.

    whenReady: function (callback, context) {
        if (this._loaded) {
            callback.call(context || this, {target: this});
        } else {
            this.on('load', callback, context);
        }
        return this;
    },

Fortunately, Bruno Bergot is already on top of this and you can pull his patch down for the time being: https://github.com/shramov/leaflet-plugins/pull/175.

Leaflet Point-in-Polygon

Leaflet-pip depends on the Mutlipolygon class, so it broke http://exploringspatial.com/#demo/8 at line 15: “Uncaught TypeError: Expecting a function in instanceof check, but got undefined.” Specifically, it breaks at this line of code: “if ((l instanceof L.MultiPolygon…”

var leafletPip = {
    bassackwards: false,
    pointInLayer: function(p, layer, first) {
        'use strict';
        if (p instanceof L.LatLng) p = [p.lng, p.lat];
        else if (leafletPip.bassackwards) p = p.concat().reverse();

        var results = [];

        layer.eachLayer(function(l) {
            if (first && results.length) return;
            if ((l instanceof L.MultiPolygon ||
                 l instanceof L.Polygon) &&
                gju.pointInPolygon({
                    type: 'Point',
                    coordinates: p
                }, l.toGeoJSON().geometry)) {
                results.push(l);
            }
        });
        return results;
    }
};

There is not a patch yet, but I found the solution contained in this thread: https://github.com/mapbox/leaflet-pip/issues/8.  There is a post from user “nikolauskrismer” that replaces the entire code block starting at line 6: “var leafletPip = …” That got me past the error above.

Leaflet MarkerCluster

In http://exploringspatial.com/#demo/5 I used Leaflet.MarkerCluster, but in http://exploringspatial.com/#demo/6 I switched to Leaflet.PruneCluster for performance reasons. Upgrading to Leaflet 1.0 Beta 2 broke Demo 5. Leaflet.MarkerCluster caused the error “Uncaught TypeError: Cannot read property ‘trim’ of undefined” in leaflet-src.js at line 137. The cause was line 51 from leaflet.markercluster-src.js, “this._featureGroup.on( L.FeatureGroup.EVENTS, this._propagateEvent, this).” The problem is that L.FeatureGroup.EVENTS no longer exists in Leaflet 1.0. Since I was already using PruneCluster successfully with Leaflet 1.0 beta 2, and I didn’t see any patches, I dumped Leaflet.MarkerCluster and switched to Demo 5 to Leaflet.PruneCluster.

Mouse Events

Another issue that I ran into on http://exploringspatial.com/#demo/7 was that my mouseover and mouseout events were expecting “event.layer“, but with Leaflet 1.0 that has changed to “event.target” That was easy for me to switch. I was just calling event.target.style to highlight polygons on mouseover.

Reset Style

The final issue I hit was on http://exploringspatial.com/#demo/8. In my states map view I called GeoJSONLayer.resetStyle(layer) on all the state polygons each time a new race distance was selected. That no longer worked in Leaflet 1.0. I had to switch to layer.setStyle() to get around that.

That is all that I’ve found so far. All my changes are now live at http://exploringspatial.com. Let me know if you spot any problems that I missed.

 

Advertisements

Color Gradient Lines: Speed Bump

I was all set to start using Leaflet Hotline when I hit a speed bump. It does not appear to work with Leaflet 0.7.7. Unfortunately, some other plugins on my site do not work with Leaflet 1.0 Beta 2.

This is where having a demo “site” with an MVC framework, as opposed to simple standalone demo pages or in JSFiddle with straight HTML/javascript, becomes a problem. I’ve brought Leaflet and all of my plugins up to the latest versions, but I cannot run Leaflet 1.0 Beta 2 without causing problems for Leaflet PruneCluster and my Google/Bing plugins.

I’ll have to either, a) figure out whether RequireJS will allow me to essential overwrite “L” with a different version of Leaflet for Demo 10, or b) build a standalone page for Demo 10.

Grrrr!

Color Gradient Lines: Begin with the End in Mind

I’ve been looking into what it would take to draw map lines with color gradients, like the red/blue line to the left. My assumption was that this would require generating raster map tiles (something I know little about), but this week Tom MacWrite pointed out the demo that he wrote for MapBox. That, in turn, led me to look for Leaflet plugins that support gradient colors.

The first one I found is Leaflet.MultiOptionsPolyline.  The screen shot below is from its demo page. It looks interesting, but it’s not quite the smooth gradient effect I was after.

A more promising Leaflet plugin I found is Leaflet.hotline, by iosSphere of Cologne, Germany. Below is a screen shot from its demo page — much closer to the effect that I was looking for. Leaflet Hotline was inspired by the Leaflet.heat plugin. That makes sense to me now since heat maps also have smooth color gradients.

Clearly, a polyline drawn with a color gradient is possible with Leaflet, so now let’s step back and begin with the end in mind.

Objective

My objective is to convey information, like heart rate or pace, on top of the race path recorded by a GPS device. I’ll use pace for my demo. The map should show the runner where her pace was faster, and where it was slower.

The race path on the map should support interaction with other components on the page. For instance, it may not be enough to see speed alone. It would be nice to hover over the line on the map and see the corresponding point on an elevation chart. A slowdown may be the result of a steep incline.

Colors

The gradient colors need to convey additional information about the runner’s race without being distracting. The colors should not make the map harder to read, for example, blending into the background.  The Leaflet Hotline example used black outlines to solve that problem. Also, the colors should take color blindness into consideration.

Below is an example of line colors Google chose for the Bart Transit map. How do those work for red/green, or blue/yellow color blindness? Perhaps those shades are okay?

Awhile back I found an article, How The Rainbow Color Map Misleads, that explains why not to use rainbow colors. For more information see Rainbow Color Map (Still) Considered Harmful (Full discloser, I didn’t pay to download this report). There is a handy tool to help find alternative colors for your map called ColorBrewer. Another tool for picking gradient colors generally is uiGradients.

I stumbled upon this set of color-blind safe colors on Paul Tol’s website. The shades of blue and green from Paul Tol’s site are somewhat similar to the colors from Google’s Bart transit map above. I’ll try to incorporate some of these colors into my soon-to-come demo.

colourpalette_small

Color-blind Safe Palette from Paul Tol

Stay tuned for a demo at http://exploringspatial.com.

Relaunching Exploring Spatial as a Single Page Web Site.

After a bit of a break from my blog, I have returned. There is a lot on the plate for work in 2015, and I need to get out ahead of that development. 2015 will be the year that we begin to introduce Leaflet to our maps, so it’s time that I returned to my exploration of Leaflet and its plugins.

Begin Again

Over the last couple of weeks, I did several things to improve Exploring Spatial. I converted the site to a single page web application, I reworked that HTML/CSS on my site to utilize more real-estate, and I made everything available on GitHub.

Bigger is Better

The CSS template I was using had a fixed height and width. I’ve expanded it to be a full page to allow for bigger maps. There are some wrapping issues that must be fixed, but overall the result was what I wanted. One of my TODO tasks is to add some JavaScript to size the height and width of the map container DIV tags from the document viewport. Some map providers don’t work well with percentage sizes, so I want to plug in the height and width in pixels and redraw the map when the browser window is resized.

“GIT”ting Better

The entire site is now available at GitHub: https://github.com/smitchell/exploringspatial. Not only can you find all the demo code there, but theoretically you can contribute your own code to the demos too.

One Page Fits All

My biggest change was to convert the entire website to be a single page app using Backbone.js. I did this for no other reason than this is the direction we are heading at work. At first, I resisted making this change because it makes the demos a little harder to follow if you are not familiar with Backbone.js.

Eventually, I decided that my website is as much a personal journal as it is a public resource, and the kind of people that might be interested in my journal are professionals who can find their way around the Backbone JavaScript files.

Enjoy the new site. You can expect a lot of activity on the Leaflet demos in 2015.

Learning Leaflet

leaflet

This week I launched http://www.exploringspatial.com to host companion labs for this blog. My first lab is for Leaflet, a JavaScript library for maps. I’m looking for two things from this framework:

  1. The ability for users to pick Google, OSM, or Bing as the base map later.
  2. A vector graphics layer (points and polylines) that is separate from the base map.

This week’s lab, http://www.exploringspatial.com/#demo/1, combines Leaflet’s quick start tutorial with a layer example posted by @james_croft.  James used a TileLayer for Google that he found at http://psha.org.ru/leaflet/Google.js (there are a lot of Leaflet goodies at  http://psha.org.ru/leaflet. I’m working on figuring out who posted them).

In my lab the shapes and click events work fine on the Cloudmade and OSM layers, but not on the Google layer. That is a deal breaker for me, so my next task is to understand why they don’t work with the Google plugin and resolve the problem.