Monday, 8 August 2016

React-ing to the need for a modern MapGuide viewer (Part 3): We almost have an AJAX viewer replacement

WARNING: This post is GIFs galore. You have been warned :)

When I last wrote about this viewer, we had the following:

  • A functional map viewer component based on OpenLayers
  • A working legend component
  • A mock Task Pane that will eventually function like its AJAX viewer and Fusion counterparts
So where are we at since that post? I think we have something that can almost replace the AJAX viewer.

The above screenshot may not fully cover the extent of changes, so let's cover the changes bit by bit.

External Base Layers

The map viewer can now have external layers incorporated. Currently, this can be OpenStreetMap or any XYZ-based tile set, like Stamen tiles as seen from the above screenshot.

One thing that will surprise you (as it did for me when I got this first working), is that there is no longer a hard EPSG:3857 requirement in order for your MapGuide Map Definitions to properly line up against OpenStreetMap and friends. The above screenshot shows our venerable Sheboygan sample map in its original EPSG:4326 coordinates lined up against EPSG:3857 stamen tiles.

This is possible due to client-side raster re-projection capabilities present in OpenLayers 3 itself. What this means is that as long as your Map Definition is in a coordinate system that has a corresponding EPSG code, OpenLayers will happily re-project other layers to line up with your Map Definition instead of vice versa. In the above screenshot, the Stamen tiles are being re-projected to line up with the Map Definition.

For maps that are not in EPSG:3857 or EPSG:4326, there is currently a small additional setup process to carry out.

For example if I load the map from the Melbourne sample dataset, the viewer throws this cryptic error message.

What this error means (and something I can hopefully clean up), is that OpenLayers has no idea about the projection EPSG:28355 (the projection of the map). Although the viewer includes proj4js and automatically wires it up to OpenLayers, it still only knows about two projections out of the box: 4326 and 3857.

Foreign projections have to be registered to proj4js first ( conveniently provides proj4js snippets to show you what to do) before mounting the map viewer application component. Once I registered the projection for EPSG:28355 to proj4js, the Melbourne map shows up properly, with OpenLayers happily re-projecting the EPSG:3857 stamen tiles to line up.


The viewer now contains a floating toolbar where we can dock our various commands to. Toolbars are completely data-driven and commands inside can be individually be selected/enabled/disabled based on various states of the map viewer.

The react-flyout component is used to provide support for flyout menus

Task Pane

In our previous post, the Task Pane was nothing more than a plain UI mockup. Now it is a mostly functional simulation of what is provided by our existing viewers.

The Task Pane functions as a generic content container where various viewer commands can show their UI in. In order to fully simulate the Task Pane, it needs to provide the JS functions that Task Pane content can call back into. In other words, our viewer needs to shim/emulate the AJAX viewer APIs to allow existing Task Pane content to work.

So to this end, I've been using the official PHP Developer Guide samples as a "reference implementation" for Task Pane content and the AJAX Viewer APIs they're trying to call. The page in the first screenshot is the landing page of the developer guide samples. So what this means now, is we have emulated AJAX viewer APIs for:

Zooming/Panning to a particular location

Setting selections

Refreshing the map in response to server-side layer/group changes

Digitizing geometry

And much more!

The AJAX viewer API emulation works so well, we can throw things like the existing AJAX Viewer buffer tool at it, and it will work just fine in our new viewer environment.


Finally, as can be inferred from previous screenshots, the Legend component is now aware of external base layers and provides a switcher UI if more than one external layer is present.

So when you combine all these changes together, I think I will get agreement here that we have something that nearly approaches (in some cases, exceed) the AJAX viewer in functionality. The only glaring omissions at this point are various display elements (like a status bar), reaching command parity with the AJAX viewer, and a layout/configuration abstraction akin to a WebLayout or ApplicationDefinition, which is something I intend to implement in some form.

Before I close out this post, here's the current weigh-in for this production viewer bundle

The weight increase was mainly due to adding proj4js, but compared to Fusion we're still way smaller. As long as things stay under 1MB, I'd be content.


Unknown said...

That was almost 10 years old architecture?

Good job Jackie!

Georges said...

Yes, Good job indeed!

Danny Tuypens said...

Great !
Finally a viewer up with the latest technology, no more messing around with the ajax viewer templates :-)