ガイド変更履歴HERE SDK API references
ガイド

UI ビルディング ブロックを追加する

このセクションでは、HERE SDKのサービスの一部としてすでに利用可能なさまざまなUI要素と関連するコードスニペットについて説明します。運転操作手順や運転操作アイコンアセットから、視覚的なルート表現まで、これらの要素をアプリケーションインターフェースに統合する方法を確認します。今後、再利用可能なUIビルディングブロックの追加が計画されています。

運転指示を取得する

Routeオブジェクトの各Sectionには、目的地に到達するためにユーザーが従う必要がある運転指示が含まれています。それぞれの右左折では、Maneuverオブジェクトに運転操作を実行する必要がある場所とアクションが含まれます。アクションは、「出発」などのアクションや「左折」などの指示を示す場合があります。

let sections = route.sections
for section in sections {
    logManeuverInstructions(section: section)
}

セクションごとの運転指示にアクセスするコードは次のとおりです。

private func logManeuverInstructions(section: heresdk.Section) {
    print("Log maneuver instructions per route section:")
    let maneuverInstructions = section.maneuvers
    for maneuverInstruction in maneuverInstructions {
        let maneuverAction = maneuverInstruction.action
        let maneuverLocation = maneuverInstruction.coordinates
        let maneuverInfo = "\(maneuverInstruction.text)"
            + ", Action: \(maneuverAction)"
            + ", Location: \(maneuverLocation)"
        print(maneuverInfo)
    }
}

これは、ルート全体を書面で説明する運転指示リストを簡単に作成するのに役立ちます。たとえば、ManeuverAction列挙型を使用して、独自のルート検索エクスペリエンスを構築できます。

注 (Navigateにのみ適用)

ナビゲーション中のManeuver指示テキスト (maneuverInstruction.text) は、NavigatorまたはVisualNavigatorから取得された場合は空になります。これには、Routeインスタンスから取得された場合のローカライズされた指示のみが含まれます。ManeuverAction列挙型は、ナビゲーション中に視覚的なインジケーターを表示するために使用されることが想定されており、テキストによる指示は、移動を開始する前に運転指示をプレビューするリストに適しています。

反対に、maneuverInstruction.roadTextsmaneuverInstruction.nextRoadTextsmaneuverInstruction.exitSignTexts は、ナビゲーション中に経路誘導運転操作の一部として表示されることを意図しているため、ManeuverNavigator または VisualNavigator から取得された場合には空になりません。Routeインスタンスから取得した場合は、これらの属性は常に空になります。

注 (Exploreにのみ適用)

属性maneuverInstruction.roadTextsmaneuverInstruction.nextRoadTextsmaneuverInstruction.exitSignTextsはナビゲーション中に経路誘導運転操作の一部として表示されることを目的としているため、Navigateなどのライセンスを持つユーザーのみが使用できます。Routeインスタンスから取得した場合は、これらの属性は常に空になります。

「APIリファレンス」では利用可能な運転操作アクションの概要を確認できます。

以下の表は、すべてのManeuverActionアイテムとプレビューの説明およびアセットの例をまとめたものです。HERE SDK 自体には運転操作アイコンが付属していないことに注意してください。アセットは、オープンソースのHERE Icon Libraryの一部として、さまざまな密度のSVGまたはソリッドPNGとして利用できます。

利用可能な運転操作アクションは、「APIリファレンス」に記載されている順序で並べ替えられています。

