Skip to content
Language
DE EN FR
Start a project

cloudtec Stack: Coordinate Picker with open source

Looking up coordinates in a third-party map, copying them and pasting them blindly into the target system: we have replaced this detour with our own widget based on OpenLayers.

A feature that looks like little but involves a fair amount of detailed work: our Coordinate Picker, based on the open-source library OpenLayers. It is built directly into our platforms, so nobody has to leave the application when entering a location.

Why we built the Coordinate Picker

Many of our projects include a map: company locations, appointments per location, hikes, activities. For a point to appear on that map, its coordinates have to be entered, and that is exactly where the detour began. Search for the location in a map service, copy the coordinates, paste them into the form. Afterwards, the target system no longer showed whether the point was really correct. On top of that, we had to explain where the values come from and in which order they belong, so that longitude and latitude would not be swapped.

That is an unnecessary break in usability. Instead of explaining further, we built our own widget for selecting coordinates that sits directly in the form in our platforms.

Form field ‘Starting point coordinates’ with an embedded swisstopo map, zoom buttons on the left and a delete button at the top right.
Setting a point: choose the map section, click in the map: the marker is placed and the coordinates are in the field.

What OpenLayers is

OpenLayers is an open-source JavaScript library for interactive maps in web applications. What makes it useful for us:

  • Open source. Free to use, adapt and pass on, as long as the licence terms are complied with.
  • Interactive maps. Multiple layers, markers, popups as well as zooming and panning are part of the library.
  • Free choice of base map. OpenStreetMap, the federal swisstopo maps and other WMS, WMTS or XYZ sources can be integrated, plus your own layers.
  • Geodata formats. Vector data such as GeoJSON and KML can be displayed directly; raster data is added via WMS or WMTS.
  • Extensible. Custom functions, custom styling and adapted interactions are designed in, not retrofitted.
  • Mobile-friendly. The maps work on different screen sizes and with touch input.
  • Documentation and community. Extensive examples and an active developer community, as is usual with open source.

How the Coordinate Picker is implemented

From the outside, the function is simple: a widget with a map in which you can zoom and set a point. The point is saved and can be displayed again anywhere else in the application. There is a little more behind it.

The same map with a marker already set and the delete button at the top right.
A set point can be moved or removed entirely using the button at the top right.

Basics

For the map material we use the swisstopo pixel map. That limits the Coordinate Picker to Switzerland. For our projects that is the right scope; for other areas you swap the map source. The widget offers three interactions: zoom, reset and delete. In the background there are two input fields for longitude and latitude, which are filled as soon as the point is set.

The feature is implemented in standard JavaScript plus jQuery. Global settings define the zoom level and map section when it is opened. A bounding box limits the map to Swiss territory, so that no point can be set outside the map material; at the same time it keeps the aspect ratio when the size of the widget changes.

Then there are event listeners, for example on the click that sets the pin. The OpenLayers event is translated into a dedicated Coordinate Picker event, to which further actions can be attached, such as saving the point directly. When the widget is opened, mechanisms ensure that it does not initialise twice and that actions are not executed twice. Existing data is loaded and the buttons are shown accordingly.

Two coordinate systems

Two projections run side by side in the background. The swisstopo map delivers EPSG:3857, that is WGS 84 / Pseudo-Mercator, the usual Web Mercator grid for tiled maps. Towards the outside, however, the widget works with EPSG:4326: WGS 84 in longitude and latitude, the way GPS devices output it and the way we store the values. Conversion between the two is needed; OpenLayers comes with the function for it. If the projection is configured wrongly, the points end up off target, and debugging becomes tedious because the widget otherwise works normally.

Code

For anyone curious, and very much in the spirit of open source: the defaults and the conversion, which show the principle.

class CoordinatePicker extends EventTarget {
    // global defaults
    static options = {
        center: [915000, 5910000], // center of switzerland
        boundingBox: [670433, 5744676, 1162476, 6078756], // swiss extent in EPSG:3857
        zoom: 14, // used when there is already a coordinate set
        backgroundLayerUrl: 'https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/3857/{z}/{x}/{y}.jpeg',
    };

    // expects coordinates in GPS (WGS84, EPSG:4326) format
    setData(long, lat) {
        // set data on input fields
        let inputs = this.getInputs();
        inputs.long.val(long);
        inputs.lat.val(lat);
        inputs.long.trigger("change");
        inputs.lat.trigger("change");

        // convert to map coordinates and set the marker
        let coords = ol.proj.transform([long, lat], 'EPSG:4326', 'EPSG:3857');
        this.markerSource.clear();
        this.markerSource.addFeature(new ol.Feature({
            geometry: new ol.geom.Point(coords)
        }));
    }
}
Written by Lukas Knöpfel Senior Fullstack Software Developer

Tech 4 min read