Skip to main content

Create a map view

A lot of VIKTOR applications (especially in the infra sector) are strongly related to locations on a map. In those cases it can be helpful to display locations in a map visualization. This guide explains how to add an OpenStreetMap view to a VIKTOR entity. There are 2 different VIKTOR objects to realize this:

  • If you want to build map elements using simple map geometry objects use the MapView object
  • If you want to use exports from external software to generate a geojson format (e.g. GIS), please see if the GeoJSONView is a better fit.

Map view

note

All features in the MapView and GeoJSONView expect coordinates in the WGS system. In case you are using the RD-system you can make use of the RDWGSConverter to obtain the corresponding WGS coordinates:

lat, lon = RDWGSConverter.from_rd_to_wgs((x, y))

MapView

In the MapView map primitives (features) can be used to construct markers, (poly)lines and surfaces on this map, to add user relevant information.

Example implementation

from viktor.views import MapLinefrom viktor.views import MapPointfrom viktor.views import MapResultfrom viktor.views import MapViewclass Controller(ViktorController):    ...    @MapView('Map view', duration_guess=1)    def get_map_view(self, params, **kwargs):        marker = MapPoint(51.99311570849245, 4.385752379894256)        line = MapLine(            MapPoint(51.99311570849245, 4.385752379894256),            MapPoint(52.40912125231122, 5.031738281255681)        )        features = [marker, line]        return MapResult(features)

Styling the map elements

VIKTOR supports the following property attributes for styling the map elements:

  • title: Title of a clickable map feature.
  • description: Description of a clickable map feature. Supports formatting with Markdown.
  • color: Specifies the color of the map feature.
  • entity_links: When clicking on the map feature, links towards multiple entities can be shown.
  • icon: Icon to be shown (MapPoint only). See MapPoint for all available icons (>= v12.11.0).
from viktor import Colorfrom viktor.views import MapEntityLinklink_1 = MapEntityLink('First entity', first_entity_id)link_2 = MapEntityLink('Second entity', second_entity_id)MapPoint(51.99311570849245, 4.385752379894256, title='Location', description='I am blue', icon="pin",         color=Color(90, 148, 230), entity_links=[link_1, link_2])

Linking geo-fields to the view

When geo-fields (GeoPointField, GeoPolylineField, etc.) are used in the parametrization of an entity, corresponding geo-objects (GeoPoint, GeoPolyline, etc.) will be directly available in the params. These can easily be used in a MapView, by converting to the corresponding MapFeature. Assume the following params:

params = {    'tab': {        'section': {            'geo_point': <GeoPoint>,            'geo_polyline': <GeoPolyline>,            'geo_polygon': <GeoPolygon>        }    }}
@MapView(...)def get_map_view(self, params, **kwargs):    features = []    if params.tab.section.geo_point:        features.append(MapPoint.from_geo_point(params.tab.section.geo_point))    if params.tab.section.geo_polyline:        features.append(MapPolyline.from_geo_polyline(params.tab.section.geo_polyline))    if params.tab.section.geo_polygon:        features.append(MapPolygon.from_geo_polygon(params.tab.section.geo_polygon))    return MapResult(features)

Additional styling as explained in the previous section can be added via the class methods as well:

MapPoint.from_geo_point(params.tab.section.geo_point, color=Color(90, 148, 230))

A map view can be combined with a data view using a MapAndDataView

GeoJSONView

In the GeoJSONView GeoJSON primitives can be used to construct markers, lines and surfaces on this map, to add user relevant information. Another possibility is an export from an existing GIS program which you want to show to the user.

note

GeoJSON is a standard format for encoding geographic data structures such as points, lines and polygons (geojson.org). geojson.io is a good tool for quick experiments with geojson.

Example implementation

from viktor.views import GeoJSONResultfrom viktor.views import GeoJSONViewclass Controller(ViktorController):    ...    @GeoJSONView('GeoJSON view', duration_guess=1)    def get_geojson_view(self, params, **kwargs):        geojson = {          "type": "FeatureCollection",          "features": [            {              "type": "Feature",              "properties": {},              "geometry": {                "type": "Point",                "coordinates": [                  4.385747015476227,                  51.993107450558156                ]              }            }          ]        }        return GeoJSONResult(geojson)

Styling the map elements - simplestyle-spec GeoJSON properties

GeoJSON defines the geometrical properties of the map elements and not the styling. It does however allow to convey such information under the "properties" key of the respective element. Roughly following the simplestyle-spec, VIKTOR supports the following property attributes for styling the map elements:

  • icon (geometry type 'Point' only): icon to be shown (default: "pin"). See MapPoint for all available icons (>= v12.11.0).
  • marker-color: the color of a marker *
  • description: text to show when this item is clicked. Supports formatting with Markdown
  • stroke: the color of a line as part of a polygon, polyline, or multigeometry *
  • fill: the color of the interior of a polygon *
* color rules; Colors can be in short form "#ace" or long form "#aaccee", and should contain the "#" prefix. Colors are interpreted the same as in CSS, in \#RRGGBB and \#RGB order

A GeoJSON view can be combined with a data view using a GeoJSONAndDataView

Additional map elements

Apart from geometrical features, the map can be enriched by passing the following VIKTOR specific elements in the MapResult or GeoJSONResult:

...from viktor.views import MapLabelfrom viktor.views import MapLegend@MapView(...)def get_map_view(...):    ...    legend = MapLegend(...)    labels = [        MapLabel(...),        ...    ]    return MapResult(features, labels=labels, legend=legend)  # or GeoJSONResult

Interaction

For more information on map view interaction, see here.

Testing

New in v13.3.0

Methods decorated with @MapView, @MapAndDataView, @GeoJSONView, or @GeoJSONAndDataView need to be mocked within the context of (automated) testing.

import unittestfrom viktor.testing import mock_Viewfrom app.my_entity_type.controller import MyEntityTypeControllerclass TestMyEntityTypeController(unittest.TestCase):    @mock_View(MyEntityTypeController)    def test_map_view(self):        params = ...        result = MyEntityTypeController().map_view(params=params)        self.assertEqual(result.features, ...)        self.assertEqual(result.labels, ...)