運転操作アクション 説明の例 アイコンの例
arrive 「~に到着」などの到着運転操作。中間の経由地の説明の例:「<道路名 | 経由地> に到着」。ルートの目的地の場合:「<道路名 | 目的地名 | 目的地> に到着」。 到着
continueOn 「<道路名>をそのまま走行」などの運転操作を続行します。 そのまま走行
depart 「<道路名>を出発」などの出発運転操作。 出発
enterHighwayFromLeft 左側から高速道路に合流します。これは、ドライバーが右に移動して高速道路に入る必要があることを意味します。このような運転操作は、一般道路の左側 (左側通行) を走行する国でのみ実行されます。 左側から高速道路に合流
enterHighwayFromRight 右側から高速道路に合流します。これは、ドライバーが左に移動して高速道路に入る必要があることを意味します。このような運転操作は、一般道路の右側 (右側通行) を走行する国でのみ実行されます。 右側から高速道路に合流
leftExit 「左側の出口から出て<次の道路名>に合流」などの左側出口運転操作。 左側出口
leftFork 「左車線を走行して<次の道路名>に合流」などの左車線運転操作。 左車線
leftRamp 「左ランプを走行」などの左ランプ運転操作。 左ランプ
leftRoundaboutEnter 「ロータリーに入る」などのロータリー運転操作 (左側通行)。
leftRoundaboutExit1 「ロータリーの最初の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口1アイコン
leftRoundaboutExit10 「ロータリーの10番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口10アイコン
leftRoundaboutExit11 「ロータリーの11番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口11アイコン
leftRoundaboutExit12 「ロータリーの12番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口12アイコン
leftRoundaboutExit2 「ロータリーの2番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口2アイコン
leftRoundaboutExit3 「ロータリーの3番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口3アイコン
leftRoundaboutExit4 「ロータリーの4番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口4アイコン
leftRoundaboutExit5 「ロータリーの5番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口5アイコン
leftRoundaboutExit6 「ロータリーの6番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口6アイコン
leftRoundaboutExit7 「ロータリーの7番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口7アイコン
leftRoundaboutExit8 「ロータリーの8番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口8アイコン
leftRoundaboutExit9 「ロータリーの9番目の出口を出る」などのロータリー運転操作 (左側通行)。 左ロータリー出口9アイコン
leftRoundaboutPass 「ロータリーを通過する」などのロータリー運転操作 (左側通行)。 左ロータリーを通過アイコン
leftTurn 「<次の道路名>を左折」などの左折運転操作。 左折アイコン
leftUTurn 「<次の道路名>でUターン」などの左Uターン運転操作。 左Uターンアイコン
middleFork 「中央車線を走行して<次の道路名>に合流」などの中央車線運転操作。 中央車線アイコン
rightExit 「右側の出口から出て<次の道路名>に合流」などの右側出口運転操作。 右側出口アイコン
rightFork 「右車線を走行して<次の道路名>に合流」などの右車線運転操作。 右車線アイコン
rightRamp 「右ランプを走行」などの右ランプ運転操作。 右ランプアイコン
rightRoundaboutEnter 「ロータリーに入る」などのロータリー運転操作 (右側通行)。 右側ロータリー進入アイコン
rightRoundaboutExit1 「ロータリーの最初の出口を出る」などのロータリー運転操作 (右側通行)。 右側ロータリー出口1アイコン
rightRoundaboutExit10 「ロータリーの10番目の出口を出る」などのロータリー運転操作 (右側通行)。 右側ロータリー出口10アイコン
rightRoundaboutExit11 「ロータリーの11番目の出口を出る」などのロータリー運転操作 (右側通行)。 右側ロータリー出口11アイコン
rightRoundaboutExit12 「ロータリーの12番目の出口を出る」などのロータリー運転操作 (右側通行)。 右ロータリー出口12アイコン
rightRoundaboutExit2 「ロータリーの2番目の出口を出る」などのロータリー運転操作 (右側通行)。 右ロータリー出口2アイコン
rightRoundaboutExit3 「ロータリーの3番目の出口を出る」などのロータリー運転操作 (右側通行)。 右ロータリー出口3アイコン
rightRoundaboutExit4 「ロータリーの4番目の出口を出る」などのロータリー運転操作 (右側通行)。 右ロータリー出口4アイコン
rightRoundaboutExit5 「ロータリーの5番目の出口を出る」などのロータリー運転操作 (右側通行)。 右ロータリー出口5アイコン
rightRoundaboutExit6 「ロータリーの6番目の出口を出る」などのロータリー運転操作 (右側通行)。 右ロータリー出口6アイコン
rightRoundaboutExit7 「ロータリーの7番目の出口を出る」などのロータリー運転操作 (右側通行)。 右ロータリー出口7アイコン
rightRoundaboutExit8 「ロータリーの8番目の出口を出る」などのロータリー運転操作 (右側通行)。 右ロータリー出口8アイコン
rightRoundaboutExit9 「ロータリーの9番目の出口を出る」などのロータリー運転操作 (右側通行)。 右ロータリー出口9アイコン
rightRoundaboutPass 「ロータリーを通過する」などのロータリー運転操作 (右側通行)。 右側ロータリー通過アイコン
rightTurn 「<次の道路名>を右折」などの右折運転操作。 右折アイコン
rightUTurn 「<次の道路名>で右Uターン」などの右Uターン運転操作。 右Uターンアイコン
sharpLeftTurn 「左に急旋回して<次の道路名>に合流」などの左急旋回運転操作。 急な左折アイコン
sharpRightTurn 「右に急旋回して<次の道路名>に合流」などの右急旋回運転操作。 急な右折アイコン
slightLeftTurn 「道なりに左側を進んで<次の道路名>に合流」などの道なり左側走行運転操作。 わずかに左折アイコン
slightRightTurn 「道なりに右側を進んで<次の道路名>に合流」などの道なり右側走行運転操作。 わずかに右折アイコン

