Caméra et vue

Dans le SDK Maps pour Android, il est possible d'incliner et de faire pivoter les cartes avec des gestes simples, ce qui permet aux utilisateurs de choisir l'orientation qui leur convient le mieux. À n'importe quel niveau de zoom, vous pouvez effectuer un panorama sur la carte ou modifier sa perspective avec une latence très faible grâce au format réduit des tuiles de carte vectorielles.

Exemples de code

Le dépôt ApiDemos sur GitHub inclut un exemple qui présente les fonctionnalités de la caméra :

Introduction

À l'instar de Google Maps sur le Web, le SDK Maps pour Android effectue représente la surface de la terre (sphère) sur l'écran de votre appareil (surface plane) en utilisant une projection de Mercator. Vers l'est et vers l'ouest, la carte est répétée à l'infini car la terre tourne sur elle-même. Vers le nord et le sud, la carte est limitée à environ 85 degrés nord et 85 degrés sud.

Remarque : la projection de Mercator a une largeur finie sur le plan longitudinal, mais une hauteur infinie sur le plan latitudinal. Nous « coupons » l'image de la carte de base en utilisant la projection de Mercator à environ +/- 85 degrés pour rendre carrée la carte qui en résulte et ainsi simplifier la logique de sélection des tuiles.

Le SDK Maps pour Android vous permet de changer le point de vue de l'utilisateur de la carte en modifiant la caméra de la carte.

Les modifications apportées à la caméra ne modifieront pas les repères, les superpositions ou tout autre élément graphique que vous avez ajouté, mais vous pourrez toujours modifier ces éléments pour qu'ils s'intègrent mieux à la nouvelle vue.

Étant donné que vous pouvez écouter les gestes de l'utilisateur sur la carte, vous pouvez modifier la carte en réponse aux requêtes de l'utilisateur. Par exemple, la méthode de rappel OnMapClickListener.onMapClick() répond à un seul toucher sur la carte. Étant donné que la méthode reçoit la latitude et la longitude de l'emplacement du toucher, vous pouvez répondre en effectuant un panorama ou un zoom sur ce point. Des méthodes similaires sont disponibles pour répondre aux touchers sur la bulle d'un repère ou pour répondre à un geste de glissement sur un repère.

Vous pouvez également écouter les mouvements de la caméra, afin que votre application reçoive une notification lorsque la caméra commence à bouger, est en train de bouger ou arrête de bouger. Pour plus d'informations, consultez le guide des événements liés aux changements de caméra.

Bâtiments en 3D sur la carte

De nombreuses villes, vues en gros plan, permettront d'afficher les bâtiments en 3D, comme sur l'image ci-dessous de Vancouver au Canada. Vous pouvez désactiver les bâtiments en 3D en appelant GoogleMap.setBuildingsEnabled(false).

Carte de Vancouver, Canada

Position de la caméra

La vue de la carte est modélisée comme une caméra orientée vers le bas sur une surface plane. La position de la caméra (et par conséquent le rendu de la carte) est indiquée par les propriétés suivantes : position cible (latitude/longitude), orientation, inclinaison et zoom.

Schéma des propriétés de la caméra

Cible (zone géographique)

La cible de la caméra est la position du centre de la carte, spécifiée en tant que coordonnées de latitude et longitude.

Orientation

La direction est le cap vers lequel pointe une ligne verticale sur la carte, mesurée en degrés dans le sens horaire à partir du nord. Un conducteur tourne souvent sa carte routière pour l'aligner dans le sens de la route, tandis qu'un randonneur utilisant une carte et une boussole oriente généralement la carte afin qu'une ligne verticale pointe vers le nord. L'API Google Maps vous permet de modifier l'alignement ou l'orientation d'une carte. Par exemple, avec une direction de 90 degrés, l'orientation vers le haut de la carte pointe vers l'est.

Inclinaison (angle de vue)

L'inclinaison définit la position de la caméra sur un arc directement au-dessus du point central de la carte et de la surface de la Terre, mesurée en degrés à partir du nadir (direction qui pointe directement sous la caméra). Lorsque vous modifiez l'angle de vue, la carte apparaît en perspective, les éléments lointains semblant plus petits, et les plus proches semblant plus grands. Les illustrations suivantes le montrent.

Dans les images ci-dessous, l'angle de vue est de 0 degré. La première image correspond à un plan schématisé ; la position 1 correspond à la position de la caméra et la position 2 à la position actuelle de la carte. La carte qui en résulte est présentée juste en dessous.

