Run Example Apps

The Data Inspector Library contains example applications designed to help you understand the different use cases for the Library.

Each example runs in the Data Inspector application window (represented by the DataInspector class) and explains a single feature of a certain Data Inspector Library component or a combination of various features.

To install and run the examples, you should follow the steps described in the Install Example Apps chapter. Once installed, open the examples at http://localhost:5000/.

Data Inspector Library Examples
Figure 1. Data Inspector Library Examples

To quickly find an example by name, you can use the filter field.

Each example features the button in the bottom-right corner, showing the source code of each example when clicked.

Examples List

This chapter describes all the examples that the Data Inspector Library contains, including their source code (click to expand):

control / DI

http://localhost:5000/#dist/verity_control_DI

This example showcases how an embedded application can control the DataInspector from outside.

It is possible to change the catalog's HERE Resource Name (HRN), layer, layer version, as well as zoom level and map view location based on user input or URL parameters.

In this example, an input form is provided where you can enter the HRN, layer, version, latitude, longitude, and zoom level values in order to change the state of the DataInspector.

For this purpose, DataInspector provides these public methods:

  • setState: Sets a new state for the DataInspector and reloads with a new HRN, layer, and layer version.
  • focusMapCameraAt: Centers the camera at the specified coordinates and sets the desired zoom level.

Also, you can get the state of the DataInspector and maintain it in the URL parameters when you move around, or specify a new HRN, version, or layer, for example:

?hrn=hrn:here-cn:data::olp-cn-here:here-map-content-china-2&layer=topology-geometry&location=52.4956004,13.3553675&zoomLevel=10

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { GeoCoordinates } from "@here/harp-geoutils";
import { MapViewEventNames } from "@here/harp-mapview";
import { DataInspector } from "@here/interactive-mapview-ui";
import { WidgetAbstract } from "@here/interactive-mapview-ui/lib/core/WidgetAbstract";
import {
    ToolBar,
    ToolBarVersionChangeEvent
} from "@here/interactive-mapview-ui/lib/data-inspector/ToolBar";
import { Action, History, Location, createBrowserHistory } from "history";
import {
    enableExtendedCoverage,
    layerBrowserAppDataLayer,
    layerBrowserAppHostHrn,
    lookupServiceEnvironment
} from "../config";
import { PanelDisplayMode } from "@here/interactive-mapview-ui";

/**
 * This example showcases how embedded application can control the data inspector from outside.
 *
 * It is possible to change the catalog HRN, layer, and layer version, as well as
 * zoom level and location of the map view based on user input or URL parameters.
 *
 * In this example the input form provided where user can input HRN, Layer, Version, Latitude,
 * Longitude and Level in order to change the state of the data inspector.
 *
 * For this purpose the `DataInspector` provides public methods such as:
 * `setState` - Sets new state for a component and reloads with new HRN, layer and layer version.
 * `focusMapCameraAt` - Centers the camera at the specified coordinates and sets desired zoom level.
 *
 * Also, it allows to get state of the data inspector and maintain it in the URL parameters
 * when user moves around or gives new HRN/version/layer:
 * ?hrn=hrn:here:data::olp-here:rib-2&layer=topology-geometry&location=52.4956004,13.3553675&zoomLevel=10
 */

/**
* Interface for parameters which controls the data inspector.
*/
interface DataInspectorControlParams {
    /**
     * A catalog HRN string for the data source.
     */
    hrn: string;

    /**
     * A layer name for the data source.
     */
    layer: string;

    /**
     * A version of the data source layer.
     */
    version?: number;

    /**
     * Map zoom level.
     */
    zoomLevel?: number;

    /**
     * Camera position.
     */
    location?: {
        latitude: number;
        longitude: number;
    };
}

/**
 * Class which implements functionality of controlling the data inspector.
 */
class LayerBrowserApplication {
    /** An instance of [[DataInspector]] UI widget. */
    private m_dataInspector: DataInspector;

    /**
     * Parameters which controls the data inspector.
     * Catalog HRN and layer already set by default. Can be changed to any other supported
     * catalog/layer.
     */
    private m_controlParams: DataInspectorControlParams = {
        hrn: layerBrowserAppHostHrn,
        layer: layerBrowserAppDataLayer
    };

    /**
     * An object which lets easily manage browser history.
     */
    private m_browserHistory: History | undefined;

    /**
     * One of PUSH, REPLACE, or POP depending on how the URL was set.
     */
    private m_browserAction: Action = "PUSH";

    /**
     * Constructor initializes browser history, control parameters, data inspector, listeners and
     * user input form.
     *
     * @param useHistory Demonstrates possibility to control the data inspector from embedded
     * application. If `false` browser history will not be used to avoid URL parameters conflict.
     */
    constructor(useHistory = true) {
        if (useHistory) {
            this.m_browserHistory = createBrowserHistory();
            this.m_browserHistory.listen(this.browserHistoryHandler.bind(this));
        }

        // Fetch control parameter from URL before creating data inspector instance in order to
        // initialize with defined in URL parameters.
        this.fetchControlParams();

        // Set browser title.
        this.setBrowserTitle();

        // Create data inspector.
        this.m_dataInspector = new DataInspector(
            {
                mapView: {
                    theme: "resources/normal.reduced.night.json",
                    decoder: {
                        url: "./decoder.bundle.js"
                    },
                    defaultZoomLevel: this.m_controlParams.zoomLevel
                },
                widgets: {
                    authForm: {
                        tokenForm: false,
                        accessKeyForm: true,
                        localAuthForm: true
                    }
                },
                logMessages: true,
                lookupServiceEnvironment
            },
            document.getElementById("map-here") as HTMLElement,
            {
                interactiveDataSource: {
                    hrn: this.m_controlParams.hrn,
                    layer: this.m_controlParams.layer,
                    catalogVersion: this.m_controlParams.version
                },
                enableCoverage: true,
                enableExtendedCoverage,
                enableFiltering: true,
                enableInfoPanel: true
            }
        );

        // Open control panel to pay attention of the user on authorization form in case if not
        // logged in.
        if (
            this.m_dataInspector.toolBar !== undefined &&
            this.m_dataInspector.authForm !== undefined &&
            this.m_dataInspector.authForm.isDisabled === false
        ) {
            const leftPanelBtn = this.m_dataInspector.toolBar.getLeftPanelBtn();
            if (leftPanelBtn) {
                leftPanelBtn.switchOn();
            }
        }

        // Add listeners after data inspector created.
        this.addDataInspectorStateListeners();

        // During update of the data inspector event listeners destroyed, so it requires to add
        // listeners again.
        this.m_dataInspector.addEventListener(
            WidgetAbstract.EVENT_AFTER_UPDATE,
            this.addDataInspectorStateListeners.bind(this)
        );

        // Adds submit handler for user input form.
        this.initializeUserInputForm();
    }

    /**
     * Changes state of the data inspector when navigating
     * by browser buttons ("Back", "Forward") without page reload.
     *
     * @param location The current location.
     * @param action The current navigation action (PUSH, REPLACE, or POP).
     */
    private browserHistoryHandler(location: Location, action: Action): void {
        this.m_browserAction = action;
        this.fetchControlParams();

        // Update browser title.
        this.setBrowserTitle();

        // Change state of the data inspector only on actions caused by
        // browser buttons ("Back", "Forward").
        if (action !== "POP") {
            return;
        }

        this.changeState(
            this.m_controlParams.hrn,
            this.m_controlParams.layer,
            this.m_controlParams.version,
            this.m_controlParams.location !== undefined
                ? this.m_controlParams.location.latitude
                : undefined,
            this.m_controlParams.location !== undefined
                ? this.m_controlParams.location.longitude
                : undefined,
            this.m_controlParams.zoomLevel
        );
    }

    /**
     * Adds listeners of events which changes state of the data inspector
     * in order to represent actual parameter values in URL.
     */
    private addDataInspectorStateListeners(): void {
        if (this.m_browserHistory === undefined || this.m_dataInspector.mapView === undefined) {
            return;
        }

        // Covers `zoomLevel`, `location.latitude` and `location.longitude`.
        this.m_dataInspector.mapView.addEventListener(MapViewEventNames.MovementFinished, () => {
            // Don't change URL in case of `window.history.back()` or `window.history.forward()`
            // since it already changed.
            if (this.m_browserAction === "POP") {
                this.m_browserAction = "PUSH";
                return;
            }
            if (this.m_dataInspector.mapView === undefined) {
                return;
            }

            this.pushToHistory({
                ...this.m_controlParams,
                zoomLevel: this.m_dataInspector.mapView.zoomLevel,
                location: {
                    latitude: this.m_dataInspector.mapView.geoCenter.latitude,
                    longitude: this.m_dataInspector.mapView.geoCenter.longitude,
                }
            });
        });

        // Covers `version`.
        if (this.m_dataInspector.toolBar !== undefined) {
            this.m_dataInspector.toolBar.addEventListener(
                ToolBar.ON_CATALOG_VERSION_SELECT,
                (event: ToolBarVersionChangeEvent) => {
                    this.pushToHistory({
                        ...this.m_controlParams,
                        version: event.catalogVersion
                    });
                }
            );
        }
    }

    /**
     * Fetch data inspector control parameters from page URL.
     */
    private fetchControlParams(): void {
        if (this.m_browserHistory === undefined) {
            return;
        }

        const searchParams = new URLSearchParams(location.search);

        const urlHrn = searchParams.get("hrn");
        if (urlHrn !== null) {
            this.m_controlParams.hrn = urlHrn;
        }

        const urlLayer = searchParams.get("layer");
        if (urlLayer !== null) {
            this.m_controlParams.layer = urlLayer;
        }

        const urlVersion = searchParams.get("version");
        if (urlVersion !== null) {
            const version = Number.parseInt(urlVersion, undefined);
            this.m_controlParams.version = !Number.isNaN(version) ? version : undefined;
        } else {
            // If `version` parameter not present in URL it should be latest version.
            this.m_controlParams.version = undefined;
        }

        const urlZoomLevel = searchParams.get("zoomLevel");
        if (urlZoomLevel !== null) {
            const zoomLevel = Number.parseInt(urlZoomLevel, undefined);
            this.m_controlParams.zoomLevel = !Number.isNaN(zoomLevel) ? zoomLevel : undefined;
        }

        const urlLocation = searchParams.get("location");
        if (urlLocation !== null) {
            const coordinates = urlLocation.split(",");
            if (coordinates.length === 2) {
                const latitude = Number.parseFloat(coordinates[0]);
                const longitude = Number.parseFloat(coordinates[1]);
                if (!isNaN(latitude) && !isNaN(longitude)) {
                    this.m_controlParams.location = {
                        latitude,
                        longitude
                    };
                }
            }
        }
    }

