OpenLayers

OpenLayers: failure of map redraw on panning

Just a quick heads up for those of you using OpenLayers. There seem to have been a lot of problems lately with OpenLayers refusing to redraw its layers when panning, where everything was working before. One possible solution turned up in this thread on OpenLayers Users. The credit for solving the problem is therefore not mine, but I found it so useful that I had to share.

Short version: check that you’re not using OpenLayers.Control.MouseDefaults – it has been deprecated. Instead, use OpenLayers.Control.Navigation – everything else stays the same.

Quick fix for a silly problem that kept me occupied for far too long.

Norwegian Trekking with QGIS Server

I have blogged about the awesomeness that is QGIS Server before. Maybe you have seen some of the nice maps that Andreas Neumann has made in Uster, Switzerland. Over the past 3 months we were contracted to help prototyping a new mapping service for the Norwegian Trekking Association. We really got a chance to put QGIS Server (and the new QGIS Web Client project) through its paces. Why not take a little look for yourself. We had quite a lot of fun optimising the client’s data set for good performance and generally making sure everything works smoothly.

Note:

- the site is still a test site, but the fine folks from Norway gave me the OK to let people take it for a whirl.
- we have not yet implemented search support.
- We made a bunch of different print layouts for you to try out!

It’s now incredibly easy to get your QGIS cartography online. In the near future I plan to test out techniques for tilecaching with QGIS Server and once that works it will be the end of the line for my 11+ year love affair with UMN Mapserver for the most part I think.

Get your map on! QGIS Server in action (click for full image)

Get your map on! QGIS Server in action (click for full image)

 

 

 

Live vehicle tracking with OpenLayers

The last three or four weeks we have been preparing the Tracks4Africa site for the next season of ‘Voetspore‘ (translated from Afrikaans: ‘foot steps’) – a South African TV program which follows the adventures of a group of 4×4 drivers as they traverse africa. For this season, one of the vehicles has been fitted with two tracking devices – a satellite transponder and a GSM unit. By wiring up a couple of Django views to deliver GeoJSON, and consuming that from OpenLayers we are able to deliver real time data on the vehicle positions during their excursion. The data is degraded to show one vertex per hour, although the complete dataset is much more detailed.

 

The trip just started this weekend from  Cape Agulhas, the Southern Tip of Africa (and coincidentally not far from where I live) to Alexandria in Egypt (which is coincidentally extremely far from where I live). You can track their progress by visiting the dedicated Tracks4Africa Voetspore page created for this purpose.

Voetspore map on Tracks4Africa (click for large view)

Voetspore map on Tracks4Africa (click for large view)

FossGIS Web Mappers Toolbox

I thought I would take a moment to run through the tools in my digital toolbox that I use to develop GIS enabled web sites. I try to pick the best of breed in each area rather than learn multiple tools that do the same thing – life is short and there isn’t enough time for me to do that.  I would be interested to read in the comments if anyone has suggestions of better alternatives:

Operating system: Debian or Ubuntu Server Edition. Really don’t run your web site on Windows, its just a silly waste of time and money.

Web server – Apache 2. It’s a no brainer really, its fast, robust and infinitely configurable while easy to get running in a default configuration.

Programmers editor: Vim (or emacs if you prefer). Being able to use the same editor on both local development machines and remote servers is indispesible. Also if you hand write your html it tends to have less gumpf clogging up the works compared to the Frontpage etc. generated sites I have seen out there. If you must use a GUI editor there are a few good choices under Linux, but VIM does it for me.

Web Application framework: (Geo)Django. With its support for spatial extensions,  intuitive MVC architecture and wealth of 3rd party add-ons, Django is a great choice for building your web applications with Python.

Backend Database: PostgreSQL/PostGIS. It does everything you need including store geospatial data.  Some people suggest SpatialLite as an alternative, but thus far I have haven’t used it in a production system so I don’t know what limitations, if any, it has.

Javascript Framework: Jquery. I know there are some good competitors but JQuery and JQuery-UI are so great I haven’t felt a need to go and discover their competitors. There are a huge number of add ons for JQuery and plenty of helpful people out there if you get stuck.

CSS Framework: Blueprint CSS. I think CSS frameworks are still a relatively new concept. They take a lot of the pain out of layout and make your site look good with minimal effort. Blueprint implements the 960 grid and the results are pretty much always pleasing on the eye.

CSS Compressor: http://www.csscompressor.com/. This web site will take your CSS and squish it by removing comments, white space etc. It typically makes my  CSS files around 25% smaller.