Capture d'écran d'une carte avec une caméra placée à un angle de vue de 0 degrés, avec un niveau de zoom de 18.
Carte affichée avec l'angle de vue par défaut de la caméra
Schéma affichant la position par défaut de la caméra, directement sur la position de la carte, à un angle de 0 degré.
Angle de vue par défaut de la caméra

Sur les images ci-dessous, l'angle de vue est de 45 degrés. Notez que la caméra n'est pas inclinée à 45 degrés ; elle se déplace à mi-chemin le long d'un arc entre une ligne verticale perpendiculaire (0 degré) et le sol (90 degrés), jusqu'à la position 3. La caméra pointe toujours vers le point central de la carte, mais la zone représentée par la ligne en position 4 est maintenant visible.

Capture d'écran d'une carte avec une caméra placée à un angle de vue de 45 degrés, avec un niveau de zoom de 18.
Carte affichée avec un angle de vue de 45 degrés
Schéma affichant l'angle de vue de la caméra défini sur 45 degrés, avec le niveau de zoom toujours défini sur 18.
Angle de vue de 45 degrés

Sur cette capture d'écran, la carte est toujours centrée sur le même point que sur la carte d'origine, mais d'autres éléments ont été ajoutés en haut de la carte. À mesure que vous augmentez l'angle au-delà de 45 degrés, les éléments situés entre la caméra et la position <ph type='fmt'>{}</ph>de la carte apparaissent proportionnellement plus grands, tandis que les éléments situés au-delà de la position de la carte apparaissent proportionnellement plus petits, ce qui donne un effet tridimensionnel.

Zoom

Le niveau de zoom de la caméra détermine l'échelle de la carte. Plus le niveau de zoom est élevé, plus on peut voir de détails sur la carte ; et inversement, plus le niveau de zoom est faible, plus la partie du monde affichée à l'écran est grande. À un niveau de zoom 0, l'échelle de la carte est telle que le monde entier a une largeur d'environ 256 dp (pixels indépendants de la densité).

Augmenter le niveau de zoom de 1 double la largeur du monde à l'écran. Ainsi, à un niveau de zoom N, la largeur du monde est environ de 256 * 2N dp. Par exemple, à un niveau de zoom de 2, le monde entier mesure environ 1 024 dp de large. Notez que le niveau de zoom doit être un nombre entier. La fourchette de niveaux de zoom autorisée par la carte dépend d'un certain nombre de facteurs, comme le lieu, le type de carte et la taille de l'écran. Tout nombre en dehors de la plage sera converti vers la valeur valide la plus proche, qui peut correspondre au niveau de zoom minimal ou maximal. La liste suivante indique le niveau de détail approximatif que vous pouvez vous attendre à voir à chaque niveau de zoom :

  • 1 : Le monde
  • 5 : La masse continentale/le continent
  • 10 : La ville
  • 15 : Les rues
  • 20 : Les immeubles

Les images suivantes montrent à quoi ressemblent les différents niveaux de zoom :

Capture d'écran d'une carte au niveau de zoom 5
Carte au niveau de zoom 5
Capture d'écran d'une carte au niveau de zoom 15
Carte au niveau de zoom 15
Capture d'écran d'une carte au niveau de zoom 20
Carte au niveau de zoom 20.

Remarque : En raison de la taille de l'écran et de la densité, certains appareils peuvent ne pas être compatibles avec les niveaux de zoom les plus bas. Utilisez GoogleMap.getMinimumZoomLevel() pour obtenir le plus bas niveau de zoom possible pour la carte. Si vous devez montrer le monde entier dans la fenêtre d'affichage, il peut être préférable d'utiliser le mode simplifié.

Déplacer la caméra

Maps API vous permet de modifier la partie du monde visible sur la carte. Pour cela, vous devez changer la position de la caméra (au lieu de déplacer la carte).

Lorsque vous modifiez la caméra, vous avez la possibilité d'animer le mouvement de caméra qui en résulte. L'animation effectue une interpolation entre les attributs de caméra actuels et les nouveaux attributs. Vous pouvez également contrôler la durée de l'animation.

Pour modifier la position de la caméra, vous devez indiquer où vous souhaitez la déplacer à l'aide d'un CameraUpdate. L'API Google Maps vous permet de créer de nombreux types de CameraUpdate en utilisant CameraUpdateFactory. Les options suivantes sont disponibles :