    /**
     * Updates page URL to represent state of the data inspector.
     * This method manipulates the browser history by pushing new URL into history which
     * allows to navigate through different states of data inspector without page reload.
     *
     * @param controlParams Parameters which controls the data inspector.
     */
    private pushToHistory(controlParams: DataInspectorControlParams): void {
        if (this.m_browserHistory === undefined) {
            return;
        }

        const searchParams: string[] = [];

        if (controlParams.hrn !== undefined) {
            searchParams.push("hrn=" + controlParams.hrn);
        }

        if (controlParams.layer !== undefined) {
            searchParams.push("layer=" + controlParams.layer);
        }

        if (controlParams.version !== undefined) {
            searchParams.push("version=" + controlParams.version);
        }

        if (
            controlParams.location !== undefined &&
            controlParams.location.latitude !== undefined &&
            controlParams.location.longitude !== undefined
        ) {
            const location = Number(controlParams.location.latitude).toFixed(5)
                + "," + Number(controlParams.location.longitude).toFixed(5);
            searchParams.push("location=" + location);
        }

        if (controlParams.zoomLevel !== undefined) {
            searchParams.push("zoomLevel=" + Math.floor(controlParams.zoomLevel));
        }

        const search = "?" + searchParams.join("&");

        if (this.addOptionalParameters(search) ===
            this.addOptionalParameters(this.m_browserHistory.location.search)
        ) {
            if (search === this.m_browserHistory.location.search) {
                // Don't add to history if URL the same as current one.
                return;
            } else {
                // Replace latest URL in the history in case if it's just extended with optional
                // parameter(s) (e.g. &zoomLevel=10 added).
                this.m_browserHistory.replace({
                    pathname: this.m_browserHistory.location.pathname,
                    search: this.addOptionalParameters(search)
                });
            }
        } else {
            // Add new URL to the history.
            this.m_browserHistory.push({
                pathname: this.m_browserHistory.location.pathname,
                search
            });
        }
    }

    /**
     * Adds optional parameters to search query in order to be able to compare all configuration
     * parameters.
     * @param search URL search query
     */
    private addOptionalParameters(search: string): string {
        // Optional parameters.
        const params = new Map();
        params.set("hrn", this.m_controlParams.hrn);
        params.set("layer", this.m_controlParams.layer);

        if (this.m_dataInspector.mapView) {
            params.set(
                "location",
                Number(this.m_dataInspector.mapView.geoCenter.latitude).toFixed(5) + "," +
                Number(this.m_dataInspector.mapView.geoCenter.longitude).toFixed(5)
            );
            params.set("zoomLevel", Math.floor(this.m_dataInspector.mapView.zoomLevel).toString());
        }

        // Extend/replace optional parameters with actual values from URL.
        search.substr(1).split("&").forEach(param => {
            const paramPair = param.split("=");
            if (paramPair.length === 2) {
                params.set(paramPair[0], paramPair[1].toString());
            }
        });

        // Get final search query with all parameters.
        const fullSearch = [];
        for (const entry of params.entries()) {
            fullSearch.push(entry.join("="));
        }

        return "?" + fullSearch.join("&");
    }

    /**
     * Adds submit handler of user input form where user can change some parameters to control data
     * inspector from outside.
     */
    private initializeUserInputForm(): void {
        const form = document.getElementById("userInputForm") as HTMLFormElement;
        if (form === null) {
            return;
        }
        form.onsubmit = this.userInputFormHandler.bind(this);
        this.populateUserInputForm(form);
    }

    /**
     * Populate form fields with default configurations.
     * @param form From object.
     */
    private populateUserInputForm(form: HTMLFormElement): void {
        const config = this.m_dataInspector.getConfig();
        if (config === undefined) {
            return;
        }

        const formFields = form.elements;

        if (config.interactiveDataSource !== undefined) {
            (formFields.namedItem("userHrn") as HTMLInputElement).value =
                config.interactiveDataSource.hrn.toString();
            (formFields.namedItem("userLayer") as HTMLInputElement).value =
                config.interactiveDataSource.layer.toString();
            (formFields.namedItem("userVersion") as HTMLInputElement).value =
                config.interactiveDataSource.catalogVersion !== undefined
                    ? config.interactiveDataSource.catalogVersion.toString() : "";
        }
        const geoCenter = config.mapView.geoCenter || config.mapView.defaultGeoCenter;
        (formFields.namedItem("userLatitude") as HTMLInputElement).value =
            geoCenter.latitude.toFixed(5);
        (formFields.namedItem("userLongitude") as HTMLInputElement).value =
            geoCenter.longitude.toFixed(5);
        (formFields.namedItem("userZoomLevel") as HTMLInputElement).value =
            config.mapView.defaultZoomLevel.toString();
    }

    /**
     * Gathers user input, changes data inspector state and updates URL.
     */
    private userInputFormHandler(event: Event): boolean {
        const formData = new FormData(event.target as HTMLFormElement);

        // Data source.
        const hrn = formData.get("userHrn") as string || this.m_controlParams.hrn;
        const layer = formData.get("userLayer") as string || this.m_controlParams.layer;
        let version: number | undefined = Number.parseInt(
            formData.get("userVersion") as string,
            undefined
        );
        version = !isNaN(version) ? version : undefined;

        // Camera position.
        let latitude: number | undefined = Number.parseFloat(
            formData.get("userLatitude") as string
        );
        latitude = !isNaN(latitude) ? latitude : undefined;
        let longitude: number | undefined = Number.parseFloat(
            formData.get("userLongitude") as string
        );
        longitude = !isNaN(longitude) ? longitude : undefined;
        const location = latitude !== undefined && longitude !== undefined ? {
            latitude,
            longitude
        } : undefined;
        const zoomLevel: number | undefined = Number.parseInt(
            formData.get("userZoomLevel") as string,
            undefined
        ) || undefined;

        this.changeState(hrn, layer, version, latitude, longitude, zoomLevel);

        this.pushToHistory({
            hrn,
            layer,
            version,
            zoomLevel,
            location
        });

        // Prevent default submit behavior.
        return false;
    }

    /**
     * Changes state of data inspector (data source and position of camera).
     * @param hrn Catalog HRN.
     * @param layer Catalog layer.
     * @param version Layer version.
     * @param latitude Latitude.
     * @param longitude Longitude.
     * @param zoomLevel Zoom level.
     */
    private changeState(
        hrn: string,
        layer: string,
        version?: number,
        latitude?: number,
        longitude?: number,
        zoomLevel?: number
    ): void {
        this.changeDataInspectorState(hrn, layer, version);

        const coordinates = latitude !== undefined && longitude !== undefined
            ? new GeoCoordinates(latitude, longitude)
            : undefined;

        this.m_dataInspector.focusMapCameraAt(coordinates, zoomLevel);
    }

    /**
     * Sets new state of the data inspector with changed HRN, layer and/or layer version.
     * @param hrn Catalog HRN.
     * @param layer Catalog layer.
     * @param version Layer version.
     */
    private changeDataInspectorState(hrn: string, layer: string, version?: number): void {
        const config = this.m_dataInspector.getConfig();
        // Don't change state if hrn, layer or version wasn't changed.
        if (config !== undefined
            && config.interactiveDataSource !== undefined
            && config.interactiveDataSource.hrn === hrn
            && config.interactiveDataSource.layer === layer
            && config.interactiveDataSource.catalogVersion === version
        ) {
            return;
        }

        const prevState = this.m_dataInspector.state;
        const controlPanel = this.m_dataInspector.controlPanel;
        const prevControlPanelDisplayMode =
            controlPanel ? controlPanel.state.displayMode : undefined;

        this.m_dataInspector.setState({
            ...prevState,
            interactiveDataSource: {
                ...prevState.interactiveDataSource,
                hrn,
                layer,
                catalogVersion: version
            }
        });

        if (controlPanel !== undefined) {
            if (prevControlPanelDisplayMode === PanelDisplayMode.Expanded) {
                controlPanel.show();
            } else {
                controlPanel.hide();
            }
        }
    }

    /**
     * Sets browser title with HRN and layer.
     */
    private setBrowserTitle(): void {
        document.title = this.m_controlParams.hrn + "/" + this.m_controlParams.layer;
    }
}

// Run example application.
new LayerBrowserApplication();

interactive / DI / basic

http://localhost:5000/#dist/verity_interactive_DI_basic

This example is similar to the interactive / DI / default example, but offers a minimum number of options. To show a single map, just remove the interactiveDataSource object from the DataInspector constructor.

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { DataInspector } from "@here/interactive-mapview-ui";
import { lookupServiceEnvironment, ribCartoLayer, ribHostHrn } from "../config";