現時点では、leftRoundaboutPassrightRoundaboutPassのHEREアセットはSVGとしてのみ利用可能であり、一部の運転操作アセットはサブフォルダー「wego-fallback-roundabout」でのみ利用できます。

道路標識アイコンを取得する

iconProvider.createRoadShieldIcon(...)を使用すると、「A7」や「US-101」などの道路番号がマップ ビューにすでに表示されているように、非同期でBitmapを作成できます。

道路標識アイコンの作成はオフラインで行われ、インターネット接続は必要ありません。アイコンの作成に必要なデータは、Route自体から取得されますが、手動で入力することもできます。

運転操作プレビューに表示される道路標識の実装例は「Rerouting」サンプルの一部です。入手するには、GitHubのサンプルアプリリポジトリにアクセスします。これにはHERE SDK (Navigate) が必要ですが、IconProviderのコードは他のライセンスでも使用でき、たとえば、ルートプレビューの一部として道路標識アイコンを表示できます。

地図にルートを表示する

以下のコードスニペットは、出発地と目的地を含むルートの各座標間に描画されるMapPolylineを使用して地図にルートを表示する方法を示しています。

let routeGeoPolyline = route.geometry
let widthInPixels = 20.0
let polylineColor = UIColor(red: 0, green: 0.56, blue: 0.54, alpha: 0.63)
do {
    let routeMapPolyline =  try MapPolyline(geometry: routeGeoPolyline,
                                            representation: MapPolyline.SolidRepresentation(
                                                lineWidth: MapMeasureDependentRenderSize(
                                                    sizeUnit: RenderSize.Unit.pixels,
                                                    size: widthInPixels),
                                                color: polylineColor,
                                                capShape: LineCap.round))

    mapView.mapScene.addMapPolyline(routeMapPolyline)
} catch let error {
    fatalError("Failed to render MapPolyline. Cause: \(error)")
}

mapView.mapScene.addMapPolyline(routeMapPolyline)

以下の最初のスクリーンショットは、追加の経由地のないルート、つまりルートセクションが1つだけのルートを示しています。出発地と目的地は、緑色の丸のマップ マーカーで示されています。円で囲まれたオブジェクトを描画するコードはここには示されていませんが、興味があればサンプルのソースコードから確認できます。

2 番目のスクリーンショットは上記と同じルートを示していますが、赤丸のマップ マーカーで示された 2 つの追加の stopover 経由地があります。このため、ルートには3つのルートセクションが含まれています。

stopoverで経由地を追加すると、ルートが複数のセクションに分割され、ルートはこれらのポイントを通過して、各ポイントで運転操作指示を生成するように強制されます。

内部的には、MapPolylineのレンダリングが非常に長いルート向けに最適化されていることに注意してください。たとえば、ズームレベルが高ければすべての座標をレンダリングする必要はありませんが、ズームレベルが低いとルート全体が表示されません。このためのアルゴリズムは公開されていませんが、基本原理はHEREのflexible-polylineオープンソースプロジェクトで見ることができます。

ルートにズームする

ユースケースによっては、計算されたルートにズームすると便利な場合があります。カメラクラスには、ルートが収まるようにビューポートを調整する便利なメソッドが用意されています。

let routeGeoBox = route?.boundingBox
camera.lookAt(area: routeGeoBox!,
              orientation: GeoOrientationUpdate(bearing: nil, tilt: nil))

ここでは、ルートオブジェクトの囲みバウンディング ボックスを使用します。これを使用すると、カメラを即座に更新できます。指定されたバウンディング長方形がビューポートに正確に収まるように、カメラのズームレベルとターゲット ポイントが変更されます。さらに、方向を指定してさらに多くのカメラパラメーターを指定することもできます。ここではデフォルト値をそのまま使用します。lookAt()を呼び出すとビューが即座に変更されることに注意してください。