Changer le niveau de zoom et définir le niveau de zoom minimal/maximal

CameraUpdateFactory.zoomIn() et CameraUpdateFactory.zoomOut() vous donnent un CameraUpdate qui change le niveau de zoom de 1.0, tout en laissant les autres propriétés inchangées.

CameraUpdateFactory.zoomTo(float) donne un CameraUpdate qui change le niveau de zoom à la valeur donnée, tout en laissant les autres propriétés inchangées.

CameraUpdateFactory.zoomBy(float) et CameraUpdateFactory.zoomBy(float, Point) donnent un CameraUpdate qui augmente (ou diminue, si la valeur est négative) le niveau de zoom de la valeur donnée. Le second fixe le point donné sur l'écran afin qu'il reste à la même position (latitude/longitude) et dans ce cas, il peut déplacer la caméra pour y parvenir.

Il peut parfois s'avérer utile de définir un niveau de zoom minimal et/ou maximal idéal. Vous pouvez par exemple définir ce niveau de zoom pour contrôler l'expérience utilisateur si votre application affiche une zone définie autour d'un point d'intérêt, ou si vous utilisez une superposition de tuile personnalisée avec un ensemble limité de niveaux de zoom.

Java

private GoogleMap map;
    map.setMinZoomPreference(6.0f);
    map.setMaxZoomPreference(14.0f);
      

Kotlin

private lateinit var map: GoogleMap

    map.setMinZoomPreference(6.0f)
    map.setMaxZoomPreference(14.0f)
      

Notez qu'en raison de certaines considérations techniques, il est possible que l'API ne permette pas aux utilisateurs d'effectuer un zoom trop faible ou trop élevé. Par exemple, une carte satellite ou en relief peut avoir un niveau de zoom maximal moins élevé que les tuiles de la carte de base.

Changer la position de la caméra

Il existe deux méthodes pour les changements de position courants. CameraUpdateFactory.newLatLng(LatLng) vous donne un CameraUpdate qui change la latitude et la longitude de la caméra, tout en conservant les autres propriétés. CameraUpdateFactory.newLatLngZoom(LatLng, float) vous donne un CameraUpdate qui modifie la latitude, la longitude et le zoom de la caméra, tout en conservant les autres propriétés.

Pour plus de souplesse dans le changement de position de la caméra, utilisez CameraUpdateFactory.newCameraPosition(CameraPosition) qui donne un CameraUpdate qui déplace la caméra sur la position donnée. Vous pouvez obtenir un CameraPosition soit directement, en utilisant new CameraPosition(), soit avec un CameraPosition.Builder en utilisant new CameraPosition.Builder().

Panoramique (défilement)

CameraUpdateFactory.scrollBy(float, float) vous donne un CameraUpdate qui change la latitude et la longitude de la caméra de sorte que la carte se déplace du nombre de pixels spécifié. Une valeur x positive déplace la caméra vers la droite, de sorte que la carte semble avoir bougé vers la gauche. Une valeur y positive déplace la caméra vers le bas, de sorte que la carte semble avoir bougé vers le haut. Inversement, des valeurs x négatives déplacent la caméra vers la gauche, de sorte que la carte semble avoir bougé vers la droite, et des valeurs y négatives déplacent la caméra vers le haut. Le défilement est effectué par rapport à l'orientation actuelle de la caméra. Par exemple, si la caméra est orientée à 90 degrés, alors l'est est "haut".

Définir des limites

Définir les limites de la carte

Il peut parfois être utile de déplacer la caméra pour que la totalité d'une zone d'intérêt soit visible au plus haut niveau de zoom possible. Par exemple, si vous affichez toutes les stations-service dans un rayon de 5 km autour de la position actuelle de l'utilisateur, vous pouvez déplacer la caméra afin qu'elles soient toutes visibles sur l'écran. Pour ce faire, vous devez d'abord calculer la limite LatLngBounds qui doit être visible à l'écran. Vous pouvez ensuite utiliser CameraUpdateFactory.newLatLngBounds(LatLngBounds bounds, int padding) pour obtenir un CameraUpdate qui change la position de la caméra de sorte que la LatLngBounds tienne entièrement dans la carte, en tenant compte de la marge extérieure (en pixels) indiquée. Le CameraUpdate obtenu garantit que l'espace (en pixels) qui sépare la limite donnée et le bord de la carte est au moins égal à la marge extérieure indiquée. Notez que l'inclinaison et la direction de la carte seront toutes deux définies sur 0.