new DataInspector(
    {
        mapView: {
            decoder: {
                url: "./decoder.bundle.js"
            }
        },
        widgets: {
            authForm: {
                accessKeyForm: true
            }
        },
        lookupServiceEnvironment: lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        // this "interactiveDataSource" object can be commented to just show the map.
        interactiveDataSource: {
            hrn: ribHostHrn,
            layer: ribCartoLayer
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);

tokenprovider

http://localhost:5000/#dist/verity_token_provider

This example demonstrates how to create and use a simple server-side token provider. Rather than having a login that works on all accounts for demo purposes, the token provider generates login tokens based on your own credentials only. A client application can request and use these tokens for all its requests.

For more details on how to run this example, see Use Token from Server Token Provider

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

/*
 * This file shows the simple NodeJS back-end application that provides tokens to clients.
 *
 * Current example hands out tokens to anybody who has access, therefore an access to the the server
 * should be additionally protected (e.g. some company specific login mechanism).
 */

// Raw function, that is used to retrieve tokens.
const requestToken = require("@here/olp-sdk-authentication").requestToken;

// Initialize the server.
const express = require("express");
const app = express();


// Get credentials from the file ./credentials.properties
// snippet:token-provider-credentials.js
const credentials = require("fs").readFileSync("./credentials.properties");
const url = (/here\.token\.endpoint\.url\s*=\s*([\S]*)/g).exec(credentials)[1];
const consumerKey = (/here\.access\.key\.id\s*=\s*([\S]*)/g).exec(credentials)[1];
const secretKey = (/here\.access\.key\.secret\s*=\s*([\S]*)/g).exec(credentials)[1];
const scope = ((/here\.token\.scope\s*=\s*([\S]*)/g).exec(credentials) || [])[1];
// end:token-provider-credentials.js

// snippet:token-provider-app.js
// Cached data
let tokenExpirationTime = new Date();
let tokenInfo = null;

// Add GET endpoint on this server, that will fetch the token from the token endpoint.
// API format: /getToken?ttl={number}, where ttl is an optional parameter which defines the time to
// live of a token in seconds.
app.get("/getToken", async (request, response) => {
    try {
        if (new Date() >= tokenExpirationTime) {
            console.log('Request a new token...');

            tokenInfo = await requestToken({
                // Set the token endpoint
                url,

                // Set the time to live of the token. If not defined, then 3600 sec will be used by default.
                expiresIn: request.query.ttl,

                // Pass credential data.
                consumerKey,
                secretKey,
                scope
            });

            tokenExpirationTime = new Date(Date.now() + tokenInfo.expiresIn * 1000);

            console.log(`The token expires on: ${tokenExpirationTime}`);
        }

        // Allow CORS. Optional, if token provider and client application will be hosted on different server
        response.set("Access-Control-Allow-Origin", "*");

        // Send back token to the requestor.
        response.status(200).send(tokenInfo.accessToken);
    } catch (e) {
        // For code brevity, we don't analyze error type and return HTTP 500 response.
        console.error(`Error acquiring new token: ${e.message}`);
        response.status(500).send(e.message);
    }
});
// end:token-provider-app.js


// snippet:token-provider-listen.js
// Define the server port.
const PORT = 3000;

// Start the server.
app.listen(PORT, () => {
    console.log(`Token provider is listening port ${PORT}`);
});
// end:token-provider-listen.js
interactive / DI / full

http://localhost:5000/#dist/verity_interactive_DI_full

This example is similar to the interactive / DI / default example, but with the 'Stats' panel enabled. This panel shows a log with information about decoded tiles and an expanded panel with information about the decoded tile. For all possible configuration options for UI elements, see the source code of this example below.

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

/*
 * This example shows all properties `DataInspector` can accept to customize visualization.
 *
 * Please visit API documentation to see the detailed description of all constructor arguments:
 * https://developer.here.com/olp/documentation/data-inspector-library/api_reference_typedoc/classes/_here_interactive_mapview_ui.hostcomponent.html#constructor
 */


import { DataInspector, PanelDisplayMode } from "@here/interactive-mapview-ui";
import {
    boundingBox,
    enableExtendedCoverage,
    geoCenter,
    lookupServiceEnvironment,
    omvHostHrn,
    omvDataLayer,
    ribHostHrn,
    ribTopologyLayer
} from "../config";


new DataInspector({
        elementId: "my-host-component",

        // The property below sets custom auth token provider without authentication form.
        // getBearerToken: () => Promise.resolve("Your Token"),

        mapView: {
            theme: "resources/normal.reduced.day.json",
            decoder: {
                url: "./decoder.bundle.js",
                count: 2
            },
            maxZoomLevel: 15,
            defaultZoomLevel: 12,
            geoCenter: geoCenter,
            // Please note that the "boundingBox" property will override the values of "geoCenter"
            // and "defaultZoomLevel" properties.
            boundingBox,
            enableTilt: false,
            enableRotation: false
        },
        baseMap: {
            hrn: omvHostHrn,
            layer: omvDataLayer,
            // Catalog version for the base map.
            // version: -1;
            styleSetName: "tilezen" //The name of the style set from the theme
        },
        widgets: {
            zoomLevel: true,
            statusBar: true,
            searchField: true,
            decodedPanel: {
                enabled: true,
                initialState: PanelDisplayMode.Expanded,
                width: 400
            },
            statsPanel: {
                enabled: true,
                initialState: PanelDisplayMode.Collapsed
            },
            authForm: {
                tokenForm: true,
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        toolbar: {
            enabled: true,
            fullScreenButton: true
        },
        logMessages: true,
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: ribHostHrn,
            layer: ribTopologyLayer,
            catalogVersion: 0,
            levelWithData: 12,
            externalRendererPluginName: "interactive_host_full.plugin.template",
            preferRendererPlugin: false
        },
        enableCoverage: true,
        enableExtendedCoverage,
        enableInfoPanel: true,
        enableFiltering: true
    }
);

js / integration

http://localhost:5000/#dist/verity_js_integration

This example demonstrates the easiest way to embed visualization in a single-page application written in pure HTML and JavaScript. This example uses the DataInspector class with all the default values. To run this example code, no compilation is required.

leaflet / geojson

http://localhost:5000/#dist/verity_leaflet_geojson

The leaflet / geojson example demonstrates how you can use JavaScript to authenticate with OLP and access GeoJSON data in the HERE GeoJSON Samples catalog with the OLP SDK for TypeScript, how to show the OMV basemap using the HARP plugin for Leaflet, and how to visualize the data on top of the basemap. For more details, see Inspect OLP Data with Leaflet.

Example Source Code


/*
 * Copyright (C) 2019-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */


async function start(env, accessKeyId, accessKeySecret, scope, hrn, layerId, partitions, latLong, zoom, baseMapHRN) {
    // Get a function, that will provide a token for an access to HERE data.
    const token = new UserAuth({
        env,
        credentials: {
            accessKeyId,
            accessKeySecret
        },
        tokenRequester: requestToken,
        scope
    }).getToken();
    const getToken = () => token;

    // Get layer object, that will fetch GeoJSON data.
    const settings = new OlpClientSettings({
        environment: env,
        getToken
    });
    const layer = await getLayerClient(hrn, layerId, settings);
    if (!layer) {
        throw new Error("Layer not found");
    }

    // Create Leaflet map.
    const map = L.map("map", {
        renderer: L.canvas()
    });
    map.setView(latLong, zoom);

    // snippet:leaflet-get-geojson.js
    // Get tile data and add to Leaflet.
    partitions.forEach(async partition => {
        const request = new DataRequest()
            .withPartitionId(`${partition}`);
        const response = await layer.getData(request);
        const data = await response.json();

        L.geoJSON(data)
            .bindPopup(item => item.feature.properties.tooltip)
            .addTo(map);
    });
    // end:leaflet-get-geojson.js



    // Add the HERE base map. This can be replaced with the code of your preferred base map.
    const harpLeaflet = new L.HarpGL({
        theme: "https://unpkg.com/@here/harp-map-theme@0.12.0/resources/berlin_tilezen_night_reduced.json"
    }).addTo(map);
    const baseMapLayer = await getLayerClient(baseMapHRN, "omv-base-v2", settings);
    harpLeaflet.mapView.addDataSource(new harp.OmvDataSource({
        dataProvider: {
            async getTile(tileKey) {
                const request = new DataRequest()
                    .withPartitionId(`${mortonCodeFromQuadKey(tileKey)}`);
                const response = await baseMapLayer.getData(request);
                return response.arrayBuffer();
            },
            async connect() {},
            async ready() { return true; }
        },
        layerName: "omv-base-v2",
        getBearerToken: getToken,
        styleSetName: "tilezen"
    }));
}

/**
 * Fetch the layer config and return an instance of a layer client.
 * 
 * @param hrn A catalog HRN.
 * @param layerId A layer ID.
 * @param settings Client settings.
 */
async function getLayerClient(hrn, layerId, settings) {
    const catalogClient = new CatalogClient(HRN.fromString(hrn), settings);
    const config = await catalogClient.getCatalog(new CatalogRequest());
    const layerConfig = config.layers.find(item => item.id === layerId);
    if (layerConfig === undefined) {
        return;
    }

    switch (layerConfig.layerType) {
        case "versioned":
            return new VersionedLayerClient(hrn, layerId, settings);

        case "volatile":
            return new VolatileLayerClient(hrn, layerId, settings);
    }
}
leaflet / protobuf

http://localhost:5000/#dist/verity_leaflet_protobuf

The leaflet / protobuf example demonstrates how you can use JavaScript to authenticate with OLP and access Protobuf-encoded data in the Road Topology & Geometry layer from the HERE Map Conent catalog with the OLP SDK for TypeScript, how to retrieve a schema from the layer and use it to decode the data into GeoJSON, how to show the OMV basemap using the HARP plugin for Leaflet, and how to visualize the data on top of the basemap. For more details, see Inspect OLP Data with Leaflet.

Example Source Code


/*
 * Copyright (C) 2019-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */


async function start(env, accessKeyId, accessKeySecret, scope, hrn, layerId, partitions, latLong, zoom, baseMapHRN) {
    // snippet:leaflet-get-token.js
    // Get a function, that will provide a token to access HERE data.
    const token = new UserAuth({
        env,
        credentials: {
            accessKeyId,
            accessKeySecret
        },
        tokenRequester: requestToken,
        scope
    }).getToken();
    const getToken = () => token;
    // end:leaflet-get-token.js

    // snippet:leaflet-get-layer.js
    // Get layer object, that will fetch GeoJSON data.
    const settings = new OlpClientSettings({
        environment: env,
        getToken
    });
    const layerConfig = await getLayerConfig(hrn, layerId, settings);
    if (!layerConfig) {
        throw new Error("Layer config was not found");
    }

    const layer = getLayerClient(layerConfig.layerType, hrn, layerId, settings);
    // end:leaflet-get-layer.js

    // snippet:leaflet-get-decoder.js
    if (layerConfig.schema === undefined || layerConfig.schema.hrn === undefined) {
        throw new Error("Layer schema HRN is not defined");
    }

    // Get a decoder from the schema.
    const decoder = await getDecoder(layerConfig.schema.hrn, settings);
    if (!decoder) {
        throw new Error("Decoder was not found.");
    }
    // end:leaflet-get-decoder.js

    // Create Leaflet map.
    const map = L.map("map", {
        renderer: L.canvas()
    });
    map.setView(latLong, zoom);

    // snippet:leaflet-get-protobuf.js
    // Fetch, decode and visualize specific partitions.
    partitions.forEach(async partition => {
        const request = new DataRequest()
            .withPartitionId(`${partition}`);
        const response = await layer.getData(request);
        const data = await response.arrayBuffer();

        const decodedData = decode(data, decoder);

        const geojson = decodedData.segment.map(segment => ({
            type: "Feature",
            properties: {
                tooltip: segment.identifier
            },
            geometry: {
                type: "LineString",
                coordinates: segment.geometry.point.map(point => [point.longitude, point.latitude])
            }
        }));

        L.geoJSON(geojson)
            .bindPopup(layer => layer.feature.properties.tooltip)
            .addTo(map);
    });
    // end:leaflet-get-protobuf.js


    // snippet:leaflet-add-base-map.js
    // Add the HERE base map. This can be replaced with the code of your preferred base map.
    const harpLeaflet = new L.HarpGL({
        theme: "https://unpkg.com/@here/harp-map-theme@0.12.0/resources/berlin_tilezen_night_reduced.json"
    }).addTo(map);
    const baseMapLayerConfig = await getLayerConfig(baseMapHRN, "omv-base-v2", settings);
    if (!baseMapLayerConfig) {
        throw new Error("Base map layer was not found");
    }
    const baseMapLayer = getLayerClient(baseMapLayerConfig.layerType, baseMapHRN, "omv-base-v2", settings);
    harpLeaflet.mapView.addDataSource(new harp.OmvDataSource({
        dataProvider: {
            async getTile(tileKey) {
                const request = new DataRequest()
                    .withPartitionId(`${mortonCodeFromQuadKey(tileKey)}`);
                const response = await baseMapLayer.getData(request);
                return response.arrayBuffer();
            },
            async connect() {},
            async ready() { return true; }
        },
        layerName: "omv-base-v2",
        getBearerToken: getToken,
        styleSetName: "tilezen"
    }));
    // end:leaflet-add-base-map.js
}

// snippet:leaflet-get-config-and-client.js
/**
 * Fetch the layer config and return an instance of a layer client.
 * 
 * @param hrn A catalog HRN.
 * @param layerId A layer ID.
 * @param settings Client settings.
 */
async function getLayerConfig(hrn, layerId, settings) {
    const catalogClient = new CatalogClient(HRN.fromString(hrn), settings);
    const config = await catalogClient.getCatalog(new CatalogRequest());
    return config.layers.find(item => item.id === layerId);
}

/**
 * Fetch the layer config and return an instance of a layer client.
 * 
 * @param layerType A layer type.
 * @param hrn A catalog HRN.
 * @param layerId A layer ID.
 * @param settings Client settings.
 */
function getLayerClient(layerType, hrn, layerId, settings) {
    switch (layerType) {
        case "versioned":
            return new VersionedLayerClient(hrn, layerId, settings);

        case "volatile":
            return new VolatileLayerClient(hrn, layerId, settings);

        default:
            throw new Error(`Layer type "${layerType}" is not supported yet.`);
    }
}
// end:leaflet-get-config-and-client.js

// snippet:leaflet-get-decoder-function.js
/**
 * Fetch and process schema archive to prepare a Protobuf decoder.
 * 
 * @param layer Instance of a layer client.
 */
async function getDecoder(hrn, settings) {
    // Get schema with protobuf files
    const artifactClient = new ArtifactClient(settings);
    const detailsRequest = new SchemaDetailsRequest()
        .withSchema(HRN.fromString(hrn));
    const details = await artifactClient.getSchemaDetails(detailsRequest);

    if (details === undefined || details.variants === undefined) {
        return;
    }

    const variant = details.variants.find(item => item.id === "ds");
    if (variant === undefined) {
        return;
    }

    const request = new SchemaRequest().withVariant(variant);
    const archive = await artifactClient.getSchema(request);

    // Load schema as a ZIP archive
    const zip = new JSZip();
    await zip.loadAsync(archive);

    // Read all .proto file and parse them by Protobuf
    const protobufRoot = new protobuf.Root();
    Object.keys(zip.files).forEach(async fileName => {
        if (!fileName.endsWith(".proto")) {
            return;
        }

        const file = await zip.file(fileName).async("text");
        protobuf.parse(file, protobufRoot, { keepCase: true })
    });

    // Extract the manifest data.
    const manifestFile = await zip.file("META-INF/layer.manifest.json").async("text");
    const manifest = JSON.parse(manifestFile);

    return protobufRoot.lookupType(manifest.main.message);
}
// end:leaflet-get-decoder-function.js


/**
 * Decode data.
 *
 * @param data Array buffer of encoded data.
 * @param decoder Decoder.
 */
function decode(data, decoder) {
    const uint8Array = new Uint8Array(data);
    const decodedMessage = decoder.decode(uint8Array);

    return decodedMessage.$type.toObject(decodedMessage, {
        defaults: true,
        longs: String,
        enums: String,
        bytes: String,
        json: true
    });
}

sdii / DI

http://localhost:5000/#dist/other_sdii_DI

This example demonstrates how to interact with the features of the Sensor Data Ingestion Interface (SDII) data source. You can highlight paths and road signs with the mouse pointer and filter out individual SDII messages.

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { DataInspector } from "@here/interactive-mapview-ui";
import {
    omvDataLayer,
    omvHostHrn,
    sdiiHostHrn,
    sdiiDataLayer,
    lookupServiceEnvironment
} from "../config";

new DataInspector(
    {
        mapView: {
            theme: "./resources/normal.reduced.night.json",
            decoder: { url: "./decoder.bundle.js" },
            defaultZoomLevel: 12
        },
        baseMap: {
            hrn: omvHostHrn,
            layer: omvDataLayer
        },
        widgets: {
            authForm: {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: sdiiHostHrn,
            layer: sdiiDataLayer
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);

sdii / DI / animated

http://localhost:5000/#dist/other_sdii_DI_animated

This example shows how you can use sdiiDataSource to animate road signs and paths.

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { DataInspector } from "@here/interactive-mapview-ui";
import {
    omvDataLayer,
    omvHostHrn,
    sdiiHostHrn,
    sdiiDataLayer,
    lookupServiceEnvironment
} from "../config";

new DataInspector(
    {
        mapView: {
            theme: "./resources/normal.reduced.night.json",
            decoder: { url: "./decoder.bundle.js" },
            defaultZoomLevel: 12
        },
        baseMap: {
            hrn: omvHostHrn,
            layer: omvDataLayer
        },
        widgets: {
            authForm: {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: sdiiHostHrn,
            layer: sdiiDataLayer,
            animationEnabled: true
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);

tilegrid

http://localhost:5000/#dist/other_tilegrid

This example of coverageDataSource displays a grid that represents Sensor Data Ingestion Interface (SDII) tiles with data. It displays the tileKey of a certain tile when clicking it.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { CoverageDataSource } from "@here/coverage-datasource";
import { DataProvider, MapControlHandler } from "@here/interactive-datasource-protocol";
import { geoJsonDataLayer, geoJsonHrn, lookupServiceEnvironment } from "../config";
import {
    InformationPanel,
    createBaseMapDataSource,
    initializeMapView,
    setupTileSelection,
    createTokenResolver
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapViewUtils } from "@here/harp-mapview";
import {
    calculateNormalizedDeviceCoordinates,
    getWidthAndHeightFromCanvas,
    MapControls
} from "@here/harp-map-controls";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);

// Create info panel
const infoPanel = new InformationPanel("Click on a map to see tile code");

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const dataProvider = new DataProvider({
    hrn: geoJsonHrn,
    layer: geoJsonDataLayer,
    getToken: getBearerToken.bind(tokenResolver),
    environment: lookupServiceEnvironment
});

// Tile grid
const coverageDataSource = new CoverageDataSource({
    dataProvider,
    // The grid will be rendered for specified tiles level
    levelWithData: 12
});

mapView.addDataSource(coverageDataSource);

setUpDataSourceEvents(canvas, coverageDataSource);

function setUpDataSourceEvents(
    mapCanvas: HTMLCanvasElement,
    coverage: CoverageDataSource
): void {
    // set up mouse hover event on a tile
    mapCanvas.addEventListener("mousemove", event => {
        const geoPoint = mapView.getGeoCoordinatesAt(event.pageX, event.pageY);
        if (geoPoint === null) {
            return;
        }

        const tileKey = coverage.getTilingScheme().getTileKey(geoPoint, 12);
        if (tileKey !== null) {
            coverage.highlightedTile = tileKey.mortonCode();
        }
    });

    // set up click event
    MapControlHandler.getInstance(mapView).addEventHandler("select", geoPoint => {
        const tileKey = coverage.getTilingScheme().getTileKey(geoPoint, 12);
        if (tileKey !== null) {
            infoPanel.innerText = "Selected tile: " + tileKey.mortonCode();

            // remove highlight from previous tile
            if (coverage.lastSelectedTile) {
                coverage.deselectTile(coverage.lastSelectedTile);
            }

            // highlight selected tile
            coverage.selectTile(tileKey.mortonCode());
        }
    }).addEventHandler("zoom", (geoPoint, keyModifier, event) => {
        if (event) {
            const currentZoomLevel = MapViewUtils.calculateZoomLevelFromDistance(
                mapView,
                mapView.camera.position.z
            );
            const targetZoom = currentZoomLevel + (keyModifier.ctrlKey ? -1 : 1);
            const { width, height } = getWidthAndHeightFromCanvas(mapView.canvas);
            const {x, y} = calculateNormalizedDeviceCoordinates(
                (event as MouseEvent).offsetX,
                (event as MouseEvent).offsetY,
                width,
                height
            );
            MapViewUtils.zoomOnTargetPosition(mapView, x, y, targetZoom);
        }
    });
}

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(11);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, coverageDataSource));

geojson / simple

http://localhost:5000/#dist/other_geojson_simple

This example uses GeoJsonDataSource to obtain data from a catalog with GeoJSON data. It visualizes GeoJSON data from a single tile.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { MapViewEventNames } from "@here/harp-mapview";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import { geoJsonDataLayer, geoJsonDataTile, geoJsonHrn, lookupServiceEnvironment } from "../config";
import {
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";
import { DataProvider } from "@here/interactive-datasource-protocol";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const dataProvider = new DataProvider({
    hrn: geoJsonHrn,
    layer: geoJsonDataLayer,
    getToken: getBearerToken.bind(tokenResolver),
    environment: lookupServiceEnvironment
});

// geoJSON Data source
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider
});

mapView.addEventListener(MapViewEventNames.DataSourceConnect, (event: any) => {
    if (event.dataSourceName === geoJsonDataSource.name) {
        geoJsonDataSource.selectTile(geoJsonDataTile);
    }
});

mapView.addDataSource(geoJsonDataSource);

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(13);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, geoJsonDataSource));

geojson / tooltip

http://localhost:5000/#dist/other_geojson_tooltip

This example displays user data for certain GeoJSON objects in the top-right corner of a map. When InteractiveIntersectionAgent triggers an EVENT_INTERSECTION_CHANGE event, a tooltip is extracted from the event data and is displayed in a specific DOM element.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import * as THREE from "three";
import { MapViewEventNames } from "@here/harp-mapview";
import {
    DataProvider,
    InteractiveIntersectionAgent,
    InteractiveIntersectionEvent
} from "@here/interactive-datasource-protocol";
import * as DataSourceProtocolUtils from "@here/interactive-datasource-protocol/lib/utils/Utils";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import { geoJsonDataLayer, geoJsonDataTile, geoJsonHrn, lookupServiceEnvironment } from "../config";
import {
    InformationPanel,
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);

// Create info panel
const infoPanelMsg = "Hover mouse over the rendered geometry";
const infoPanel = new InformationPanel(infoPanelMsg);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const dataProvider = new DataProvider({
    hrn: geoJsonHrn,
    layer: geoJsonDataLayer,
    getToken: getBearerToken.bind(tokenResolver),
    environment: lookupServiceEnvironment
});

// geoJSON Data source
const intersectionAgent = new InteractiveIntersectionAgent(mapView);
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider,
    intersectionAgent
});

mapView.addEventListener(MapViewEventNames.DataSourceConnect, () => {
    // Show geoJSON data on specific tile
    geoJsonDataSource.selectTile(geoJsonDataTile);
});

intersectionAgent.addEventListener(
    InteractiveIntersectionAgent.EVENT_INTERSECTION_CHANGE,
    (event: THREE.Event) => {
        const intersectionEvent = event as InteractiveIntersectionEvent;
        let intersection = intersectionEvent.intersection;
        let tooltipContent: string | undefined;

        if (intersectionEvent.intersected && intersection) {
            let segmentIndex: number | undefined;

            if (typeof (intersection.index) === "number") {
                segmentIndex = intersection.index;
            } else if (typeof (intersection.faceIndex) === "number") {
                segmentIndex = intersection.faceIndex;
            }

            if (segmentIndex) {
                const tooltips = intersection.object.userData
                    .tooltipRanges as Map;

                tooltipContent = DataSourceProtocolUtils.getValueInRange(
                    tooltips,
                    segmentIndex
                );
            }
        }

        infoPanel.innerHTML = (intersectionEvent.intersected && tooltipContent !== undefined)
            ? tooltipContent
            : infoPanelMsg;
    }
);

mapView.addDataSource(geoJsonDataSource);

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(13);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, geoJsonDataSource));