ほとんどのユースケースでは、アニメーションを使用してルートにズームすると、ユーザーエクスペリエンスが向上します。以下に、GeoBoxに50ピクセルの追加のパディングを加えてズームする例を示します。

func animateToRoute(route: Route) {
    // Untilt and unrotate the map.
    let bearing: Double = 0
    let tilt: Double = 0

    // We want to show the route fitting in the map view with an additional padding of 50 pixels.
    let origin:Point2D = Point2D(x: 50.0, y: 50.0)
    let sizeInPixels:Size2D = Size2D(width: mapView.viewportSize.width - 100, height: mapView.viewportSize.height - 100)
    let mapViewport:Rectangle2D = Rectangle2D(origin: origin, size: sizeInPixels)

    // Animate to the route within a duration of 3 seconds.
    let update:MapCameraUpdate = MapCameraUpdateFactory.lookAt(area: route.boundingBox, orientation: GeoOrientationUpdate(GeoOrientation(bearing: bearing, tilt: tilt)), viewRectangle: mapViewport)
    let animation: MapCameraAnimation = MapCameraAnimationFactory.createAnimation(from: update, duration: TimeInterval(3), easing: Easing(EasingFunction.inCubic))
    mapView.camera.startAnimation(animation)
}

CameraKeyframeTracksサンプルアプリでは、これがどのように見えるかを示しています。

ルートに交通情報を表示する

ルート上に交通状況を視覚化する方法については、交通流に沿ってポリラインをレンダリングする方法やカスタムの交通情報オーバーレイなど、「ルート上の交通状況を視覚化する」参照してください。


EN 日本語

HERE documentation

Find answers to your product and technical questions

Documentation

What's new

Videos

EN 日本語

HERE ドキュメント

製品や技術に関する質問の答えを見つけましょう。より多くの内容と最新の情報については、英語版をご覧ください。

ドキュメント

ダイナミックマップ

動的コンテンツ関連のAPIをアプリやサービスに活用して、ドライバーが安全・快適かつ予定どおりに目的地へ到着できるよう支援します。

地図とデータ

世界中を走行する多数のマッピング車両から得られる最新の位置情報データを活用し、精度の高い地図やカスタムレイヤーを構築できます。

最新情報

動画

(function () { const input = document.querySelector('input[data-typeahead]'); if (!input) return; // Prevent the form from submitting/navigating input.closest('form')?.addEventListener('submit', e => e.preventDefault()); input.addEventListener('input', function () { const q = this.value.trim().toLowerCase(); document.querySelectorAll('.nav-group-name').forEach(group => { let anyVisible = false; group.querySelectorAll('.nav-group-task').forEach(task => { const text = task.textContent.trim().toLowerCase(); const show = !q || text.includes(q); task.style.display = show ? '' : 'none'; if (show) anyVisible = true; }); // Hide the whole group header if nothing matches group.style.display = anyVisible || !q ? '' : 'none'; }); }); })(); (function () { function onTokenClick(event) { var link = event.target.closest('.sdk-for-ios .item .token'); if (!link) return; event.preventDefault(); console.log('token clicked', link.textContent.trim()); var item = link.closest('.item'); if (!item) return; var content = item.querySelector('.height-container'); if (!content) { console.log('no .height-container found for item', item); return; } var isHidden = window.getComputedStyle(content).display === 'none'; content.style.display = isHidden ? 'block' : 'none'; link.classList.toggle('token-open', isHidden); var href = link.getAttribute('href'); if (href) { if (history.pushState) history.pushState({}, '', href); else location.hash = href; } } function openHashTarget() { var hash = window.location.hash.slice(1); if (!hash) return; var anchor = document.querySelector('.sdk-for-ios a[name="' + hash + '"]'); if (!anchor) return; var item = anchor.closest('.item'); if (!item) return; var link = item.querySelector('.token'); var content = item.querySelector('.height-container'); if (!link || !content) return; content.style.display = 'block'; link.classList.add('token-open'); } function init() { console.log('HERE SDK accordion init'); openHashTarget(); } document.removeEventListener('click', onTokenClick); document.addEventListener('click', onTokenClick); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } window.addEventListener('hashchange', openHashTarget); window.addEventListener('pageLoad', init); })();