Javascript Compressor: Google Closure. This web service / web app will squash your javascript down nice and small using a variety of techniques.  With simple optimisations, I typically get around 40% reduction in code size. It also optimises your code for good measure.  They provide lots of detailed documentation to get you on your way.

Web Mapping Control: OpenLayers. It’s a bit of a no-brainer. I haven’t really looked that hard but is there anything that really competes with it (other than the Google Maps API)?

Web Mapping Server: UMN Mapserver. One day soon I am going to replace this entry with QGIS’ own mapserver implementation by Marco Hugentobler, but for now Mapserver is the best thing since sliced bread – it’s  a doddle to install, incredible flexible and you can generate basic mapfiles using QGIS so it’s easy to get started with. Also worth a mention is Mapnik which can produce gorgeous maps.

Web Mapping Cache: TileCache. I keep meaning to try out MapProxy since it supports region delimitation using shapefiles rather than bounding boxes – which can drastically reduce the size of your seeded cache. But for now, TileCache is really easy to set up and you should have it running in just a few minutes.

Did I leave anything out? If you take the above tools, software and web services, you will have everything you need to produce some great web mapping software.

Vector layer styles, 24bit pngs and theming in OpenLayers

I wanted to take a moment to mention three handy little tips for OpenLayers. First lets look at a typical map OpenLayers project:

A typical OpenLayers project

A typical OpenLayers project

Tip #1: If you want OL to pull down 24bit png images instead of the default 8 bit dithered images, you can append  ‘;mode=24bit’ to the format option for a WMS layer e.g.

var imagery = new OpenLayers.Layer.WMS(
 "my_layer",
 "http://localhost/cgi-bin/mapserv?map=/home/web/mapserver-tut/mapfiles/world.map",
 {layers: "Country,Cities", format: "image/png; mode=24bit"});

Of course there is a trade off of image size for image quality, but the 24bit pngs I use in my map look clean, anti-aliased and without artifacts.

Tip #2: Bored of the default OpenLayers widgets theme? Run, don’t walk to the mapbox OpenLayers theme page and get your OpenLayers map controls looking gorgeous!

Tip #3: None of the examples on the OpenLayers website show how to do a simple thing: set the colour and style for all features in an OpenLayers vector layer. They all focus on creating class breaks and doing more advanced things and don’t mention how to get the basics done. Here is how you make all the features in a given layer have the same appearance:

var myLayerStyle = OpenLayers.Util.extend({},
 OpenLayers.Feature.Vector.style['default']);
 myLayerStyle.fillOpacity = 0;
 myLayerStyle.graphicOpacity = 1;
 myLayerStyle.strokeColor="red";
 myLayerStyle.strokeWidth=1;
 stylemap1 = new OpenLayers.StyleMap(myLayerStyle);
 var format = new OpenLayers.Format.GeoJSON();
 var layer = new OpenLayers.Layer.Vector("Areas", {styleMap : stylemap1});
 var feature = format.read({"type":"Polygon",
 "coordinates":[[[21,-31],[23,-29],[24, -31], [22,-32],[21,-31]]]})[0];
 layer.addFeatures(feature);
 map.addLayer(layer);

In the above example I clone the standard style for a new vector layer (you know, that good old orange!) and then override some of its properties to make it a red stroked non-opague stule.  The layer style is then included in a StyleMap with only one element (as opposed to multi-element StyleMaps used for unique value renderers). Finally, when the new layer is created, our StyleMap is added to it.

Lets take a look at how our map looks with the above tips applied (click for larger version)!

All our tips applied to our project

All our tips applied to our project

The OpenLayers guys have built an incredible piece of software – everyday I find something new and cool that I never thought it could do before. Hope you enjoyed the tips!

Great page of Open Layers examples

The more I use OpenLayers, the more I enjoy using it. I often refer to the OpenLayers examples page to look at the source of examples as inspiration for my work. Today I happened across another great website providing some more brilliant examples of how to get the most out of OpenLayers, so I thought I would share the resource here in case others also find it useful.

Enjoy!

Slimming down OpenLayers

The recent release of the 2.9.x OpenLayers javascript library has seen it grow still fatter 857kb for the OpenLayers.js if you use it out of the box from the OpenLayers download.

If you live in a bandwidth impoverished country like South Africa, those 857kb equate to a lengthy wait time while a page with a map on it first loads.

I’ve never really delved much into the inner workings of OpenLayers before – I’m just a contented user – but with this new release I thought I would take a little poke around to see if it was possible to trim some of the fat off the library.

The fine folks at OpenLayers already minify the javascript (which removes redundant white space, compacts var names etc), so my best option was to look at removing parts of the code base I don’t really use. OL supports many data formats that I’m not using e.g. WFS, bing maps, etc.