geojson / without / dataservice

http://localhost:5000/#dist/other_geojson_without_dataservice

This example visualizes the geometry of a hard-coded GeoJSON object without connecting to the OLP Data API.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { MapViewEventNames } from "@here/harp-mapview";
import { InteractiveIntersectionAgent } from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";
import { geoJsonData, geoJsonMapCenter } from "../config";
import { GeoCoordinates } from "@here/harp-geoutils";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);
mapView.geoCenter = new GeoCoordinates(geoJsonMapCenter.latitude, geoJsonMapCenter.longitude);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

// geoJSON Data source
const geoJsonDataSource = new GeoJsonDataSource({
    intersectionAgent: new InteractiveIntersectionAgent(mapView)
});

mapView.addDataSource(geoJsonDataSource);

/**
 * Show geoJSON data from other resource than DataStore
 * (e.g. read from the file, direct geoJSON object).
 */
mapView.addEventListener(MapViewEventNames.DataSourceConnect, (event: any) => {
    if (event.dataSourceName === geoJsonDataSource.name) {
        geoJsonDataSource.renderGeoJson(geoJsonData);
    }
});

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(17);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, geoJsonDataSource));

geojson / DI / plugin

http://localhost:5000/#dist/other_geojson_DI_plugin

This example visualizes speed limits using an external GeoJSON renderer plugin. The plugin uses SegmentAnchorGeometryDataProvider to retrieve road geometries and map speed limit data to them.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { MapViewEventNames } from "@here/harp-mapview";
import { DataInspector } from "@here/interactive-mapview-ui";
import { lookupServiceEnvironment, ribHostHrn, speedLimitTiles } from "../config";

