サンプルアプリを実行します

データ インスペクター ライブラリには、さまざまな使用例を理解できるように設計されたサンプルアプリケーションが用意されています。 この例にアクセスするには、次の 2 つの方法があります。

  • HERE platform でホストされている例にアクセスするには、このリンクをクリックしてください。 データ インスペクターの機能の調査をすぐに開始できます。インストールは不要です。 必要なのは、プラットフォームにログインすることだけです。

  • サンプルアプリをインストールする」の章で説明されている手順に従って、サンプルをローカルでインストールして実行します。 インストールが完了したら、で例を開き http://localhost:5000/ます。

各例は 、データ インスペクター アプリケーションウィンドウ ( DataInspector クラスで表されます ) で実行され、特定のデータ インスペクター ライブラリコンポーネントの単一の機能、またはさまざまな機能の組み合わせについて説明します。

データ インスペクター ライブラリの例
図 1. データ インスペクター ライブラリの例

詳細ボタンをクリックすると、詳細な説明例が表示されます。

サンプルのソースコードを表示するには、 [ ソースコード ] ボタンをクリックします。

すべてのサンプルアプリケーションのソースを含む ZIP アーカイブをダウンロードするには、 [ サンプルをダウンロード ] ボタンをクリックします。

例一覧表

この章では、データ インスペクター ライブラリに含まれているすべての例について、ソースコードを含めて説明します ( クリックすると展開できます ) 。

強調表示されます

Control the Visualization

HERE をクリック してアプリを開きます。

この例では、埋め込みアプリケーションが DataInspector 外部からを制御する方法を示します。

ユーザー入力または URL パラメーターに基づいて、カタログの HERE リソースネーム ( HERE リソースネーム )、レイヤー、レイヤーのバージョン、ズーム レベルおよびマップ ビューの場所を変更できます。

この例では、 HERE リソースネーム 、レイヤー、バージョン、緯度、経度、 の状態を変更 DataInspectorするには、とズーム レベルの値を入力します。

この目的のために、は DataInspector 次のパブリックメソッドを提供します。

  • setState: の新しい状態を設定 DataInspector し、新しい HERE リソースネーム 、レイヤー、レイヤーのバージョンで再読み込みします。
  • focusMapCameraAt: 指定した座標でカメラを中央に配置し、目的のズーム レベルを設定します。

DataInspector また、移動時にの状態を取得して URL パラメータで保持したり、新しい HERE リソースネーム 、バージョン、またはレイヤーを指定したりできます。次に例を示します。

?hrn=hrn:here:data::olp-here:rib-2&layer=topology-geometry&location=52.4956004,13.3553675&zoomLevel=10

ソースコードの例


/*
 * Copyright (C) 2018-2023 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 { VersionedLayer, PlatformDataProvider } from "@here/interactive-datasource-protocol";
import {
    DataInspector,
    I18n,
    PanelDisplayMode,
    WidgetAbstract
} from "@here/interactive-mapview-ui";
import { Action, History, createBrowserHistory, Update } from "history";
import {
    geoCenter,
    useToken,
    locale,
    showLanguageSelector,
    enableExtendedCoverage,
    layerBrowserAppDataLayer,
    layerBrowserAppHostHrn,
    lookupServiceEnvironment,
    hideURL
} from "../config";
import { bearerTokenProvider } from "./common";

/**
 * 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;
    };
}

/** Available strategies to store/retrieve data from URL. */
enum BrowserHistoryStrategy {
    /** Custom strategy. */
    Custom,
    /** Build in into DataInspector strategy. */
    DataInspector,
    /** Data will not be stored/retrieved from URL. Used to avoid URL parameters conflict. */
    None
}