Java

LatLngBounds australiaBounds = new LatLngBounds(
    new LatLng(-44, 113), // SW bounds
    new LatLng(-10, 154)  // NE bounds
);
map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0));
      

Kotlin

val australiaBounds = LatLngBounds(
    LatLng((-44.0), 113.0),  // SW bounds
    LatLng((-10.0), 154.0) // NE bounds
)
map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0))
      

Centrer la carte dans une zone donnée

Dans certains cas, vous pouvez vouloir centrer votre caméra à l'intérieur de certaines limites plutôt que d'inclure les bordures extrêmes. Imaginons par exemple que vous souhaitiez centrer la caméra sur un pays tout en conservant un zoom constant. Dans ce cas, vous pouvez utiliser une méthode similaire, en créant LatLngBounds et en utilisant CameraUpdateFactory.newLatLngZoom(LatLng latLng, float zoom) avec la méthode LatLngBounds.getCenter(). La méthode getCenter() renvoie le centre géographique de LatLngBounds.

Java

LatLngBounds australiaBounds = new LatLngBounds(
    new LatLng(-44, 113), // SW bounds
    new LatLng(-10, 154)  // NE bounds
);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.getCenter(), 10));
      

Kotlin

val australiaBounds = LatLngBounds(
    LatLng((-44.0), 113.0),  // SW bounds
    LatLng((-10.0), 154.0) // NE bounds
)
map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.center, 10f))
      

Une surcharge de la méthode, newLatLngBounds(boundary, width, height, padding), vous permet d'indiquer la largeur et la hauteur en pixels d'un rectangle, avec l'intention que celles-ci correspondent aux dimensions de la carte. Le rectangle est positionné de telle sorte que son centre est identique à celui de la vue de la carte (afin que si les dimensions spécifiées sont les mêmes que celles de la vue de la carte, le rectangle coïncide avec la vue de la carte). Le CameraUpdate obtenu déplacera la caméra de sorte que les LatLngBounds indiquées soient centrées sur l'écran au sein du rectangle donné au plus haut niveau de zoom possible, en tenant compte de la marge extérieure nécessaire.

Remarque : N'utilisez la méthode plus simple newLatLngBounds(boundary, padding) pour générer un CameraUpdate que si cela permet de déplacer la caméra une fois que la mise en page de la carte est effectuée. Au cours de la mise en page, l'API calcule les limites d'affichage de la carte qui sont nécessaires pour projeter correctement le cadre de délimitation. En comparaison, vous pouvez utiliser le CameraUpdate renvoyé par la méthode plus complexe newLatLngBounds(boundary, width, height, padding) à tout moment, même avant que la mise en page de la carte soit terminée, car l'API calcule les limites d'affichage à partir des arguments que vous transmettez.

Limiter le panoramique à une zone donnée

Dans les scénarios ci-dessus, vous définissez les limites de la carte, mais les utilisateurs peuvent ensuite faire défiler la carte ou effectuer un panoramique au-delà de ces limites. Vous pouvez toutefois fixer des limites au centre lat/lng du point focal de la carte (la cible de la caméra) pour que les utilisateurs puissent uniquement faire défiler la carte ou effectuer un panoramique à l'intérieur de ces limites. Cela pourrait, par exemple, s'avérer utile pour une application de vente au détail dans un centre commercial ou un aéroport, afin que les utilisateurs ne puissent pas faire défiler la carte ou effectuer un panoramique au-delà des limites ainsi définies.

Java

// Create a LatLngBounds that includes the city of Adelaide in Australia.
LatLngBounds adelaideBounds = new LatLngBounds(
    new LatLng(-35.0, 138.58), // SW bounds
    new LatLng(-34.9, 138.61)  // NE bounds
);

// Constrain the camera target to the Adelaide bounds.
map.setLatLngBoundsForCameraTarget(adelaideBounds);
      

Kotlin

// Create a LatLngBounds that includes the city of Adelaide in Australia.
val adelaideBounds = LatLngBounds(
    LatLng(-35.0, 138.58),  // SW bounds
    LatLng(-34.9, 138.61) // NE bounds
)

// Constrain the camera target to the Adelaide bounds.
map.setLatLngBoundsForCameraTarget(adelaideBounds)
      