const dataInspector = new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 11,
            theme: "resources/normal.reduced.night.json",
            decoder: {
                url: "./decoder.bundle.js"
            }
        },
        widgets: {
            authForm: {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: ribHostHrn,
            layer: "navigation-attributes",
            externalRendererPluginName: "renderer.plugin.template"
        },
        enableCoverage: true
    }
);

if (dataInspector.mapView === undefined) {
    throw new Error("MapView was not initialized.");
}

dataInspector.mapView.addEventListener(MapViewEventNames.DataSourceConnect, (event: any) => {
    if (dataInspector.interactiveDataSource
        && event.dataSourceName === dataInspector.interactiveDataSource.name
    ) {
        speedLimitTiles.forEach(tileCode =>
            dataInspector.tileControlHandler.selectTile(tileCode, true));
    }
});

geojson / properties

http://localhost:5000/#dist/other_geojson_properties

This example visualizes such custom GeoJSON feature properties as style.color, style.fill, style.width, properties.tooltip, as well as other MapBox styles.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { GeoCoordinates } from "@here/harp-geoutils";
import { MapViewEventNames } from "@here/harp-mapview";
import { InteractiveIntersectionAgent } from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    createBaseMapDataSource,
    createTokenResolver,
    InformationPanel,
    initializeMapView,
    setupTileSelection
} from "./common";
import { geoJsonProperties, geoJsonPropertiesCenter } from "../config";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";
import { installInfoWidgets } from "@here/interactive-mapview-ui/lib/Utils";
import { GeoJsonInfoPanel } from "@here/interactive-mapview-ui";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);
mapView.geoCenter = new GeoCoordinates(
    geoJsonPropertiesCenter.latitude,
    geoJsonPropertiesCenter.longitude
);

// Create info panel
const infoPanelMsg = "Hover mouse over the rendered geometry";
new InformationPanel(infoPanelMsg);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

// GeoJSON Data source
const geoJsonDataSource = new GeoJsonDataSource({
    intersectionAgent: new InteractiveIntersectionAgent(mapView)
});

mapView.addDataSource(geoJsonDataSource);

installInfoWidgets(GeoJsonInfoPanel, geoJsonDataSource, document.body, "geojson-info-panel");

// Show geoJSON data from other resource than DataStore
// (e.g. read from the file, direct geoJSON object)
mapView.addEventListener(MapViewEventNames.DataSourceConnect, (event: any) => {
    if (event.dataSourceName === geoJsonDataSource.name) {
        geoJsonDataSource.renderGeoJson(geoJsonProperties);
    }
});

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(17);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, geoJsonDataSource));

geojson / DI / icons

http://localhost:5000/#dist/other_geojson_DI_icons

This example demonstrates how you can add SVG icons to geometry features in your custom renderer plugins.

Example Source Code


/*
 * Copyright (C) 2019-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { MapViewEventNames } from "@here/harp-mapview";
import { DataInspector } from "@here/interactive-mapview-ui";
import {
    lookupServiceEnvironment,
    ribHostHrn,
    ribTopologyLayer,
    verity_geojson_host_icons_tile,
    verity_geojson_host_icons_plugin
} from "../config";


const dataInspector = new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 10,
            theme: "resources/normal.reduced.night.json",
            decoder: {
                url: "./decoder.bundle.js"
            }
        },
        widgets: {
            authForm: {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            },
            decodedPanel: {
                enabled: false
            }
        },
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: ribHostHrn,
            layer: ribTopologyLayer,
            externalRendererPluginName: verity_geojson_host_icons_plugin,
            preferRendererPlugin: false
        },
        enableCoverage: false
    }
);

if (dataInspector.mapView === undefined) {
    throw new Error("MapView was not initialized.");
}

dataInspector.mapView.addEventListener(MapViewEventNames.DataSourceConnect, (event: any) => {
    const dataSource = dataInspector.interactiveDataSource;
    if (dataSource && event.dataSourceName === dataSource.name) {
        dataSource.selectTile(verity_geojson_host_icons_tile);
    }
});

geojson / bounding / box

http://localhost:5000/#dist/other_geojson_bounding_box

This example automatically adjusts a map's zoom and position to fit a specific GeoJSON object. You can obtain the bounding box of the rendered GeoJSON object in the GeoJsonDataSource.EVENT_TILE_DECODED event. This example provides sample code to calculate the camera's position of the mapView allowing you to fit an object in the map view.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { GeoCoordinates } from "@here/harp-geoutils";
import { MapViewEventNames } from "@here/harp-mapview";
import { InteractiveIntersectionAgent } from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource, GeoJsonDataSourceEvent } from "@here/olp-geojson-datasource";
import {
    createBaseMapDataSource,
    initializeMapView,
    setupTileSelection,
    createTokenResolver
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import * as Utils from "@here/interactive-mapview-ui/lib/Utils";
import { MapControls } from "@here/harp-map-controls";
import { geoJsonData } from "../config";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);
// Initially position map off desired location.
mapView.geoCenter = new GeoCoordinates(10, 10);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

// GeoJSON Data source
const geoJsonDataSource = new GeoJsonDataSource({
    intersectionAgent: new InteractiveIntersectionAgent(mapView)
});

mapView.addDataSource(geoJsonDataSource);

/**
 * Show geoJSON data from other resource than DataStore
 * (e.g. read from the file, direct geoJSON object).
 */
mapView.addEventListener(MapViewEventNames.DataSourceConnect, (event: any) => {
    if (event.dataSourceName === geoJsonDataSource.name) {
        geoJsonDataSource.renderGeoJson(geoJsonData);
    }
});

// Map centering by bounding box
geoJsonDataSource.addEventListener(
    GeoJsonDataSource.EVENT_BEFORE_TILE_RENDERED,
    (event: GeoJsonDataSourceEvent) => {
        const boundingBox = event.boundingBox;
        if (boundingBox === undefined) {
            return;
        }

        Utils.fitMapViewToWorldBoundingBox(mapView, boundingBox, mapControls, 50);
    }
);

const mapControls = new MapControls(mapView);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, geoJsonDataSource));

geojson / tilegrid

http://localhost:5000/#dist/other_geojson_tilegrid

This example demonstrates how to couple the GeoJSON data source with the coverage data source to visualize those tiles that have data. GeoJsonDataSource obtains data from a catalog with GeoJSON data, and coverageDataSource is connected to the same catalog, so that they represent the same data.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { CoverageDataSource } from "@here/coverage-datasource";
import {
    DataProvider,
    InteractiveIntersectionAgent
} from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    geoJsonDataLayer,
    geoJsonHrn,
    geoJsonLevelWithData,
    lookupServiceEnvironment
} from "../config";
import {
    InformationPanel,
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;

const mapView = initializeMapView(canvas);

// Create info panel
new InformationPanel("Click on a map to load geoJSON data from DataStore");

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const dataProvider = new DataProvider({
    hrn: geoJsonHrn,
    layer: geoJsonDataLayer,
    getToken: getBearerToken.bind(tokenResolver),
    environment: lookupServiceEnvironment
});

// Tile grid
const coverageDataSource = new CoverageDataSource({
    dataProvider,
    // The grid will be rendered for specified tiles level
    levelWithData: geoJsonLevelWithData
});
mapView.addDataSource(coverageDataSource);

// geoJSON Data source
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider,
    intersectionAgent: new InteractiveIntersectionAgent(mapView),
    levelWithData: geoJsonLevelWithData
});