It turns out its pretty easy to create your own custom build. What I did was unpack the OL 2.9.1 tarball and then do:

cd build

To enter the build directory. Then I created a file called tim.cfg that looks like this:

# This file includes the OpenLayers code to create a build for everything that
# does not require vector support. build.py uses this profile if no other one
# is specified.

[first]
OpenLayers/SingleFile.js
OpenLayers.js
OpenLayers/BaseTypes.js
OpenLayers/BaseTypes/Class.js
OpenLayers/Console.js
OpenLayers/Util.js
OpenLayers/Events.js
OpenLayers/Handler.js
Rico/Corner.js

[last]

[include]
OpenLayers/Format/WKT.js
OpenLayers/Format/KML.js
OpenLayers/Format/WFS.js
OpenLayers/Format.js
OpenLayers/Handler/Point.js
OpenLayers/Geometry/Point.js
OpenLayers/Geometry/Surface.js
OpenLayers/Geometry.js
OpenLayers/Layer/Vector.js
OpenLayers/Control/Attribution.js
OpenLayers/Control/Button.js
OpenLayers/Handler/Box.js
OpenLayers/Handler/Click.js
OpenLayers/Handler/Drag.js
OpenLayers/Handler/Feature.js
OpenLayers/Handler/Hover.js
OpenLayers/Handler/Keyboard.js
OpenLayers/Handler/MouseWheel.js
OpenLayers/Handler/Path.js
OpenLayers/Handler/Point.js
OpenLayers/Handler/Polygon.js
OpenLayers/Handler/RegularPolygon.js
OpenLayers/Control/ZoomBox.js
OpenLayers/Control/ZoomToMaxExtent.js
OpenLayers/Control/DragPan.js
OpenLayers/Control/Measure.js
OpenLayers/Control/MouseDefaults.js
OpenLayers/Control/MousePosition.js
OpenLayers/Control/KeyboardDefaults.js
OpenLayers/Control/PanZoom.js
OpenLayers/Control/ArgParser.js
OpenLayers/Control/Permalink.js
OpenLayers/Control/Scale.js
OpenLayers/Feature/Vector.js
OpenLayers/Renderer
OpenLayers/Renderer/Elements.js
OpenLayers/Renderer/SVG.js
OpenLayers/Renderer/VML.js
OpenLayers/Renderer.js
OpenLayers/Map.js
OpenLayers/Layer/WMS.js
[exclude]

Once that is created, you can build the library then copy it into your project to test:

python build.py tim.cfg
cp OpenLayers.js [your project dir]

Then reload your web page with a map on it. You can incrementally remove features while testing your page still works properly until you reach the happy medium of size vs functionality. In my case my custom OpenLayers.js came out to a much smaller size – 342kb – and given time I could probably strip it down further.

Thanks to the OpenLayers devs for a great library!

Update After posting this I realised that I hadnt removed WFS and KML – after removing those two lines in the above file, the library now weighs in at 290kb!

OpenLayers Progress Indicator meets CSS

When the OpenLayers map of your site takes some time to load and you wish to give feedback to the user, the first place to look is the Loading Panel Addin. This addin provides an animated bar, that progresses as soon as a layer is loaded on the map. But you are not bound to its standard appearance – CSS offers you an undefined customisation freedom.

I first chose a simple progress bar, with a little globe image added to it for each loaded layer, and I felt happy enough. But I’m still a CSS beginner and moreover a very cold fan of GUIs, unlike Tim, who got a nice nice animated gif to show the progress of the map population. The AjaxInfo website provided a wide range of indicators – have fun and be sure to add it to your bookmarks!

Here are the relevant code snippets of our implementation:

1- Include the LoadingPanel Addin javascript into the head of your HTML page:

<script type="text/javascript" charset="utf-8" src="LoadingPanel.js"> </script>

2- Add the functionality in mainJavaScriptFile.js:

var loadingPanel = new OpenLayers.Control.LoadingPanel();
map.addControl(loadingPanel);    

//show the control
loadingPanel.maximizeControl();
// load your layers here
// remove it as the above function returns
loadingPanel.minimizeControl();

Note: that way, the LoadingPanel doesn’t know how many layers you are loading. The wiki page and the related example do, with much more code. I liked that 5-line implementation – and the animated gif required only a little…

3- CSS tweak

.olControlLoadingPanel {
    background-image: url("/static/images/ajax-loader.gif");
    background-color: none;
    position: relative;
    width: 50px;
    height: 50px;
    background-position:center;
    background-repeat:no-repeat;
    display: none;
}

That rocks heh? Hope this can be helpful to the OpenLayers users community!
–anne