/**
 * 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 browserHistoryStrategy Defines which strategy will be used to store/retrieve data
     * from URL.
     * @default BrowserHistoryStrategy.Custom.
     */
    constructor(browserHistoryStrategy = BrowserHistoryStrategy.Custom) {
        if (browserHistoryStrategy === BrowserHistoryStrategy.Custom) {
            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,
                    ...(this.m_controlParams.location
                        ? { geoCenter: this.m_controlParams.location }
                        : { geoCenter }
                    )
                },
                monacoEditorWorkersBasePath: "../monaco-editor",
                translationsBasePath: "../resources/i18n/",
                streamSaverBasePath: "../resources/mitm/",
                defaultLocale: locale || undefined,
                getBearerToken: useToken ? bearerTokenProvider : undefined,
                widgets: {
                    authForm: !useToken ? {
                        tokenForm: false,
                        accessKeyForm: true,
                        localAuthForm: true
                    } : undefined
                },
                toolbar: {
                    languageSelector: showLanguageSelector
                },
                logMessages: true,
                lookupServiceEnvironment,
                pageUrlParams: {
                    enabled: browserHistoryStrategy === BrowserHistoryStrategy.DataInspector
                }
            },
            document.getElementById("map-here") as HTMLElement,
            {
                interactiveDataSources: [{
                    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(update: Update): void {
        this.m_browserAction = update.action;
        this.fetchControlParams();

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

        // Change state of the data inspector only on actions caused by
        // browser buttons ("Back", "Forward").
        if (update.action !== 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 === Action.Pop) {
                this.m_browserAction = Action.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`.
        this.m_dataInspector.mapView.addEventListener(MapViewEventNames.DataSourceConnect, async (event) => {
            const dataSource = this.m_dataInspector.interactiveDataSource;
            if (
                dataSource === undefined
                || (event as any).dataSourceName !== dataSource.name
            ) {
                return;
            }

            const dataProvider = dataSource.dataProvider() as PlatformDataProvider;
            if (dataProvider !== undefined) {
                const layer = dataProvider.layer;
                if (layer instanceof VersionedLayer) {
                    layer.addEventListener(
                        VersionedLayer.ON_VERSION_CHANGE,
                        (event: any) => {
                            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[] = [];

        searchParams.push("showLanguageSelector=" + showLanguageSelector);

        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;
        }
        const formFields = form.elements;
        (formFields.namedItem("userHrn") as HTMLInputElement).placeholder =
            I18n.translate("olpdi.examples.control-di.hrn");
        (formFields.namedItem("userLayer") as HTMLInputElement).placeholder =
            I18n.translate("olpdi.examples.control-di.layer");
        (formFields.namedItem("userVersion") as HTMLInputElement).placeholder =
            I18n.translate("olpdi.examples.control-di.version");
        (formFields.namedItem("userLatitude") as HTMLInputElement).placeholder =
            I18n.translate("olpdi.examples.control-di.latitude");
        (formFields.namedItem("userLongitude") as HTMLInputElement).placeholder =
            I18n.translate("olpdi.examples.control-di.longitude");
        (formFields.namedItem("userZoomLevel") as HTMLInputElement).placeholder =
            I18n.translate("olpdi.examples.control-di.zoom-level");
        (formFields.namedItem("submitBtn") as HTMLInputElement).value =
            I18n.translate("olpdi.examples.control-di.change");

        //hide `See URL` button in case examples hosted from a portal
        if (hideURL !== true) {
            // Since olp-examples shows each example in iframe, it is not possible to
            // track the URL, so the link was added which opens example in new tab to demonstrate URL.
            const viewURL = document.createElement("a");
            viewURL.href = "#";
            viewURL.textContent = I18n.translate("olpdi.examples.control-di.view-url");
            viewURL.setAttribute("target", "_blank");
            viewURL.classList.add("userInputFormLink");
            (document.getElementById("submitContainer") as HTMLElement).appendChild(viewURL);
        }
        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 !== undefined
                    ? config.interactiveDataSource.hrn.toString() : "";
            (formFields.namedItem("userLayer") as HTMLInputElement).value =
                config.interactiveDataSource.layer !== undefined
                    ? 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.setInteractiveDataSources([{
            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(BrowserHistoryStrategy.DataInspector);

Embed the Visualization in a TypeScript Application

HERE をクリック してアプリを開きます。

この例では、のインスタンスを作成 DataInspectorします。 固定 mapView サイズの HTML 要素内にを作成し 、 Data API に接続された GeoJSON データソースを作成します。

この例では、最小数のデータ インスペクターオプションを提供しています。 1 つのマップを表示するには、DataInspectorコンストラクタからinteractiveDataSourceオブジェクトを削除するだけです。

ソースコードの例


/*
 * Copyright (C) 2018-2023 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 { useToken, locale, showLanguageSelector, lookupServiceEnvironment, ribCartoLayer, ribHostHrn } from "../config";
import { bearerTokenProvider } from "./common";

new DataInspector(
    {
        mapView: {
            theme: "../resources/normal.reduced.night.json",
            decoder: {
                url: "../decoder.bundle.js"
            }
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            authForm: !useToken ? {
                accessKeyForm: true
            } : undefined
        },
        toolbar: {
            languageSelector: showLanguageSelector
        },
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true }
    },
    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
    }
);

Token Provider

HERE をクリック してアプリを開きます。

この例では、単純なサーバーサイドトークンプロバイダを作成して使用する方法を示します。 トークンプロバイダは、デモ目的ですべてのアカウントで機能するログインを持たずに、自分自身の資格情報のみに基づいてログイントークンを生成します。 クライアント アプリケーションは、これらのトークンをすべてのリクエストに要求して使用できます。

この例の実行方法の詳細については 、「サーバートークンプロバイダからトークンを使用する」を参照してください

ソースコードの例


/*
 * Copyright (C) 2018-2023 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
Data Inspector Full Setup

HERE をクリック してアプリを開きます。

この例では、のインスタンスを作成 DataInspectorします。 固定 mapView サイズの HTML 要素内にを作成し 、 Data API に接続された GeoJSON データソースを作成します。

この例では、 [ 統計 ] パネルを含むデータ インスペクターのすべての機能を示します。 このパネルには、デコードされたタイルについての情報を含むログと、デコードされたタイルについての情報を含む拡張パネルが表示されます。 UI 要素で使用できるすべての設定オプションについては、以下の例のソースコードを参照してください。

ソースコードの例


/*
 * Copyright (C) 2018-2023 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://here-tech.skawa.fun/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 {
    useToken,
    locale,
    showLanguageSelector,
    boundingBox,
    enableExtendedCoverage,
    geoCenter,
    lookupServiceEnvironment,
    omvHostHrn,
    omvDataLayer,
    ribHostHrn,
    ribTopologyLayer
} from "../config";
import { bearerTokenProvider } from "./common";


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.night.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
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        baseMap: {
            hrn: omvHostHrn,
            layer: omvDataLayer,
            // Catalog version for the base map.
            // version: -1;
            styleSetName: "tilezen" //The name of the style set from the theme
        },
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            zoomLevel: true,
            statusBar: true,
            searchField: true,
            decodedPanel: {
                enabled: true,
                initialState: PanelDisplayMode.Expanded,
                width: 400
            },
            statsPanel: {
                enabled: true,
                initialState: PanelDisplayMode.Collapsed
            },
            authForm: !useToken ? {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            } : undefined,
        },
        toolbar: {
            enabled: true,
            fullScreenButton: true,
            languageSelector: showLanguageSelector
        },
        logMessages: true,
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true },
        locales: [
            "en-US",
            "ja-JP",
            "zh-CN",
            "zz-ZZ"
        ]
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSources: [{
            hrn: ribHostHrn,
            layer: ribTopologyLayer,
            catalogVersion: 0,
            levelsWithData: [12],
            externalRendererPluginName: "interactive_host_full.plugin.template",
            preferRendererPlugin: false,
            selectedPartitions: ["23600040", "23605525", "23600039"]
        }],
        enableCoverage: true,
        enableExtendedCoverage,
        enableInfoPanel: true,
        enableFiltering: true
    }
);

HTML+JS Single Page Application

HERE をクリック してアプリを開きます。

この例では、純粋な HTML および JavaScript で記述された単一ページのアプリケーションに視覚エフェクトを埋め込む最も簡単な方法を示します。 この例 DataInspector では、すべての既定値を使用してクラスを使用しています。 このコード例を実行するには、コンパイルは必要ありません。

GeoJSON with Leaflet

HERE をクリック してアプリを開きます。

このleaflet / geojson例では、 JavaScript を使用してプラットフォームで認証し、 HERE Data SDK for TypeScript を使用して HERE GeoJSON サンプルカタログの GeoJSON データにアクセスする方法、および Leaflet 用の HARP プラグインを使用してビジュアル化に最適化した地図 Plus ベース マップを表示する方法を示します。 また、ベース マップ上でデータを視覚化する方法についても説明します。 詳細については、「リーフレットを使用して HERE platform データを検査する」を参照してください。

ソースコードの例


/*
 * Copyright (C) 2019-2023 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) {
    let getToken;
    const useToken = (new URL(window.location.href).searchParams.get("useToken") === "true");
    if (useToken) {
        // Use token provided
        getToken = () => new Promise((resolve, reject) => {
            const tokenHandler = event => {
                if (event.data.type === "userToken") {
                    resolve(event.data.token);
                    window.removeEventListener("message", tokenHandler);
                }
            };

            // send request to parent window to provide user token
            parent.postMessage({ type: "tokenRequest" }, "*");

            // wait and handle response with the user token
            window.addEventListener("message", tokenHandler);
        });
    } else {
        // 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();
        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 HarpGL.HarpGL({
        theme: "https://unpkg.com/@here/harp-map-theme@0.23.0/resources/berlin_tilezen_night_reduced.json",
        fontCatalog: "https://unpkg.com/@here/harp-map-theme@0.23.0/resources/fonts/Default_FontCatalog.json"
    }).addTo(map);
    const baseMapLayer = await getLayerClient(baseMapHRN, "omv-plus-v2", settings);
    harpLeaflet.mapView.addDataSource(new harp.OmvDataSource({
        dataProvider: {
            async getTile(tileKey) {
                const request = new DataRequest()
                    .withPartitionId(tileKey.toHereTile());
                const response = await baseMapLayer.getData(request);
                return response.arrayBuffer();
            },
            async connect() { },
            async ready() { return true; },
            async register() { },
            async unregister() { }
        },
        layerName: "omv-plus-v2",
        getBearerToken: getToken,
        styleSetName: "tilezen"
    }));
    //add HERE copyright notice
    const year = new Date().getFullYear();
    const HERECopyright = (env === "here-cn") ? "HERE, NavInfo Co., Ltd" : "HERE"
    map.attributionControl.addAttribution(`© ${year}` +
        ` ${HERECopyright}`);
}

/**
 * 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 hrnInstance = HRN.fromString(hrn);
    const catalogClient = new CatalogClient(hrnInstance, settings);
    const config = await catalogClient.getCatalog(new CatalogRequest());
    const layerConfig = config.layers.find(item => item.id === layerId);
    if (layerConfig === undefined) {
        return;
    }

    const layerClientParams = { catalogHrn: hrnInstance, layerId, settings };
    switch (layerConfig.layerType) {
        case "versioned":
            return new VersionedLayerClient(layerClientParams);

        case "volatile":
            return new VolatileLayerClient(layerClientParams);
    }
}

Encoded Data with Leaflet

HERE をクリック してアプリを開きます。

このleaflet / protobuf例では、 JavaScript を使用して HERE platform で認証し、 HERE マップコンテント カタログの Roads-Topology & Geometry レイヤーに ある Protobuf でエンコードされたデータに HERE Data SDK for TypeScript でアクセスする方法を示します。 レイヤーからスキーマを取得して使用 し、 GeoJSON にデータをデコードする方法、 HARP プラグイン for Leaflet を使用してビジュアル化に最適化した地図 Plus ベース マップを表示する方法、およびベース マップの上にデータを表示する方法。 詳細については、「リーフレットを使用して HERE platform データを検査する」を参照してください。

ソースコードの例


/*
 * Copyright (C) 2019-2023 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) {
    let getToken;
    const useToken = (new URL(window.location.href).searchParams.get("useToken") === "true");
    if (useToken) {
        // Use token provided
        getToken = () => new Promise((resolve, reject) => {
            const tokenHandler = event => {
                if (event.data.type === "userToken") {
                    resolve(event.data.token);
                    window.removeEventListener("message", tokenHandler);
                }
            };

            // send request to parent window to provide user token
            parent.postMessage({ type: "tokenRequest" }, "*");

            // wait and handle response with the user token
            window.addEventListener("message", tokenHandler);
        });
    } else {
        // 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();
        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 HarpGL.HarpGL({
        theme: "https://unpkg.com/@here/harp-map-theme@0.23.0/resources/berlin_tilezen_night_reduced.json",
        fontCatalog: "https://unpkg.com/@here/harp-map-theme@0.23.0/resources/fonts/Default_FontCatalog.json"
    }).addTo(map);
    const baseMapLayerConfig = await getLayerConfig(baseMapHRN, "omv-plus-v2", settings);
    if (!baseMapLayerConfig) {
        throw new Error("Base map layer was not found");
    }
    const baseMapLayer = getLayerClient(baseMapLayerConfig.layerType, baseMapHRN, "omv-plus-v2", settings);
    harpLeaflet.mapView.addDataSource(new harp.OmvDataSource({
        dataProvider: {
            async getTile(tileKey) {
                const request = new DataRequest()
                    .withPartitionId(tileKey.toHereTile());
                const response = await baseMapLayer.getData(request);
                return response.arrayBuffer();
            },
            async connect() { },
            async ready() { return true; },
            async register() { },
            async unregister() { },
        },
        layerName: "omv-plus-v2",
        getBearerToken: getToken,
        styleSetName: "tilezen"
    }));

    // add HERE copyright notice
    const year = new Date().getFullYear();
    const HERECopyright = (env === "here-cn") ? "HERE, NavInfo Co., Ltd" : "HERE"
    map.attributionControl.addAttribution(`© ${year}` +
        ` ${HERECopyright}`);
    // 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) {
    const hrnInstance = HRN.fromString(hrn);
    const layerClientParams = { catalogHrn: hrnInstance, layerId, settings };
    switch (layerType) {
        case "versioned":
            return new VersionedLayerClient(layerClientParams);

        case "volatile":
            return new VolatileLayerClient(layerClientParams);

        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
    });
}

Access to Other Data Source from a GeoJSON Plugin

HERE をクリック してアプリを開きます。

この例では、カスタム GeoJSON レンダラ プラグインを使用して、さまざまなレイヤーのデータにアクセスする方法を示します。 このアプリでは 、 Placesメタデータ レイヤーからデータを抽出して場所のカテゴリ名を表示する、 HERE Map Content カタログの Places for HERE Essential Map レイヤーのスキーマのサンプルプラグインを提供します。 プラグインには、その仕組みをより的確に把握できるように、インラインコメントが含まれています。

レンダリングプラグインからの複数レイヤーのデータアクセスを実装する方法の詳細について は、「レンダリング関数」を参照してください。

ソースコードの例


/*
 * Copyright (C) 2020-2023 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 { useToken, locale, showLanguageSelector, lookupServiceEnvironment, ribHostHrn } from "../config";
import { bearerTokenProvider } from "./common";

new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 11,
            theme: "../resources/normal.reduced.night.json",
            decoder: {
                url: "../decoder.bundle.js"
            }
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            authForm: !useToken ? {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            } : undefined
        },
        toolbar: {
            languageSelector: showLanguageSelector
        },
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true }
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: ribHostHrn,
            layer: "here-places",
            externalRendererPluginName: "renderer.plugin.here-places"
        },
        enableCoverage: true
    }
);
GeoJSON with OpenLayers

HERE をクリック してアプリを開きます。

この例では、 JavaScript を OpenLayers Web マッピングライブラリと組み合わせて使用し、 HERE GeoJSON サンプルカタログからヨーロッパの国の境界線を表示する方法を示します。 サンプルのソースコードから 、ユーザーの資格情報 および アプリ API キー を使用して HERE platform へのアクセス権を取得する方法、 HERE ビジュアル化に最適化した地図 Plus のベースマップの読み込み方法、ベースマップのスタイル設定のカスタマイズ方法、プラットフォームカタログから GeoJSON データを取得する方法、およびこのデータをベースマップの上にレンダリングする方法を学習できます。

ソースコードの例


/*
* Copyright (C) 2021-2023 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.
*/

// Prepare styling for base map
const styleBaseMapVector = function (feature, resolution) {
    switch (feature.get("layer")) {
        case "water":
            return new ol.style.Style({
                fill: new ol.style.Fill({
                    color: "#9db9e8"
                }),
            });
        case "boundaries":
            return new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: (feature.get("kind") == "region") ? "#d0d0d0" : "#909090",
                    width: (feature.get("kind") == "region") ? 1 : 1.5
                })
            });
        case "roads":
            return new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: "#cccc55",
                    width: (feature.get("kind") == "highway") ? 2 : 1
                })
            });
        case "places":
            return new ol.style.Style({
                image: new ol.style.Circle({
                    radius: (feature.get("kind_detail") == "city") ? 2 : 0,
                    fill: new ol.style.Fill({
                        color: (feature.get("kind_detail") == "city") ? "#906060" : "#909090"
                    }),
                    stroke: 0
                }),
                text: new ol.style.Text({
                    text: (feature.get("kind_detail") == "city") ? feature.get("name") : null,
                    fill: new ol.style.Fill({
                        color: "#909090"
                    }),
                    font: "12px sans-serif"
                })
            });
        default:
            return new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: "#d0f0d0"
                }),
                fill: new ol.style.Fill({
                    color: "#e0f0e0"
                })
            });
    }
};

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

    const layerClientParams = { catalogHrn: hrnInstance, layerId, settings };
    switch (layerConfig.layerType) {
        case "versioned":
            return new VersionedLayerClient(layerClientParams);

        case "volatile":
            return new VolatileLayerClient(layerClientParams);
    }
}

// Show an error when credentials are invalid
const fail = (form, status) => {
    status.innerText = "Cannot connect. Please double check your credentials and access.";
    form.key.disabled = false;
    form.secret.disabled = false;
    form.apikey.disabled = false;
    form.scope.disabled = false;
    form.action.disabled = false;
}

let map;
// Draw the base map when credentials are valid
const success = (layer) => {
    map = new ol.Map({
        target: "map",
        view: new ol.View({
            center: ol.proj.fromLonLat([8.41, 52.82]),
            zoom: 4
        })
    });
    map.addLayer(layer);
    document.body.removeChild(document.body.querySelector(".auth-form"));
}

// Get layer object, that will fetch GeoJSON data. Then get data and draw on map
async function getAndDrawData(env, form) {
    const hrn = "hrn:here:data::olp-here:here-geojson-samples";
    const layerId = "country-borders";
    const partitions = ["1440", "1441", "1444", "1419", "1269", "1271"];

    // Prepare authentication and token function for accessing the HERE data layer
    const authCreds = {
        env: env,
        credentials: {
            accessKeyId: form.key.value, // accessKeyId
            accessKeySecret: form.secret.value // accessKeySecret
        },
        tokenRequester: requestToken,
        scope: form.scope.value ?? "" // project scope not necessary for example data
    };
    const token = new UserAuth(authCreds).getToken();
    const getToken = () => token;

    const settings = new OlpClientSettings({
        environment: env,
        getToken
    });

    let dataLayer;
    try {
        dataLayer = await getLayerClient(hrn, layerId, settings);
        if (!dataLayer) {
            throw new Error("Layer not found");
        }
        const url = `https://vector.hereapi.com/v2/vectortiles/base/mc/{z}/{x}/{y}/omv?apikey=${form.apikey.value}`;
        const layer = new ol.layer.VectorTile({
            source: new ol.source.VectorTile({
                attributions: [
                    '© HERE'
                ],
                format: new ol.format.MVT(),
                url,
                maxZoom: 17
            }),
            style: styleBaseMapVector
        });
        try {
            // check if user`s HERE API Key is valid
            const response = await fetch(url);
            if (response.status === 401) {
                fail(form, status);
            } else {
                success(layer);
            }
        } catch (e) {
            // in case fetch request is blocked by CORS policy
            success(layer);
        }
    } catch (error) {
        fail(form, status);
        throw new Error(error);
    }

    if (map === undefined) {
        return;
    }

    //var vectorSource, vectorLayer;
    partitions.forEach(async partition => {
        const request = new DataRequest()
            .withPartitionId(`${partition}`);
        const response = await dataLayer.getData(request);
        const data = await response.json();

        // Draw on map
        const vectorSource = new ol.source.Vector({
            features: new ol.format.GeoJSON().readFeatures(data, {featureProjection: "EPSG:3857"})
        });

        const vectorLayer = new ol.layer.Vector({
            source: vectorSource
        });

        map.addLayer(vectorLayer);
    });
}

その他

sdii / DI

HERE をクリック してアプリを開きます。

この例では、 Sensor のデータインジェストインターフェース( SDII )データソースの機能を操作する方法を示します。 マウスポインタを使用してパスと道路標識を強調表示し、個々の SDII メッセージをフィルタリングできます。

ソースコードの例


/*
 * Copyright (C) 2018-2023 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 {
    useToken,
    locale,
    showLanguageSelector,
    omvDataLayer,
    omvHostHrn,
    sdiiHostHrn,
    sdiiDataLayer,
    lookupServiceEnvironment
} from "../config";
import { bearerTokenProvider } from "./common";

new DataInspector(
    {
        mapView: {
            theme: "../resources/normal.reduced.night.json",
            decoder: {
                url: "../decoder.bundle.js"
            },
            defaultZoomLevel: 12
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        baseMap: {
            hrn: omvHostHrn,
            layer: omvDataLayer
        },
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            authForm: !useToken ? {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            } : undefined
        },
        toolbar: {
            languageSelector: showLanguageSelector
        },
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true }
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: sdiiHostHrn,
            layer: sdiiDataLayer
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);
sdii / DI / animated

HERE をクリック してアプリを開きます。

この例では sdiiDataSource 、を使用して道路標識および道路をアニメーション化する方法を示します。

ソースコードの例


/*
 * Copyright (C) 2018-2023 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 {
    useToken,
    locale,
    showLanguageSelector,
    omvDataLayer,
    omvHostHrn,
    sdiiHostHrn,
    sdiiDataLayer,
    lookupServiceEnvironment
} from "../config";
import { bearerTokenProvider } from "./common";

new DataInspector(
    {
        mapView: {
            theme: "../resources/normal.reduced.night.json",
            decoder: { url: "../decoder.bundle.js" },
            defaultZoomLevel: 12
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        baseMap: {
            hrn: omvHostHrn,
            layer: omvDataLayer
        },
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            authForm: !useToken ? {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            } : undefined
        },
        toolbar: {
            languageSelector: showLanguageSelector
        },
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true }
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: sdiiHostHrn,
            layer: sdiiDataLayer,
            animationEnabled: true
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);

sdii / DI / plugin

HERE をクリック してアプリを開きます。

この例では、 GeoJSON レンダラ プラグインを使用してセンサーデータインジェストインターフェイス (SDII) データを表示する方法を示します。

ソースコードの例


/*
 * Copyright (C) 2020-2023 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 { useToken, locale, showLanguageSelector, sdiiDataLayer, sdiiHostHrn, lookupServiceEnvironment } from "../config";
import { bearerTokenProvider } from "./common";

new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 12,
            theme: "../resources/normal.reduced.night.json",
            decoder: {
                url: "../decoder.bundle.js"
            }
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            authForm: !useToken ? {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            } : undefined
        },
        toolbar: {
            languageSelector: showLanguageSelector
        },
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true }
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSource: {
            hrn: sdiiHostHrn,
            layer: sdiiDataLayer,
            preferRendererPlugin: true,
            externalRendererPluginName: "plugin-sdii"
        },
        enableCoverage: true,
        enableFiltering: true,
        enableInfoPanel: true
    }
);

geojson / simple

HERE をクリック してアプリを開きます。

この例では、を使用 GeoJsonDataSource して、 GeoJSON データを含むカタログからデータを取得します。 単一のタイルから GeoJSON データを視覚化します。

ソースコードの例


/*
 * Copyright (C) 2017-2023 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 { useToken, geoJsonDataLayer, geoJsonDataTile, geoJsonHrn, lookupServiceEnvironment } from "../config";
import {
    addBaseMapCountryBorder,
    bearerTokenProvider,
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection
} from "./common";
import { TileControlHandler } from "@here/interactive-mapview-ui";
import { MapControls } from "@here/harp-map-controls";
import {
    BaseMapDataProvider,
    LookupEnvironment,
    PlatformDataProvider
} 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);

let getBearerToken;
if (useToken) {
    getBearerToken = bearerTokenProvider;
} else {
    const tokenResolver = createTokenResolver(mapView);
    getBearerToken = tokenResolver.getBearerToken.bind(tokenResolver) as () => Promise;
}

// Base map
createBaseMapDataSource(getBearerToken).then(omvDataSource => {
    mapView.addDataSource(omvDataSource);
    if (lookupServiceEnvironment === LookupEnvironment.HERE_CN) {
        addBaseMapCountryBorder(mapView, omvDataSource.dataProvider() as BaseMapDataProvider);
    }
});

const dataProvider = new PlatformDataProvider({
    hrn: geoJsonHrn,
    layer: geoJsonDataLayer,
    getToken: getBearerToken,
    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 / without / dataservice

HERE をクリック してアプリを開きます。

この例では、 Data API に接続せずに、ハードコードされた GeoJSON オブジェクトのジオメトリを表示します。

ソースコードの例


/*
 * Copyright (C) 2017-2023 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 {
    BaseMapDataProvider,
    InteractiveIntersectionAgent,
    LookupEnvironment
} from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    addBaseMapCountryBorder,
    bearerTokenProvider,
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection
} from "./common";
import { TileControlHandler } from "@here/interactive-mapview-ui";
import { MapControls } from "@here/harp-map-controls";
import { useToken, geoJsonData, geoJsonMapCenter, lookupServiceEnvironment } 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);

let getBearerToken;
if (useToken) {
    getBearerToken = bearerTokenProvider;
} else {
    const tokenResolver = createTokenResolver(mapView);
    getBearerToken = tokenResolver.getBearerToken.bind(tokenResolver) as () => Promise;
}

// Base map
createBaseMapDataSource(getBearerToken).then(omvDataSource => {
    mapView.addDataSource(omvDataSource);
    if (lookupServiceEnvironment === LookupEnvironment.HERE_CN) {
        addBaseMapCountryBorder(mapView, omvDataSource.dataProvider() as BaseMapDataProvider);
    }
});

// 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

HERE をクリック してアプリを開きます。

この例 では、外部 GeoJSON レンダラ プラグインを使用して制限速度を表示します。 プラグインは、を使用 SegmentAnchorGeometryDataProvider して道路のジオメトリを取得し、そのジオメトリに制限速度のデータをマップします。

ソースコードの例


/*
 * Copyright (C) 2017-2023 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, DataInspectorEventNames } from "@here/interactive-mapview-ui";
import { useToken, locale, showLanguageSelector, lookupServiceEnvironment, ribHostHrn, speedLimitTiles } from "../config";
import { bearerTokenProvider } from "./common";

const dataInspector = new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 11,
            theme: "../resources/normal.reduced.night.json",
            decoder: {
                url: "../decoder.bundle.js"
            }
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            authForm: !useToken ? {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            } : undefined
        },
        toolbar: {
            languageSelector: showLanguageSelector
        },
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true }
    },
    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.addEventListener(
    DataInspectorEventNames.DATA_INSPECTOR_IS_READY,
    () => speedLimitTiles.forEach(tile => dataInspector.tileControlHandler.selectTile(tile, true))
);

geojson / properties

HERE をクリック してアプリを開きます。

この例では、style.colorstyle.fillstyle.widthproperties.tooltipなどのカスタム GeoJSON フィーチャプロパティおよび他の MapBox スタイルを表示します。

ソースコードの例


/*
 * Copyright (C) 2017-2023 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 {
    BaseMapDataProvider,
    InteractiveIntersectionAgent,
    LookupEnvironment
} from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    addBaseMapCountryBorder,
    bearerTokenProvider,
    createBaseMapDataSource,
    createTokenResolver,
    InformationPanel,
    initializeMapView,
    setupTileSelection
} from "./common";
import {
    useToken,
    geoJsonProperties,
    geoJsonPropertiesCenter,
    lookupServiceEnvironment
} from "../config";
import { MapControls } from "@here/harp-map-controls";
import {
    GeoJsonInfoPanel,
    I18n,
    installInfoWidgets,
    TileControlHandler
} 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 = I18n.translate("olpdi.examples.geojson-properties.hint");
new InformationPanel(infoPanelMsg);

let getBearerToken;
if (useToken) {
    getBearerToken = bearerTokenProvider;
} else {
    const tokenResolver = createTokenResolver(mapView);
    getBearerToken = tokenResolver.getBearerToken.bind(tokenResolver) as () => Promise;
}

// Base map
createBaseMapDataSource(getBearerToken).then(omvDataSource => {
    mapView.addDataSource(omvDataSource);
    if (lookupServiceEnvironment === LookupEnvironment.HERE_CN) {
        addBaseMapCountryBorder(mapView, omvDataSource.dataProvider() as BaseMapDataProvider);
    }
});

// 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 / bounding / box

HERE をクリック してアプリを開きます。

この例では、特定の GeoJSON オブジェクトに合わせてマップのズームと位置を自動的に調整します。 この GeoJsonDataSource.EVENT_TILE_DECODED イベントでは、レンダリングされた GeoJSON オブジェクトのバウンディング ボックスを取得できます。 この例では、のカメラの位置を計算して mapView 、マップ ビューにオブジェクトを収めることができるようにするためのサンプルコードを示します。

ソースコードの例


/*
 * Copyright (C) 2017-2023 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 {
    BaseMapDataProvider,
    InteractiveIntersectionAgent,
    LookupEnvironment
} from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource, GeoJsonDataSourceEvent } from "@here/olp-geojson-datasource";
import {
    bearerTokenProvider,
    createBaseMapDataSource,
    initializeMapView,
    setupTileSelection,
    createTokenResolver,
    addBaseMapCountryBorder
} from "./common";
import { TileBoundingBox, TileControlHandler } from "@here/interactive-mapview-ui";
import { MapControls } from "@here/harp-map-controls";
import { useToken, geoJsonData, lookupServiceEnvironment } 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);

let getBearerToken;
if (useToken) {
    getBearerToken = bearerTokenProvider;
} else {
    const tokenResolver = createTokenResolver(mapView);
    getBearerToken = tokenResolver.getBearerToken.bind(tokenResolver) as () => Promise;
}

// Base map
createBaseMapDataSource(getBearerToken).then(omvDataSource => {
    mapView.addDataSource(omvDataSource);
    if (lookupServiceEnvironment === LookupEnvironment.HERE_CN) {
        addBaseMapCountryBorder(mapView, omvDataSource.dataProvider() as BaseMapDataProvider);
    }
});

// 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;
        }

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

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

geojson / tilegrid

HERE をクリック してアプリを開きます。

この例では、GeoJSON データソースをカバレッジデータソースと結合して、データを含むタイルを表示する方法を示します。GeoJsonDataSourceは、 GeoJSON データを含むカタログからデータを取得し、coverageDataSource同じカタログに接続して、同じデータを表すようにします。

ソースコードの例


/*
 * Copyright (C) 2017-2023 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 {
    PlatformDataProvider,
    InteractiveIntersectionAgent,
    LookupEnvironment,
    BaseMapDataProvider
} from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    useToken,
    geoJsonDataLayer,
    geoJsonHrn,
    geoJsonLevelWithData,
    lookupServiceEnvironment
} from "../config";
import {
    bearerTokenProvider,
    InformationPanel,
    createBaseMapDataSource,
    createTokenResolver,
    initializeMapView,
    setupTileSelection,
    addBaseMapCountryBorder
} from "./common";
import { I18n, TileControlHandler } from "@here/interactive-mapview-ui";
import { MapControls } from "@here/harp-map-controls";

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

const mapView = initializeMapView(canvas);

// Create info panel
new InformationPanel(I18n.translate("olpdi.examples.geojson-tilegrid.hint"));

let getBearerToken;
if (useToken) {
    getBearerToken = bearerTokenProvider;
} else {
    const tokenResolver = createTokenResolver(mapView);
    getBearerToken = tokenResolver.getBearerToken.bind(tokenResolver) as () => Promise;
}

// Base map
createBaseMapDataSource(getBearerToken).then(omvDataSource => {
    mapView.addDataSource(omvDataSource);
    if (lookupServiceEnvironment === LookupEnvironment.HERE_CN) {
        addBaseMapCountryBorder(mapView, omvDataSource.dataProvider() as BaseMapDataProvider);
    }
});

const dataProvider = new PlatformDataProvider({
    hrn: geoJsonHrn,
    layer: geoJsonDataLayer,
    getToken: getBearerToken,
    environment: lookupServiceEnvironment
});

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

// geoJSON Data source
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider,
    intersectionAgent: new InteractiveIntersectionAgent(mapView),
    levelsWithData: [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

HERE をクリック してアプリを開きます。

この例 GeoJsonDataSourceでは、のさまざまなイベントにサブスクライブする方法を示します。 タイルがロードされた後、任意のタイルをロングクリックすると、トリガーされたイベントを確認できます。 イベントリスナーがEVENT_TILE_GETEVENT_TILE_DECODEDEVENT_BEFORE_TILE_DECODEEVENT_TILE_SELECT、およびEVENT_TILE_DESELECTのイベントに追加されます。

ソースコードの例


/*
 * Copyright (C) 2017-2023 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 {
    PlatformDataProvider,
    InteractiveIntersectionAgent,
    LookupEnvironment,
    BaseMapDataProvider
} from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    useToken,
    geoJsonDataLayer,
    geoJsonHrn,
    geoJsonLevelWithData,
    lookupServiceEnvironment,
} from "../config";
import {
    bearerTokenProvider,
    createBaseMapDataSource,
    InformationPanel,
    initializeMapView,
    setupTileSelection,
    createTokenResolver,
    addBaseMapCountryBorder
} from "./common";
import { MapControls } from "@here/harp-map-controls";
import { I18n, TileControlHandler } 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);

// Create info panel
const infoPanelMsg = I18n.translate("olpdi.examples.geojson-events.hint") + ``
    + I18n.translate("olpdi.examples.geojson-events.events-list-title") + `:`;
const infoPanel = new InformationPanel(infoPanelMsg, true);

let getBearerToken;
if (useToken) {
    getBearerToken = bearerTokenProvider;
} else {
    const tokenResolver = createTokenResolver(mapView);
    getBearerToken = tokenResolver.getBearerToken.bind(tokenResolver) as () => Promise;
}

// Base map
createBaseMapDataSource(getBearerToken).then(omvDataSource => {
    mapView.addDataSource(omvDataSource);
    if (lookupServiceEnvironment === LookupEnvironment.HERE_CN) {
        addBaseMapCountryBorder(mapView, omvDataSource.dataProvider() as BaseMapDataProvider);
    }
});

const dataProvider = new PlatformDataProvider({
    hrn: geoJsonHrn,
    getToken: getBearerToken,
    layer: geoJsonDataLayer,
    environment: lookupServiceEnvironment
});

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

// geoJSON Data source
const intersectionAgent = new InteractiveIntersectionAgent(mapView);
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider,
    intersectionAgent,
    levelsWithData: [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

HERE をクリック してアプリを開きます。

この例では、カタログのバージョン付レイヤーから GeoJSON データをロードする方法を示します。

ソースコードの例


/*
 * Copyright (C) 2017-2023 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 {
    PlatformDataProvider,
    InteractiveIntersectionAgent,
    LookupEnvironment,
    BaseMapDataProvider
} from "@here/interactive-datasource-protocol";
import { GeoJsonDataSource } from "@here/olp-geojson-datasource";
import {
    useToken,
    geoJsonContentTypeHrn,
    geoJsonContentTypeLayerVersioned,
    geoJsonContentTypeLevelWithData,
    lookupServiceEnvironment
} from "../config";
import {
    addBaseMapCountryBorder,
    bearerTokenProvider,
    createBaseMapDataSource,
    createTokenResolver,
    InformationPanel,
    initializeMapView,
    setupTileSelection
} from "./common";

import { MapControls } from "@here/harp-map-controls";
import { I18n, TileControlHandler } 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);

// Create info panel
const infoPanelMsg = I18n.translate("olpdi.examples.geojson-contenttype-versioned.hint");
new InformationPanel(infoPanelMsg);

let getBearerToken;
if (useToken) {
    getBearerToken = bearerTokenProvider;
} else {
    const tokenResolver = createTokenResolver(mapView);
    getBearerToken = tokenResolver.getBearerToken.bind(tokenResolver) as () => Promise;
}

// Base map
createBaseMapDataSource(getBearerToken).then(omvDataSource => {
    mapView.addDataSource(omvDataSource);
    if (lookupServiceEnvironment === LookupEnvironment.HERE_CN) {
        addBaseMapCountryBorder(mapView, omvDataSource.dataProvider() as BaseMapDataProvider);
    }
});

const dataProvider = new PlatformDataProvider({
    hrn: geoJsonContentTypeHrn,
    getToken: getBearerToken,
    layer: geoJsonContentTypeLayerVersioned,
    environment: lookupServiceEnvironment
});

// GeoJSON Data Source
const geoJsonDataSource = new GeoJsonDataSource({
    dataProvider,
    levelsWithData: [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
    levelsWithData: [geoJsonContentTypeLevelWithData],
    schemaProviderOptions: {
        enabled: false
    }
});
mapView.addDataSource(coverageDataSource);

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

geometrydataprovider / speedlimits / DI

HERE をクリック してアプリを開きます。

この例では、カスタムInteractiveDataSourceのインスタンスを作成し、DataInspectorインスタンスに動的に追加する方法を示します。 カスタム SpeedLimitsDataSource は、 HERE Map Content カタログから速度制限を表示します。 HERE Map Content ナビゲーション属性レイヤーから速度制限データを取得し、 HERE Map Content ロードトポロジレイヤーから道路のジオメトリ上に表示します。 制限速度のデータにはジオメトリ情報がないため、道路 - トポロジ & ジオメトリレイヤーの道路セグメントにマップされます。

ソースコードの例


/*
 * Copyright (C) 2017-2023 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 {
    PlatformDataProvider,
    InteractiveIntersectionAgent
} from "@here/interactive-datasource-protocol";
import {
    DataInspector,
    DataInspectorEventNames,
    InfoPanel,
    installInfoWidgetsWhenDataSourceReady,
    PanelDisplayMode
} from "@here/interactive-mapview-ui";
import {
    useToken,
    locale,
    showLanguageSelector,
    omvDataLayer,
    omvHostHrn,
    lookupServiceEnvironment,
    ribHrn,
    ribTopologyLayer,
    speedLimitTiles
} from "../config";
import { bearerTokenProvider } from "./common";
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,
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        baseMap: {
            hrn: omvHostHrn,
            layer: omvDataLayer
        },
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            zoomLevel: true,
            statusBar: true,
            searchField: true,
            decodedPanel: {
                enabled: true,
                initialState: PanelDisplayMode.Expanded,
                width: 400
            },
            statsPanel: {
                enabled: true,
                initialState: PanelDisplayMode.Collapsed
            },
            authForm: !useToken ? {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            } : undefined
        },
        toolbar: {
            enabled: true,
            fullScreenButton: true,
            languageSelector: showLanguageSelector
        },
        logMessages: true,
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true }
    },
    document.getElementById("map-here") as HTMLElement,
    undefined,
    true
);

let speedLimitsDataSource: SpeedLimitsDataSource | undefined;

dataInspector.addEventListener(
    DataInspectorEventNames.DATA_INSPECTOR_IS_READY,
    async () => {
        if (dataInspector.mapView === undefined || dataInspector.interactiveDataSource !== undefined) {
            return;
        }
        //create data provider
        const dataProvider = new PlatformDataProvider({
            hrn: ribHrn,
            layer: "navigation-attributes",
            getToken: dataInspector.getConfig().getBearerToken!,
            environment: lookupServiceEnvironment
        });
        await dataProvider.connect();
        // Create an instance of `SegmentAnchorGeometryDataProvider`, necessary for `SpeedLimitsDataSource`.
        const geometryDataProvider = new SegmentAnchorGeometryDataProvider(
            {
                hrn: ribHrn,
                layer: ribTopologyLayer,
                getToken: dataInspector.getConfig().getBearerToken!,
                environment: lookupServiceEnvironment
            }
        );
        await geometryDataProvider.connect();

        const selectedTiles = speedLimitsDataSource !== undefined
            ? [...speedLimitsDataSource.selectedPartitions]
            : [speedLimitTiles[0]];
        // Create a sample speed limits datasource which uses `RoadSegmentsDataProvider`.
        speedLimitsDataSource = new SpeedLimitsDataSource({
            dataProvider,
            geometryDataProvider
        });
        speedLimitsDataSource.isSelected = true;

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

        if (dataInspector.controlPanel !== undefined) {
            installInfoWidgetsWhenDataSourceReady(
                InfoPanel,
                speedLimitsDataSource,
                dataInspector.controlPanel.container,
                "info-panel"
            );
        }

        await dataInspector.setInteractiveDataSources([speedLimitsDataSource]);

        // Select speed limit tiles.
        for (const tile of selectedTiles) {
            dataInspector.tileControlHandler.selectTile(tile.toString(), true);
        }
    }
);

DI / object / store / layer

HERE をクリック してアプリを開きます。

この例では、データ インスペクターツールを使用して、通常のファイルブラウザと同様の方法でオブジェクトストアのレイヤーを探索する方法を示します。

ソースコードの例


/*
 * Copyright (C) 2021-2023 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 {
    useToken,
    locale,
    showLanguageSelector,
    lookupServiceEnvironment,
    objectStoreCatalogHrn,
    objectStoreLayer
} from "../config";
import { bearerTokenProvider } from "./common";

new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 11,
            theme: "../resources/normal.reduced.night.json",
            decoder: {
                url: "../decoder.bundle.js"
            }
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            authForm: !useToken ? {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            } : undefined
        },
        toolbar: {
            languageSelector: showLanguageSelector
        },
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true }
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSources: [{
            hrn: objectStoreCatalogHrn,
            layer: objectStoreLayer,
        }],
        enableCoverage: true
    }
);

DI / interactive / map / layer

HERE をクリック してアプリを開きます。

この例では、データ インスペクター を使用して HERE platform のインタラクティブなマップレイヤを探索する方法を示します。 インタラクティブな地図レイヤーでは、タイルをクリックしてデータを読み込む必要はありません。地図をパンまたはズームすると、データが自動的に取得されます。 データの密度と現在のズーム レベル によっては、結果から一部のデータ機能を削除できます。 ズームインして、より詳細な結果を表示します。

ソースコードの例


/*
 * Copyright (C) 2021-2023 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 {
    useToken,
    locale,
    showLanguageSelector,
    lookupServiceEnvironment,
    interactiveMapCatalogHrn,
    interactiveMapLayer
} from "../config";
import { bearerTokenProvider } from "./common";

new DataInspector(
    {
        mapView: {
            defaultZoomLevel: 11,
            theme: "../resources/normal.reduced.night.json",
            decoder: {
                url: "../decoder.bundle.js"
            }
        },
        monacoEditorWorkersBasePath: "../monaco-editor",
        translationsBasePath: "../resources/i18n/",
        streamSaverBasePath: "../resources/mitm/",
        defaultLocale: locale || undefined,
        getBearerToken: useToken ? bearerTokenProvider : undefined,
        widgets: {
            authForm: !useToken ? {
                tokenForm: false,
                accessKeyForm: true,
                localAuthForm: true
            } : undefined
        },
        toolbar: {
            languageSelector: showLanguageSelector
        },
        lookupServiceEnvironment,
        pageUrlParams: { enabled: true }
    },
    document.getElementById("map-here") as HTMLElement,
    {
        interactiveDataSources: [{
            hrn: interactiveMapCatalogHrn,
            layer: interactiveMapLayer,
        }],
        enableCoverage: true
    }
);

」に一致する結果は 件です

    」に一致する結果はありません