mapView.addDataSource(geoJsonDataSource);

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(12);
setupTileSelection(
    mapView,
    new TileControlHandler(mapView, mapControls, geoJsonDataSource, coverageDataSource)
);

geojson / events

http://localhost:5000/#dist/other_geojson_events

This example demonstrates how to subscribe to various events of the GeoJsonDataSource. After the tiles have been loaded, you can see the events that are triggered by long-clicking any tile. It adds event listeners to the EVENT_TILE_GET, EVENT_TILE_DECODED, EVENT_BEFORE_TILE_DECODE, EVENT_TILE_SELECT, and EVENT_TILE_DESELECT events.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { CoverageDataSource } from "@here/coverage-datasource";
import { DataProvider, InteractiveIntersectionAgent } from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    geoJsonDataLayer,
    geoJsonHrn,
    geoJsonLevelWithData,
    lookupServiceEnvironment,
} from "../config";
import {
    createBaseMapDataSource,
    InformationPanel,
    initializeMapView,
    setupTileSelection,
    createTokenResolver
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);

// Create info panel
const infoPanelMsg = `Click on a map to see eventsEvents:`;
const infoPanel = new InformationPanel(infoPanelMsg, true);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const dataProvider = new DataProvider({
    hrn: geoJsonHrn,
    getToken: getBearerToken.bind(tokenResolver),
    layer: geoJsonDataLayer,
    environment: lookupServiceEnvironment
});

// Tile grid
const coverageDataSource = new CoverageDataSource({
    dataProvider,
    // The grid will be rendered for specified tiles level
    levelWithData: geoJsonLevelWithData
});
mapView.addDataSource(coverageDataSource);

// geoJSON Data source
const intersectionAgent = new InteractiveIntersectionAgent(mapView);
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider,
    intersectionAgent,
    levelWithData: geoJsonLevelWithData
});

mapView.addDataSource(geoJsonDataSource);

// all events of GeoJsonDataSource
geoJsonDataSource.addEventListener(GeoJsonDataSource.EVENT_TILE_GET, () => {
    infoPanel.element.innerText += GeoJsonDataSource.EVENT_TILE_GET + "\n";
});

geoJsonDataSource.addEventListener(GeoJsonDataSource.EVENT_TILE_DECODED, () => {
    infoPanel.element.innerText += GeoJsonDataSource.EVENT_TILE_DECODED + "\n";
});

geoJsonDataSource.addEventListener(GeoJsonDataSource.EVENT_BEFORE_TILE_DECODE, () => {
    infoPanel.element.innerText += GeoJsonDataSource.EVENT_BEFORE_TILE_DECODE + "\n";
});

geoJsonDataSource.addEventListener(GeoJsonDataSource.EVENT_BEFORE_TILE_RENDERED, () => {
    infoPanel.element.innerText += GeoJsonDataSource.EVENT_BEFORE_TILE_RENDERED + "\n";
});

geoJsonDataSource.addEventListener(GeoJsonDataSource.EVENT_TILE_SELECT, () => {
    infoPanel.element.innerText += GeoJsonDataSource.EVENT_TILE_SELECT + "\n";
});

geoJsonDataSource.addEventListener(GeoJsonDataSource.EVENT_TILE_DESELECT, () => {
    infoPanel.element.innerText += GeoJsonDataSource.EVENT_TILE_DESELECT + "\n";
});

const mapControls = new MapControls(mapView);
mapControls.setZoomLevel(12);
setupTileSelection(
    mapView,
    new TileControlHandler(mapView, mapControls, geoJsonDataSource, coverageDataSource)
);

geojson / contenttype / versioned

http://localhost:5000/#dist/other_geojson_contenttype_versioned

This example shows how to load GeoJSON data from a versioned layer of a catalog.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */


import { CoverageDataSource } from "@here/coverage-datasource";
import { DataProvider, InteractiveIntersectionAgent } from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    geoJsonContentTypeHrn,
    geoJsonContentTypeLayerVersioned,
    geoJsonContentTypeLevelWithData,
    lookupServiceEnvironment
} from "../config";
import {
    createBaseMapDataSource,
    createTokenResolver,
    InformationPanel,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);

// Create info panel
const infoPanelMsg = "Click on a tile to load GeoJSON data from versioned layer";
new InformationPanel(infoPanelMsg);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const dataProvider = new DataProvider({
    hrn: geoJsonContentTypeHrn,
    getToken: getBearerToken.bind(tokenResolver),
    layer: geoJsonContentTypeLayerVersioned,
    environment: lookupServiceEnvironment
});

// GeoJSON Data Source
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider,
    levelWithData: geoJsonContentTypeLevelWithData,
    schemaProviderOptions: {
        enabled: false
    },
    intersectionAgent: new InteractiveIntersectionAgent(mapView)
});

mapView.addDataSource(geoJsonDataSource);

// Tile grid
const coverageDataSource = new CoverageDataSource({
    dataProvider,
    // The grid will be rendered for specified tiles level
    levelWithData: geoJsonContentTypeLevelWithData,
    schemaProviderOptions: {
        enabled: false
    }
});
mapView.addDataSource(coverageDataSource);

const mapControls = new MapControls(mapView);
mapControls.setZoomLevel(13);
setupTileSelection(
    mapView,
    new TileControlHandler(mapView, mapControls, geoJsonDataSource, coverageDataSource)
);

interactive / zoomControls

http://localhost:5000/#dist/other_interactive_zoomControls

This example showcases a widget for adjusting a map's zoom level. To use it, you should create an instance of ZoomLevelWidget and pass the container DOM element and a mapView instance to its constructor.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { ZoomLevelWidget, ZoomLevelWidgetEvents } from "@here/interactive-mapview-ui";
import {
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";
import { MapViewEventNames } from "@here/harp-mapview";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
const mapView = initializeMapView(canvas);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

// Zoom level widget embed starts here

const uiContainer = document.getElementById("ui-container");
if (uiContainer === null) {
    throw new Error("Element 'ui-container' not found in document");
}

// An instance of `MapControls` is needed to control zoom level of `MapView`.
const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(13);

// Create a UI widget which visualizes current zoom and provides buttons to zoom in/out.
const zoomLevelWidget = new ZoomLevelWidget(
    {},
    uiContainer,
    { zoomLevel: mapView.zoomLevel }
);

// Handler for zoom in button.
zoomLevelWidget.addEventListener(
    ZoomLevelWidgetEvents.ZOOM_IN,
    () => mapControls.setZoomLevel(mapControls.zoomLevelTargeted + 1)
);

// Handler for zoom out button.
zoomLevelWidget.addEventListener(
    ZoomLevelWidgetEvents.ZOOM_OUT,
    () => mapControls.setZoomLevel(mapControls.zoomLevelTargeted - 1)
);

// Update zoom widget with current zoom level.
mapView.addEventListener(MapViewEventNames.Render,
    () => {
        zoomLevelWidget.setState({
            zoomLevel: mapView.zoomLevel,
            zoomInDisabled: mapView.zoomLevel >= mapView.maxZoomLevel,
            zoomOutDisabled: mapView.zoomLevel 
interactive / statsPanel

http://localhost:5000/#dist/other_interactive_statsPanel

This example demonstrates InteractiveStatsPanel – a collapsible widget that displays statistics about decoded tiles.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { MapViewEventNames } from "@here/harp-mapview";
import { InteractiveStatsPanel, PanelDisplayMode } from "@here/interactive-mapview-ui";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import { geoJsonDataLayer, geoJsonDataTile, geoJsonHrn, lookupServiceEnvironment } from "../config";
import {
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection,
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";
import { DataProvider } from "@here/interactive-datasource-protocol";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const dataProvider = new DataProvider({
    hrn: geoJsonHrn,
    layer: geoJsonDataLayer,
    getToken: getBearerToken.bind(tokenResolver),
    environment: lookupServiceEnvironment
});

// geoJSON Data source
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider
});

// Stats panel embed starts here.

const interactiveStatsPanel = new InteractiveStatsPanel({
    elementId: "interactive-stats-panel",
    initialDisplayMode: PanelDisplayMode.Expanded
});

const uiContainer = document.getElementById("ui-container");
if (uiContainer === null) {
    throw new Error("Element 'ui-container' not found in document");
}

uiContainer.appendChild(interactiveStatsPanel.element);

interactiveStatsPanel.addDatasource(geoJsonDataSource);

// Stats panel embed ends here.

mapView.addEventListener(MapViewEventNames.DataSourceConnect, () => {
    // Show geoJSON data on specific tile
    geoJsonDataSource.selectTile(geoJsonDataTile);
});

mapView.addDataSource(geoJsonDataSource);

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(13);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, geoJsonDataSource));

interactive / infoPanel

http://localhost:5000/#dist/other_interactive_infoPanel

This example displays a popup info panel when there is a GeoJSON feature under the mouse pointer.

To display information about the GeoJSON object under the mouse pointer, you should create an instance of GeoJsonInfoPanel and connect it to intersectionAgent and the mapView used in the data source. It will listen to events of InteractiveIntersectionAgent and create a popup with the tooltip data that is available for the current object.

GeoJsonInfoPanel used in this example is a subclass of a more generic InteractiveInfoPanel. It features the same functionality but positions the popup more precisely over GeoJSON objects.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { MapViewEventNames } from "@here/harp-mapview";
import { DataProvider, InteractiveIntersectionAgent } from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import { geoJsonDataLayer, geoJsonDataTile, geoJsonHrn, lookupServiceEnvironment } from "../config";
import {
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";
import { installInfoWidgets } from "@here/interactive-mapview-ui/lib/Utils";
import { GeoJsonInfoPanel } from "@here/interactive-mapview-ui";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);

const tokenResolver = createTokenResolver(mapView);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const dataProvider = new DataProvider({
    hrn: geoJsonHrn,
    layer: geoJsonDataLayer,
    getToken: getBearerToken.bind(tokenResolver),
    environment: lookupServiceEnvironment
});

// geoJSON Data source
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider,
    intersectionAgent: new InteractiveIntersectionAgent(mapView)
});

mapView.addEventListener(MapViewEventNames.DataSourceConnect, () => {
    // Show geoJSON data on specific tile
    geoJsonDataSource.selectTile(geoJsonDataTile);
});

