ベストプラクティス

この記事では、最適な地図の応答性について、 HERE Maps API for Javascript を最も効率的に使用できるように支援するためのベストプラクティスについて説明します。

アイコンを再利用します

Maps API for JavaScript で H.map.Icon は、このクラスは再利用可能なビジュアルマップ マーカーを表します。 マップのパフォーマンスを最適化 H.map.Icon するには、各マーカーに新しいインスタンスを作成する代わりに、できるだけ多くのマーカーオブジェクトでアイコンインスタンスを再利用します。

次のコードは、 icon 新しいマーカーごとに新しいオブジェクトを作成するための非推奨の方法を示しています。

// Array of anchor points for markers
var points = [...],
    markers = [];

for (var i = 0; i < points.length; i++) {
    markers.push(new H.map.Marker(points[i], {
        // A new identical Icon instance is created at each iteration 
        // of the loop - do not do this:
        icon: new H.map.Icon('graphics/markerHouse.png')
      }));
}

マーカーごとに新しいiconオブジェクトを作成する代わりに 、以下に示すように、すべてのH.map.Markerインスタンスで単一のH.map.Iconインスタンスを再利用します。

// Array of anchor points for markers
var points = [...],
    markers = [],
    // Create single Icon instance
    icon = new H.map.Icon('graphics/markerHouse.png');

for (var i = 0; i < points.length; i++) {
    markers.push(new H.map.Marker(points[i], {
        // Reuse the Icon instance:
        icon: icon
      }));
}

上記のアプローチにより、パフォーマンスの向上とメモリフットプリントの削減を実現できます。

多数の地図マーカーを表示する必要がある場合 は、マーカーのクラスタリングを検討してください。

"onAttach" および "onDetach" コールバックはシンプルにしてください

DomMarkerを使用する場合 は、DomIconコンストラクタにオプションonAttachonDetachオプションを渡して、DomIconインスタンスを使用するすべてのDomMarkersののイベントリスナーを追加できます。

これらのコールバックは DomMarker 、がマップに表示されるたび、またはマップビューポイントから消去されるたびに呼び出されます。 このため、これらのコールバックでは高価な計算を行わないことをお勧めします。そうしないと、マップのパンニングやズームのパフォーマンスが著しく低下する可能性があります。

次の例は、このようなパフォーマンスの低下を引き起こす非推奨のアプローチを示しています。

// Assume that domElement is an already defined DOM element
// and contains a large number of children:
var domIcon = new H.map.DomIcon(domElement, {
    onAttach: function(clonedElement, domIcon, domMarker) {
        // Avoid expensive computation inside onAttach 
        // Such as quering the DOM:
        var defaultButton = clonedElement.querySelector('.btn-default');
        var infoButton = clonedElement.querySelector('.btn-info');

        defaultButton.addEventListener('click', onDefaultClick);
        infoButton.addEventListener('click', onInfoClick);
    },
    onDetach: function(clonedElement, domIcon, domMarker) {
        // Avoid expensive computation inside onDetach
        // such as quering the DOM
        var defaultButton = clonedElement.querySelector('.btn-default');
        var infoButton = clonedElement.querySelector('.btn-info');

        defaultButton.removeEventListener('click', onDefaultClick);
        infoButton.removeEventListener('click', onInfoClick);
    }
});

onAttach()/onDetach() のコードで示されているイベントの委任などの技術を使用して、必要なすべてのアセットを事前に計算するか、または計算をイベントコールバックにオフロードしてください。

// Use event bubbling to handle all events on the parent node itself,
// and perform computations only when needed.
function onMarkerClick(e) {
    var targetClassName = e.target.className;
    if (targetClassName  === 'btn-default') {
        onDefaultClick(e);
    } else if (targetClassName  === 'btn-info') {
        onInfoClick(e);
    }
}

var domIcon = new H.map.DomIcon(domElement, {
    onAttach: function(clonedElement, domIcon, domMarker) {
        // Simply subscribe to the event:
        domElement.addEventListener('click', onMarkerClick);
    },
    onDetach: function(clonedElement, domIcon, domMarker) {
        // Simply unsubscribe from the event:
        domElement.removeEventListener('click', onMarkerClick);
    }
});

"mapviewchange" ではなく "mapviewchangeend" イベントを使用します

これらのイベント mapviewchangemapviewchangeend は似ているようです。どちらもマップのビューポイントに対する変更の処理に使用できますが、その影響は異なります。 mapviewchange は、ビューポイントの状態を変更するプロセスの各アニメーションステップで呼び出されます。 多くの場合、この操作は過剰です。 たとえば、ユーザーがマップをダブルクリックするたびに、現在のズーム レベルで UI 要素を複数回更新するのは非効率的です。

