カメラ
HERE SDK for Android では、マップのビューを変更する方法がいくつか用意されています。 地図のスタイルを使用すると、地図の外観を変更できますが、カメラを使用してさまざまな視点から地図を参照できます。
たとえば、 HERE SDK for Android では、ターゲットの場所の設定、地図のチルト、ズームイン / ズームアウト、ベアリングの設定を行うことができます。
注
簡単に確認できます
- マップのビューを操作するには、
mapView.getCamera()
によって返されたCamera
を使用します。 - を呼び出し
camera.updateCamera(CameraUpdate cameraUpdate)
て、すべてのカメラのプロパティを 1 回の移動で設定します。 - を登録して、カメラへの変更を監視
CameraObserver
します。 CameraLimits
によって返されたオブジェクトに制限を設定することで、カメラに制約 camera.getLimits()
を設定します。 geoToViewCoordinates()
およびを使用 viewToGeoCoordinates()
して、ビューと地理的な座標空間を変換します。 getBoundingBox()
を呼び出して、現在表示されている領域の境界を取得します。
デフォルトでは、カメラはマップの中央に配置されます。 バードビューから見てまっすぐ下を見ると、マップは 北を向くになっています。 これは、デバイスの上端がマップの北を指していることを意味します。
地図を回転します
方位角を設定することで、地図の向きを変更できます。 「 Bearing 」は北から時計回りに度でカウントされるナビゲーション用語です。
図 : ベアリングの方向を設定します。 デフォルトでは、地図は 0 ° の方位に設定されています。 上の図に示されて いるように、 45 ° の角度を設定すると、地図が反時計回りに回転し、地図上で方位の方向が新しい上向きになり、デバイスの上端を指します。 これは、ハイキング中に特定の方向に紙の地図を保持して回転するのと似ています。 マップの上端が目的の方向を向いている場合は、自分自身の向きを変更する方が簡単です。 ただし、これが必ずしも真の北の方向であるとは限りません( bearing=0 ° )。
地図を傾けます
このカメラを使用して、 2D 地図の平坦な表面を 3D の遠近法にして、たとえば、地平線に向かって見える可能性のある長距離道路を表示することもできます。 デフォルトでは、地図はチルトされません(チルト = 0 ° )。
チルト角度は、ターゲット位置の垂直軸から計算されます。 観察者の下を直進するこの方向を 直下視することを、直下視と呼びます。 以下の図に示すように、地図を 45 ° 傾けると、カメラの鳥瞰図が 3D の視点に変わります。 これによってカメラが効果的に移動されますが、それ以降のチルト値は常にカメラのデフォルトの位置から適用されます。 チルト値が制限値を超えるか、または下回ると、マップが表示されない可能性があります。 これらの絶対値は、最小値 () の定数CameraLimits.MIN_TILT
として使用することも、実行時に取得することもできます。
try {
cameraLimits.setMaxTilt(CameraLimits.getMaxTiltForZoomLevel(12));
} catch (CameraLimits.CameraLimitsException e) {
}
このようにして、絶対範囲内で独自のカメラ制限を指定できます。
図 : マップを傾ける 地図の場所を変更します
新しいカメラターゲットを設定することで、地図の場所を変更できます。 既定では、ターゲットは地図の中央に配置されます。 全体的に、カメラの使用は非常に簡単です。 次のコードスニペットの例を参照してください。
mapView.getCamera().setTarget(new GeoCoordinates(52.518043, 13.405991));
mapView.getCamera().setZoomLevel(14);
mapView.getCamera().setTilt(60);
または、を設定すること CameraUpdate
で、 1 回の移動で複数の変更を適用できます。
カメラでは、特定の値を制限するカスタム範囲を指定することもできます。また、ユーザーがダブルタップジェスチャを実行して地図を操作した場合などに、これらの値の更新を監視する方法も提供されます。
新しいターゲットアンカーポイントを設定することで、 x=0.5, y=0.5 の位置にあるデフォルトのカメラアンカーポイントを変更できます。これは、マップ ビューの中心を示します。 ターゲットの位置は、回転やチルトなどのすべてのプログラム的なマップ変換、または新しいターゲットの位置の設定に使用されます。 ピンチ回転 や 2 本の指でのパン による地図のチルトなどの既定のジェスチャには影響しません。 次の方法で、新しいターゲットアンカーポイントを設定します。
Anchor2D transformationCenter = new Anchor2D(normalizedX, normalizedY);
camera.setTargetAnchorPoint(transformationCenter);
アンカーポイントは 、正規化 された座標で指定できます。 (0, 0) は、マップ ビューの左上隅と右下隅 (1,1) を示します。 そのため、アンカーを (1,1) に設定すると、新しいターゲットの場所がマップ ビューの右下隅に表示されます。 マップ ビュー外の値がクランプされます。
ターゲットに新しいアンカーポイントを設定しても、新しいターゲットの場所を設定するか、またはプログラムでマップをチルトまたは回転するまで、マップには表示されません。 タイル角度は、アンカーの水平座標に配置されます。 同様に、回転の中心点はアンカーと同じです。
この チュートリアルでは、ターゲットのアンカーポイントを使用する方法の例を示します。 マップ ビューの特定のポイントでズームインする方法を示します。
カメラの変化を聴いてください
オブザーバを追加すると、カメラ ( およびマップ ) が変更されたときにクラスに通知されます。
private final CameraObserver cameraObserver = new CameraObserver() {
@Override
public void onCameraUpdated(@NonNull CameraUpdate cameraUpdate) {
GeoCoordinates mapCenter = cameraUpdate.target;
Log.d(TAG, "Current map center location: " + mapCenter +
" Current zoom level: " + cameraUpdate.zoomLevel);
}
};
private void addCameraObserver() {
mapView.getCamera().addObserver(cameraObserver);
}
また、地図との高速でスムーズなインタラクションを手動で実行できます。 既定では、ダブルタップするとズームインし、パンすると指で地図を動かして移動できます。 デフォルトのマップビヘイビアーの詳細については、「ジェスチャ」セクションを参照してください。
チュートリアル : 場所にアニメーション化します
新しいカメラターゲットを設定すると、地図上の任意の場所にすぐにジャンプできます。遅延はありません。 ただし、状況によっては、現在の場所から新しい場所にゆっくりと移動する地図を表示する方がわかりやすい場合があります。
このよう な XY への移動 方法は、現在の地理座標と新しい地理座標を補間することで実現できます。 緯度と経度のペアの各中間セットを新しいカメラターゲットとして設定できます。 幸い、このアニメーション化されたトランジションは、 Android の アニメーションフレームワークで簡単に実現できます。
ご存じのように、このフレームワークで実行される各アニメーションには、TimeInterpolator
を指定できるValueAnimator
インスタンスのセットを含めることができます。 補間法では、時間の経過とともに値が変化する速度 ( または遅く ) を定義します。 この目的の AccelerateDecelerateInterpolator
ために、アニメーションの最後に減速効果を与えるを選択します。 を AnimatorSet
使用すると、複数の値を同時にアニメーション化できます。 次に、ある座標から別の座標への遷移だけでなく、回転、チルト、ズーム レベルなどの他の値も調整できます。
はじめにでは、まずインターフェイスの外観を定義します。 すべてのアニメーションコードをアプリケーションコードの REST から分離しておくことをお勧めします。 このため、という名前の新しいクラスを作成します CameraAnimator
。 使用量は次のようになります。
private static final float DEFAULT_ZOOM_LEVEL = 14;
...
cameraAnimator = new CameraAnimator(camera);
cameraAnimator.setTimeInterpolator(new AccelerateDecelerateInterpolator());
...
cameraAnimator.moveTo(geoCoordinates, DEFAULT_ZOOM_LEVEL);
このチュートリアルで紹介するのは以上です。 まず、依存関係としてCamera
オブジェクトを必要とする新しいCameraAnimator
インスタンスを作成する必要があります。 次に、 Android アニメーションフレームワークによって提供されるさまざまな補間法を試してみます。 このため、クラスで任意 TimeInterpolator
のインスタンスを受け取ることができます。 最後 moveTo()
に、新しいカメラのターゲット位置と希望のズーム レベルを受け入れます。
moveTo()
メソッドの実装は、アニメーションの開始に注意する必要があります。 アニメーションは、終了後に自動的に停止する必要があります ( 後で表示します ) 。
public void moveTo(GeoCoordinates destination, double targetZoom) {
CameraUpdate targetCameraUpdate = createTargetCameraUpdate(destination, targetZoom);
createAnimation(targetCameraUpdate);
startAnimation(targetCameraUpdate);
}
このメソッドを 1 行ずつ実行してみましょう。 CameraUpdate
まず、位置だけでなく、チルトや回転などの他のカメラパラメーターもアニメーション化する新しい AS を作成します。 次のようにして新しいを作成します CameraUpdate
。
private CameraUpdate createTargetCameraUpdate(GeoCoordinates destination, double targetZoom) {
double targetTilt = 0;
double targetBearing = camera.getBearing() > 180 ? 360 : 0;
return new CameraUpdate(targetTilt, targetBearing, targetZoom, destination);
}
実装からわかるように、アニメーションが終了したときに各プロパティの終了値を定義します。 現在設定されている傾きの値に関係targetTilt = 0
なく、非傾きのマップ () にアニメーション化して戻します。 回転移動の場合、到達速度を上げるベアリング値を決定する必要があります。 非回転の地図の方位角は 0 ° で、 360 ° と同じです。したがって、現在の方位値を確認します。 たとえば、 200 ° の場合は、 360 ° に達するまでアニメーション化が速くなります。
結果 CameraUpdate
のインスタンスには、目的の終了状態の必要なすべての値が保持されます。 実際のアニメーションを作成するには、このクラスが必要です。
private void createAnimation(CameraUpdate cameraUpdate) {
valueAnimatorList.clear();
ValueAnimator zoomValueAnimator = createAnimator(camera.getZoomLevel(), cameraUpdate.zoomLevel);
ValueAnimator tiltValueAnimator = createAnimator(camera.getTilt(), cameraUpdate.tilt);
ValueAnimator bearingValueAnimator = createAnimator(camera.getBearing(), cameraUpdate.bearing);
ValueAnimator latitudeValueAnimator = createAnimator(
camera.getTarget().latitude, cameraUpdate.target.latitude);
ValueAnimator longitudeValueAnimator = createAnimator(
camera.getTarget().longitude, cameraUpdate.target.longitude);
valueAnimatorList.add(zoomValueAnimator);
valueAnimatorList.add(tiltValueAnimator);
valueAnimatorList.add(bearingValueAnimator);
valueAnimatorList.add(latitudeValueAnimator);
valueAnimatorList.add(longitudeValueAnimator);
longitudeValueAnimator.addUpdateListener(animation -> {
float zoom = (float) zoomValueAnimator.getAnimatedValue();
float tilt = (float) tiltValueAnimator.getAnimatedValue();
float bearing = (float) bearingValueAnimator.getAnimatedValue();
float latitude = (float) latitudeValueAnimator.getAnimatedValue();
float longitude = (float) longitudeValueAnimator.getAnimatedValue();
GeoCoordinates intermediateGeoCoordinates = new GeoCoordinates(latitude, longitude);
camera.updateCamera(new CameraUpdate(tilt, bearing, zoom, intermediateGeoCoordinates));
});
}
前述のように、ArrayList
に保存するAnimator
インスタンスのセットを作成します。 新しいアニメーションを開始する前に、前のアニメーションからリストを消去します ( 存在する場合 ) 。 ValueAnimator
5 つのインスタンスが必要です。
-
zoomValueAnimator
: 現在のズーム レベルからターゲットズーム レベルに補間します。 -
tiltValueAnimator
: 現在のチルト値からターゲットのチルト値までを補間します。 -
bearingValueAnimator
: 現在のベアリング角度からターゲットベアリング値までを補間します。 これにより、マップが効果的に回転します。 -
latitudeValueAnimator
および longitudeValueAnimator
: 両方とも、現在のターゲット位置から目的の新しいターゲットまでの単一の座標を補間します。
各アニメーターを作成するコードは同じであるため、次の別々のメソッドに外部化しました。
private ValueAnimator createAnimator(double from, double to) {
ValueAnimator valueAnimator = ValueAnimator.ofFloat((float) from, (float )to);
if (timeInterpolator != null) {
valueAnimator.setInterpolator(timeInterpolator);
}
return valueAnimator;
}
各は ValueAnimator
、 float 値および以前に設定された値を想定 timeInterpolator
してい 何も設定されていない場合、アニメーションフレームワークはデフォルトの補間法を使用します。
createAnimation()
メソッドに戻り valueAnimatorList
、すべてのアニメーターをクラスメンバーに追加します。 後でアニメーションを開始する場合は、この一覧表が必要になります。
次のステップでは、 end 値に達するまで定期的に呼び出されるリスナーを追加します。 このリスナー内では、アニメーションフェーズ中に現在の中間値をすべて取得します。 すべてのアニメーターをAmimationSet
で一緒に再生するので、アニメーションフレームワークでは、指定したtimeInterpolator
に従って各「アニメーション化」値が更新されるように注意してください。 地図を移動するには、地図のカメラを更新するだけで済みます。この方法を使用すると簡単に移動できます。
GeoCoordinates intermediateGeoCoordinates = new GeoCoordinates(latitude, longitude);
camera.updateCamera(new CameraUpdate(tilt, bearing, zoom, intermediateGeoCoordinates));
これにより、マップの外観が指定した値に即座に変更されます。 このコードは毎秒何度も実行されるため、人間の目に滑らかなアニメーションとして表示されます。
最後に、アニメーションを開始します。
private void startAnimation(CameraUpdate cameraUpdate) {
if (animatorSet != null) {
animatorSet.cancel();
}
animatorSet = new AnimatorSet();
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
camera.updateCamera(cameraUpdate);
}
});
animatorSet.playTogether(valueAnimatorList);
animatorSet.setDuration(animationDurationInMillis);
animatorSet.start();
}
は AnimatorSet
、 CameraAnimator
1 つのインスタンスのみを許可するように、クラスで静的インスタンスとして定義されています。 新しいアニメーションを作成する前に、前のアニメーションをキャンセルできます。 また、 animatorSet
中断によって一部のフレームがスキップされる場合に備えて、リスナーをに設定して、カメラを目的の終了状態に更新することもできます。 ただし、カメラの更新状態を希望の状態にします。
実際に電話start()
をかける前に、一緒に再生するValueAnimator
インスタンスのリストを設定します。 また、期間の長さも指定します。 で animationDurationInMillis
は、 2000 ミリ秒を設定しました。 どのくらい遠くに行っても、地球の中を動き回る必要があっても、アニメーションの所要時間は 2 秒に抑えたいと思います。
これは、を使用して、ある場所から別の場所へのカスタムトランジションを実装する方法の一例にすぎ Camera
ません。 さまざまな補間法、またはカスタムの補間法を使用することで、任意のアニメーションスタイルを実現できます。 クラシック なリボン トランジション(ズームアウトしてから、もう一度ズームイン)から、直線的に進む 他のトランジションへの直線的なトランジションまでを切り替えます。