// Info panel embed starts here.

const uiContainer = document.getElementById("ui-container");

if (uiContainer === null) {
    throw new Error("Element 'ui-container' not found in document");
}

mapView.addDataSource(geoJsonDataSource);

installInfoWidgets(GeoJsonInfoPanel, geoJsonDataSource, uiContainer);

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(13);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, geoJsonDataSource));

interactive / DI / default

http://localhost:5000/#dist/other_interactive_DI_default

This example creates an instance of DataInspector with default options. It creates a mapView within an HTML element of fixed size and creates a GeoJSON data source connected to the OLP Data API.

The toolbar features the following elements:

  • A button to toggle the visibility of the Instrumental Panel with the filters widget
  • A button to show or hide the Decoded Panel
  • A version picker to change the version of the layer
  • A search form to find geo coordinates or partitions
  • A full-screen button to expand the Data Inspector window to fill in the available page size.
The information about decoded partitions can be viewed in the panel at the right-hand side, collapsed by default.

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { DataInspector } from "@here/interactive-mapview-ui";
import { geoJsonDataLayer, geoJsonHostHrn, lookupServiceEnvironment } from "../config";

const dataInspector = new DataInspector(
    {
        mapView: {
            theme: "resources/normal.reduced.night.json",
            decoder: {
                url: "./decoder.bundle.js"
            }
        },
        widgets: {
            authForm: {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: geoJsonHostHrn,
            layer: geoJsonDataLayer
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);

interactive / DI / minimal

http://localhost:5000/#dist/other_interactive_DI_minimal

This example is similar to the interactive / DI / full example, but with almost all interactive controls disabled. For all possible configuration options for UI elements, see the source code of the interactive / DI / full example.

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { DataInspector } from "@here/interactive-mapview-ui";
import { geoJsonDataLayer, geoJsonHostHrn, lookupServiceEnvironment } from "../config";

const hostContainer = document.getElementById("map-here") as HTMLElement;
hostContainer.classList.add("full-screen");

const dataInspector = new DataInspector(
    {
        mapView: {
            theme: "resources/normal.reduced.night.json",
            decoder: {
                url: "./decoder.bundle.js"
            }
        },
        widgets: {
            zoomLevel: false,
            statusBar: false,
            decodedPanel: {
                enabled: false
            },
            authForm: {
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        toolbar: {
            enabled: false
        },
        lookupServiceEnvironment
    },
    hostContainer,
    {
        interactiveDataSource: {
            hrn: geoJsonHostHrn,
            layer: geoJsonDataLayer
        },
        enableCoverage: true
    }
);

interactive / filtering

http://localhost:5000/#dist/other_interactive_filtering

This example demonstrates filtering options for certain features from InteractiveDataSource. It has a set of features with two types of properties: color and shape. You can toggle the feature visibility with both property types. This demo has a sample DemoDataSource that renders the sample feature geometry with certain properties. InteractiveFilteringControl is created to filter these features.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

/** @module @here/olp-examples **//***/

import { MapViewEventNames } from "@here/harp-mapview";
import {
    AccessTokenResolver,
    UserAuthForm
} from "@here/interactive-mapview-ui";
import { ControlPanel } from "@here/interactive-mapview-ui/lib/ControlPanel";
import {
    addConnectionListener,
    createBaseMapDataSource,
    InteractiveFilteringControl,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { DemoDataSource } from "./datasources/demoDataSource/demoDataSource";
import { MapControls } from "@here/harp-map-controls";
import { lookupServiceEnvironment, demoMapCenter, demoGeoJson } from "../config";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);
mapView.geoCenter = demoMapCenter;

// Create authentication form
const authForm = new UserAuthForm({
    tokenForm: false,
    accessKeyForm: true,
    localAuthForm: true
});

const tokenResolver = new AccessTokenResolver(authForm, lookupServiceEnvironment);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

const controlPanel = new ControlPanel(
    { showExpandButton: true },
    document.body
);
controlPanel.addSection({
    widget: authForm.element,
    name: "Authorization"
});
controlPanel.show();

addConnectionListener(authForm, mapView);

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const demoDataSource = new DemoDataSource({});
mapView.addDataSource(demoDataSource);

mapView.addEventListener(MapViewEventNames.DataSourceConnect, (event: any) => {
    if (event.dataSourceName === demoDataSource.name) {
        demoDataSource.renderDemo(demoGeoJson);
    }
});

let filteringControlUpdates = false;

const interactiveFilteringControl = new InteractiveFilteringControl({
    elementId: "my-interactive-filtering"
}, {
        visible: true,
        featureGroups: [
            {
                switchHandler: groupSwitchHandler,
                state: true,
                collapsed: false,
                featureType: "figure",
                name: "type",
                title: "Color filters group toggle",
                filters: [
                    {
                        switchHandler: filterSwitchHandler,
                        state: true,
                        featureType: "figure",
                        name: 1,
                        title: "Red type"
                    },
                    {
                        switchHandler: filterSwitchHandler,
                        state: true,
                        featureType: "figure",
                        name: 2,
                        title: "Green type"
                    },
                    {
                        switchHandler: filterSwitchHandler,
                        state: true,
                        featureType: "figure",
                        name: 3,
                        title: "Blue type"
                    }
                ]
            },
            {
                switchHandler: groupSwitchHandler,
                state: true,
                collapsed: false,
                featureType: "figure",
                name: "shape",
                title: "Shapes filter group toggle",
                filters: [
                    {
                        switchHandler: filterSwitchHandler,
                        state: true,
                        featureType: "figure",
                        name: "triangle",
                        title: "Triangle"
                    },
                    {
                        switchHandler: filterSwitchHandler,
                        state: true,
                        featureType: "figure",
                        name: "freeForm",
                        title: "Free form"
                    }
                ]
            }
        ]
    });

function groupSwitchHandler(
    state: boolean,
    type?: string,
    name?: string | number,
    attr?: string
): void {
    if (
        filteringControlUpdates
        && interactiveFilteringControl !== undefined
        && interactiveFilteringControl.state.featureGroups !== undefined
    ) {
        // Find current group
        const featureGroup = interactiveFilteringControl.state.featureGroups.find((group) => {
            return (group.featureType === type && group.name === name);
        });

        // Toggle each filter of the group
        if (featureGroup !== undefined) {
            const filters = featureGroup.filters;
            if (filters !== undefined) {
                filters.forEach(filter => {
                    const checkboxId = "filter-" + filter.featureType + "-" + filter.name;

                    if (state !== filter.state) {
                        toggleCheckbox(checkboxId);
                    }
                });
            }
        }
    }
}

function filterSwitchHandler(
    state: boolean,
    type?: string,
    name?: string | number,
    attr?: string
): void {
    if (!type || !name) {
        return;
    }

    const toApply = filteringControlUpdates && !interactiveFilteringControl.disabled;
    demoDataSource.addFeatureFilter({
        exclude: !state,
        feature: type,
        value: name
    }, toApply);

    if (filteringControlUpdates &&
        interactiveFilteringControl !== undefined &&
        interactiveFilteringControl.state.featureGroups !== undefined) {

        const featureGroup = interactiveFilteringControl.state.featureGroups.find((group) => {
            if (group.filters === undefined) {
                return false;
            }

            const filterState = group.filters[0].state;
            return (
                group.featureType === type &&
                group.filters.find((filter) => filter.name === name) !== undefined &&
                group.filters.every((filter) => filter.state === filterState)
            );
        });

        if (featureGroup) {
            const checkboxId = `filter-${featureGroup.featureType}-${featureGroup.name}`;
            if (state !== featureGroup.state) {
                toggleCheckbox(checkboxId);
            }
        }
    }
}

/**
 * Toggle checkbox.
 *
 * @param checkboxId ID of checkbox element.
 */
function toggleCheckbox(checkboxId: string) {
    const uiContainer = document.getElementById(checkboxId);
    if (uiContainer) {
        uiContainer.click();
    }
}

filteringControlUpdates = true;

controlPanel.addSection({
    widget: interactiveFilteringControl.element,
    name: "Filters"
});

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(16);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, demoDataSource));

oauth

http://localhost:5000/#dist/other_oauth

This example demonstrates how to use two authentication options – repository and platform credentials. For more information, see the Get Your Credentials chapter.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { CoverageDataSource } from "@here/coverage-datasource";
import { AccessTokenResolver, UserAuthForm } from "@here/interactive-mapview-ui";
import { ControlPanel } from "@here/interactive-mapview-ui/lib/ControlPanel";
import { geoJsonHrn, geoJsonDataLayer, geoJsonLevelWithData } from "../config";
import {
    InformationPanel,
    addConnectionListener,
    createBaseMapDataSource,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";
import { lookupServiceEnvironment } from "../config";
import { DataProvider } from "@here/interactive-datasource-protocol";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
// For the full map initialization code see sdii/simple example
const mapView = initializeMapView(canvas);

// Create info panel
//tslint:disable:max-line-length
const infoContent = `Auth form provides two types of authentication:
1. Access Credentials
Enter access key id and access key secret and click "Submit". Once the token
is expired a new one will be requested automatically without interruption and/or
waiting for the user input.
2. Local Auth
Try this method on your local olp-examples instance: copy contents of
config.json.example (without how-to comment) into config.json and replace
required fields values with your access key credentials.

Note: Use access key credentials provided by platform.here.com`;
//tslint:enable

const infoPanel = new InformationPanel(infoContent, true);

// Create authentication form with all authentication types enabled
const authForm = new UserAuthForm({
    tokenForm: false,
    accessKeyForm: true,
    localAuthForm: true
});

const controlPanel = new ControlPanel({}, document.body);
controlPanel.addSection({
    widget: authForm.element,
    name: "Authorization"
});
controlPanel.show();

const tokenResolver = new AccessTokenResolver(authForm, lookupServiceEnvironment);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

addConnectionListener(authForm, mapView);

// Base map
mapView.addDataSource(createBaseMapDataSource(getBearerToken.bind(tokenResolver)));

const dataProvider = new DataProvider({
    hrn: geoJsonHrn,
    layer: geoJsonDataLayer,
    getToken: getBearerToken.bind(tokenResolver),
    environment: lookupServiceEnvironment
});

// Tile grid
const coverageDataSource = new CoverageDataSource({
    dataProvider,
    // The grid will be rendered for specified tiles level
    levelWithData: geoJsonLevelWithData
});
mapView.addDataSource(coverageDataSource);

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(12);
setupTileSelection(mapView, new TileControlHandler(mapView, mapControls, coverageDataSource));

rib / multilayer

http://localhost:5000/#dist/other_rib_multilayer

This example uses RibDataSource to obtain data from a catalog with the HERE Map Content Data. It visualizes data from all supported layers simultaneously. Also, this example shows how to filter certain objects.

For example, you can filter for the following objects:

  • Segments and nodes from the topology layer
  • Categories of objects from the road topology and geometry
  • Layers with building footprints

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { CoverageDataSource } from "@here/coverage-datasource";
import { InteractiveIntersectionAgent } from "@here/interactive-datasource-protocol";
import { AccessTokenResolver, UserAuthForm, InfoPanel } from "@here/interactive-mapview-ui";
import { ControlPanel } from "@here/interactive-mapview-ui/lib/ControlPanel";
import { RibControls } from "@here/interactive-mapview-ui/lib/RibControls";
import { RibDataProvider, RibDataSource } from "@here/rib-datasource";
import {
    lookupServiceEnvironment,
    ribBuildingLayer,
    ribCartoLayer,
    ribHrn,
    ribLevelWithData,
    ribTopologyLayer
} from "../config";
import {
    addConnectionListener,
    InformationPanel,
    initializeMapView,
    setupTileSelection
} from "./common";
import TileControlHandler from "@here/interactive-mapview-ui/lib/data-inspector/TileControlHandler";
import { MapControls } from "@here/harp-map-controls";
import { installInfoWidgets } from "@here/interactive-mapview-ui/lib/Utils";

const canvas = document.getElementById("mapCanvas") as HTMLCanvasElement;
const mapView = initializeMapView(canvas);

// Create info panel
//tslint:disable-next-line:max-line-length
const infoPanelMsg = `Click on a map to load RIB data from '${ribTopologyLayer}', '${ribCartoLayer}' and '${ribBuildingLayer}' layers simultaneously.`;
new InformationPanel(infoPanelMsg);

// Create authentication form
const authForm = new UserAuthForm({
    tokenForm: false,
    accessKeyForm: true,
    localAuthForm: true
});

const tokenResolver = new AccessTokenResolver(authForm, lookupServiceEnvironment);
const getBearerToken = tokenResolver.getBearerToken  as () => Promise;

const controlPanel = new ControlPanel({}, document.body);
controlPanel.addSection({
    widget: authForm.element,
    name: "Authorization"
});
controlPanel.show();

addConnectionListener(authForm, mapView);

const dataProvider = new RibDataProvider(
    {
        hrn: ribHrn,
        layer: ribTopologyLayer,
        getToken: getBearerToken.bind(tokenResolver),
        environment: lookupServiceEnvironment
    },
    [ribCartoLayer, ribBuildingLayer],
);

// Tile grid
const coverageDataSource = new CoverageDataSource({
    dataProvider,
    levelWithData: ribLevelWithData
});
mapView.addDataSource(coverageDataSource);

// RIB data source
const ribDataSource = new RibDataSource({
    dataProvider,
    levelWithData: ribLevelWithData,
    intersectionAgent: new InteractiveIntersectionAgent(mapView)
});

mapView.addDataSource(ribDataSource);

// set up mouse hover event on a tile
canvas.addEventListener("mousemove", event => {
    const geoPoint = mapView.getGeoCoordinatesAt(event.pageX, event.pageY);
    if (geoPoint === null) {
        return;
    }

    const tileKey = coverageDataSource.getTilingScheme().getTileKey(geoPoint, ribLevelWithData);
    if (tileKey !== null) {
        coverageDataSource.highlightedTile = tileKey.mortonCode();
    }
});

const mapControls = new MapControls(mapView);
mapControls.zoomLevelDeltaOnDoubleClick = 0;
mapControls.setZoomLevel(12);
setupTileSelection(
    mapView,
    new TileControlHandler(mapView, mapControls, ribDataSource, coverageDataSource)
);

// create filter widget
const filtersContainer = document.createElement("div");

const ribControls = new RibControls({
    elementId: "rib-controls-widget",
    dataSource: ribDataSource,
    disableRibFeatureCallback: (isDisabled: boolean, eventType?: number | string) => {
        if (typeof eventType !== "string") {
            return;
        }

        const toApply = true;
        ribDataSource.addFeatureFilter({
            exclude: isDisabled,
            feature: "layer",
            value: eventType
        }, toApply);
    },
}, filtersContainer);
controlPanel.addDataControl(ribControls);

const uiContainer = document.getElementById("ui-container");
if (uiContainer === null) {
    throw new Error("Element 'ui-container' not found in document");
}

installInfoWidgets(InfoPanel, ribDataSource, uiContainer);

rib / DI / building

http://localhost:5000/#dist/other_rib_DI_building

This example creates an instance of DataInspector with the HERE Map Content Data source connected to the OLP Data API. It demonstrates all DataInspector features based on the data from the Building Footprints layer provided by the HERE Map Content data source.

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { DataInspector } from "@here/interactive-mapview-ui";
import { ribBuildingLayer, ribHostHrn, lookupServiceEnvironment } from "../config";

new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 13,
            theme: "resources/normal.reduced.night.json",
            decoder: {
                url: "./decoder.bundle.js"
            }
        },
        widgets: {
            authForm: {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: ribHostHrn,
            layer: ribBuildingLayer
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);

rib / DI / carto

http://localhost:5000/#dist/other_rib_DI_carto

This example is similar to the rib / DI / building example but renders the data from the cartography layer.

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { DataInspector } from "@here/interactive-mapview-ui";
import { ribCartoLayer, ribHostHrn, lookupServiceEnvironment } from "../config";

new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 13,
            theme: "resources/normal.reduced.night.json",
            decoder: {
                url: "./decoder.bundle.js"
            }
        },
        widgets: {
            authForm: {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: ribHostHrn,
            layer: ribCartoLayer
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);

rib / DI / topology

http://localhost:5000/#dist/other_rib_DI_topology

This example is similar to the rib / DI / building example but renders the data from the road topology and geometry layers.

Example Source Code


/*
 * Copyright (C) 2018-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { DataInspector } from "@here/interactive-mapview-ui";
import { ribHostHrn, ribTopologyLayer, lookupServiceEnvironment } from "../config";

new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 13,
            theme: "resources/normal.reduced.night.json",
            decoder: {
                url: "./decoder.bundle.js"
            }
        },
        widgets: {
            authForm: {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: ribHostHrn,
            layer: ribTopologyLayer
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);

geometrydataprovider / speedlimits / DI

http://localhost:5000/#dist/other_geometrydataprovider_speedlimits_DI

This example showcases how to create an instance of custom InteractiveDataSource and dynamically add it to a DataInspector instance. Custom SpeedLimitsDataSource visualizes speed limits from the HERE Map Content catalog. It retrieves the speed limits data from the HERE Map Content Navigation Attributes layer and visualizes it over the roads geometry from the HERE Map Content Road Topology layer. The speed limits data has no geometry information, so it is mapped to road segments from the road topology layer.

Example Source Code


/*
 * Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
 *
 * This software and other materials contain proprietary information controlled by HERE and are
 * protected by applicable copyright legislation. Any use and utilization of this software and other
 * materials and disclosure to any third parties is conditional upon having a separate agreement
 * with HERE for the access, use, utilization or disclosure of this software. In the absence of such
 * agreement, the use of the software is not allowed.
 */

import { SegmentAnchorGeometryDataProvider } from "@here/geometry-data-provider";
import {
    DataProvider,
    InteractiveIntersectionAgent,
    InteractiveDataSource
} from "@here/interactive-datasource-protocol";
import { DataInspector, PanelDisplayMode } from "@here/interactive-mapview-ui";
import {
    omvDataLayer,
    omvHostHrn,
    lookupServiceEnvironment,
    ribHrn,
    ribTopologyLayer,
    speedLimitTiles
} from "../config";
import { SpeedLimitsDataSource } from "./datasources/speedLimitsDataSource/SpeedLimitsDataSource";

/**
 * This example showcases dynamically creating and using a custom implementation of
 * `InteractiveDataSource` - a datasource to visualize speed limits from RIB catalog.
 *
 * Because custom `SpeedLimitsDataSource` datasource is not determined by `DataInspector` by catalog
 * HRN, it is added to an instance of `DataInspector` after it is initialized.
 */

// Create an instance of `DataInspector`.
const dataInspector = new DataInspector(
    {
        elementId: "may-host-component",
        mapView: {
            theme: "resources/normal.reduced.night.json",
            decoder: {
                url: "./decoder.bundle.js"
            },
            defaultZoomLevel: 12,
            enableTilt: false,
        },
        baseMap: {
            hrn: omvHostHrn,
            layer: omvDataLayer
        },
        widgets: {
            zoomLevel: true,
            statusBar: true,
            searchField: true,
            decodedPanel: {
                enabled: true,
                initialState: PanelDisplayMode.Expanded,
                width: 400
            },
            statsPanel: {
                enabled: true,
                initialState: PanelDisplayMode.Collapsed
            },
            authForm: {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            }
        },
        toolbar: {
            enabled: true,
            fullScreenButton: true
        },
        logMessages: true,
        lookupServiceEnvironment
    },
    document.getElementById("map-here") as HTMLElement
);

if (dataInspector.mapView === undefined) {
    throw new Error("MapView was not initialized.");
}

const dataProvider = new DataProvider({
    hrn: ribHrn,
    layer: "navigation-attributes",
    getToken: dataInspector.getConfig().getBearerToken!,
    environment: lookupServiceEnvironment
});

// Create an instance of `SegmentAnchorGeometryDataProvider`, necessary for `SpeedLimitsDataSource`.
const geometryDataProvider = new SegmentAnchorGeometryDataProvider(
    {
        hrn: ribHrn,
        layer: ribTopologyLayer,
        getToken: dataInspector.getConfig().getBearerToken!,
        environment: lookupServiceEnvironment
    }
);

// An instance of `InteractiveIntersectionAgent` is needed to detect speed limit items under mouse
// pointer.
const intersectionAgent = new InteractiveIntersectionAgent(dataInspector.mapView);

// Create a sample speed limits datasource which uses `RoadSegmentsDataProvider`.
const speedLimitsDataSource = new SpeedLimitsDataSource({
    dataProvider,
    intersectionAgent,
    geometryDataProvider
});

dataInspector.setInteractiveDataSource(speedLimitsDataSource);

// Add an event listener to be fired when data source instance is added to `MapView`.
speedLimitsDataSource.addEventListener(InteractiveDataSource.EVENT_ATTACHED, () => {
    // Visualize speed limits data on specific tile.
    speedLimitsDataSource.selectTile(speedLimitTiles[0]);
});

results matching ""

    No results matching ""