// Displays current zoom level to the end user:
function displayZoomLevel() {...}

// A listener updates the map zoom level on each map view change
// -- this occurs more than 20 times on a double-click on the map, 
// inefficient and to be avoided:
map.addEventListener('mapviewchange', function () {
    var zoom = map.getZoom();

    // This function is called more than 20 times on a double-click on the map!
    displayZoomLevel(zoom);
});

mapviewchangeend一方、ビューポイントの変更が完了すると、が 1 回だけ呼び出されます。そのため、このイベントを使用してマップビューポイントを更新することをお勧めします。

/* 
    Displays current zoom level to the end user 
 */
function displayZoomLevel() {...}

// A listener updates the map zoom level -- it is called once when the map 
// view change is complete.
map.addEventListener('mapviewchangeend', function () {
    var zoom = map.getZoom();

    // The function that displays the zoom level is called only once, 
    // after zoom level changed
    displayZoomLevel(zoom);
});

mapviewchangeend イベントはの「デバウンス」バージョン mapviewchangeである mapviewchangeendため、原則としてより効率的に使用できます。

組み込みのアニメーション機能を使用します

マップの中心の変更、ズームの変更、またはその両方によって生じるトランジションなど、さまざまなマップ状態間のトランジションをアニメーション化する必要がある場合は、常にマップエンジンの組み込みのアニメーション機能を使用してください。

setZoom()setCenter()setViewBounds()などのインスタンスメソッドをマップ し、 アニメーション化されたトランジションを適用するかどうかを示す 2 番目の引数を受け入れます。

以下のスニペットに示されているように、独自のズームアニメーションを作成しないことをお勧めします。

// Assumption: 'map' is initialized and available.
var currentZoom = map.getZoom();
var endZoom = currentZoom + 3;

// Update zoom level on each animation frame,
// till we reach endZoom:
function step() {
    currentZoom += 0.05;
    map.setZoom(currentZoom);

    (currentZoom < endZoom) && requestAnimationFrame(step);
}

// Start zoom animation
step();

代わり setZoom() に、オプションの 2 番目のパラメーターを使用してメソッドを呼び出し、アニメーションを実行します。

/**
 * Assumption: 'map' is initialized and available
 */
// Call getZoom() with an optional second parameter,
// indicating that an animation is to be performed:
map.setZoom(map.getZoom() + 3, true);

"SpatialStyle" インスタンスを読み取り専用オブジェクトとして使用します

のインスタンス SpatialStyle は、読み取り専用オブジェクトとして使用されます。 プロパティの変更は安全ではありません。また、表示の不整合が生じる可能性があります。

以下のスニペットは 、あるSpatialオブジェクトを別のオブジェクトSpatialStyleに再利用する例を示しています。 SpatialStyle この操作は、オブジェクトを変更しないため有効です。

// Assumption: 'spatial1' and 'spatial2' are initialized and available.
// Get current style of the first spatial:
var style = spatial1.setStyle();

// Reusing an existing SpatialStyle object is fine,
// because we are not modifying it:
spatial2.setStyle(style);

Spatial 1 つのオブジェクトのスタイルを別のオブジェクトで再利用する場合に、 1 fillColor つの変更で getStyle メソッドによって返されたオブジェクトを変更すると、最初の空間の視覚的な表現に決定論的でない結果が生じることがあります。

// Assumption: 'spatial1' and 'spatial2' are initialized and available.
// Get current style of the first spatial:
var style = spatial1.getStyle();

// Modification of a SpatialStyle object -- never do this
style.fillColor = 'red';

// If we now apply the modified style to the second spatial, the results may be
// inconsistent -- sometimes the fillColor change takes effect, but not always!
spatial2.setStyle(style);

スタイルを変更する正しい方法は、次 のコード例に示すように、新しいSpatialStyleオブジェクトを作成するか、または既存のオブジェクトでgetCopy()メソッドを使用することです。

/**
 * Assumption: 'spatial1' and 'spatial2' are initialized and available.
 */
// Get the current style of the first spatial and get an extended version
// by calling getCopy() method on it
var style = spatial1.setStyle().getCopy({
    fillColor: 'red'
});

// Now changing the style of the second class is completely safe and 
// produces the expected results consistently:
spatial2.setStyle(style);

したがって、一般的なルール は、既存のSpatialStyleオブジェクトを複数回再利用することですが、変更する必要がある場合は、新しいgetCopy()オブジェクトを使用するか、または作成します。

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

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