Le diagramme ci-dessous illustre le scénario suivant : la cible de la caméra est limitée à une zone légèrement plus grande que la fenêtre d'affichage. L'utilisateur peut faire défiler la carte ou effectuer un panoramique, sous réserve que la cible de la caméra reste dans la zone délimitée. La croix représente la cible de la caméra :

Schéma affichant un LatLngBounds supérieur à la fenêtre d'affichage

La carte remplit toujours la fenêtre d'affichage, même si cela se traduit par l'affichage de zones qui se trouvent en dehors des limites définies. Par exemple, si vous positionnez la cible de la caméra à un angle de la zone délimitée, la zone située au-delà de l'angle est visible dans la fenêtre d'affichage, mais les utilisateurs ne peuvent pas faire défiler la carte jusque dans cette zone. Le schéma suivant illustre ce scénario. La croix représente la cible de la caméra :

Schéma illustrant la cible de la caméra positionnée dans l'angle inférieur droit de LatLngBounds

Dans le schéma suivant, la cible de la caméra est particulièrement réduite, ce qui offre à l'utilisateur peu de liberté pour faire défiler la carte ou effectuer un panoramique. La croix représente la cible de la caméra :

Schéma illustrant un LatLngBounds de caméra inférieur à la fenêtre d'affichage

Mettre à jour la vue de la caméra

Pour appliquer un CameraUpdate à la carte, vous pouvez soit déplacer la caméra instantanément, soit l'animer doucement. Pour déplacer la caméra instantanément avec le CameraUpdate donné, vous pouvez appeler GoogleMap.moveCamera(CameraUpdate).

Pour rendre l'expérience utilisateur plus agréable, surtout pour les déplacements courts, vous pouvez animer ce changement. Pour ce faire, au lieu d'appeler GoogleMap.moveCamera, appelez GoogleMap.animateCamera. La carte se déplacera lentement vers les nouveaux attributs. La forme la plus détaillée de cette méthode, GoogleMap.animateCamera(cameraUpdate, duration, callback), offre trois arguments :

cameraUpdate
The CameraUpdate décrivant où déplacer la caméra.
callback
Objet qui implémente GoogleMap.CancellableCallback. Cette interface généralisée pour la gestion des tâches définit deux méthodes "onCancel()" et "onFinished()". Pour l'animation, les méthodes sont appelées dans les cas suivants :
onFinish()
Est appelée si l'animation arrive à la fin sans interruption.
onCancel()

Est appelée si l'animation est interrompue en appelant stopAnimation() ou en initiant un nouveau mouvement de caméra.

Cela peut aussi se produire si vous appelez GoogleMap.stopAnimation().

duration
Durée souhaitée de l'animation, en millisecondes, sous forme de int.

Les extraits de code suivants illustrent quelques-unes des méthodes les plus utilisées pour déplacer la caméra.

Java

LatLng sydney = new LatLng(-33.88,151.21);
LatLng mountainView = new LatLng(37.4, -122.1);

// Move the camera instantly to Sydney with a zoom of 15.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15));

// Zoom in, animating the camera.
map.animateCamera(CameraUpdateFactory.zoomIn());

// Zoom out to zoom level 10, animating with a duration of 2 seconds.
map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);

// Construct a CameraPosition focusing on Mountain View and animate the camera to that position.
CameraPosition cameraPosition = new CameraPosition.Builder()
    .target(mountainView )      // Sets the center of the map to Mountain View
    .zoom(17)                   // Sets the zoom
    .bearing(90)                // Sets the orientation of the camera to east
    .tilt(30)                   // Sets the tilt of the camera to 30 degrees
    .build();                   // Creates a CameraPosition from the builder
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
      

Kotlin

val sydney = LatLng(-33.88, 151.21)
val mountainView = LatLng(37.4, -122.1)

// Move the camera instantly to Sydney with a zoom of 15.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15f))

// Zoom in, animating the camera.
map.animateCamera(CameraUpdateFactory.zoomIn())

// Zoom out to zoom level 10, animating with a duration of 2 seconds.
map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null)

// Construct a CameraPosition focusing on Mountain View and animate the camera to that position.
val cameraPosition = CameraPosition.Builder()
    .target(mountainView) // Sets the center of the map to Mountain View
    .zoom(17f)            // Sets the zoom
    .bearing(90f)         // Sets the orientation of the camera to east
    .tilt(30f)            // Sets the tilt of the camera to 30 degrees
    .build()              // Creates a CameraPosition from the builder
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))