C’est quoi MapKit
MapKit
est une API puissante qui permet aux développeurs d'accéder aux
fonctionnalités cartographiques de pointe d'Apple. Grâce à des
fonctions comme l'élévation réaliste et la vue à proximité, ainsi
qu'à la flexibilité des superpositions, elle offre une expérience qui
surpasse les solutions tierces.
Grâce à ses nombreuses fonctionnalités et en tenant compte de
ses subtilités, vous êtes en mesure de créer des expériences
géolocalisées véritablement immersives et fluides pour vos
utilisateurs.
Nous allons explorer les améliorations significatives apportées par
MapKit à SwiftUI et apprendre à tirer parti des fonctionnalités
suivantes :
Initialisation de la carte
Marqueur et annotations
Styles de cartes et altitude
Commandes de la carte
Aperçu
Contenu de la superposition de carte
Comment l’intégrer dans un projet
Veuillez suivre ces étapes :
1. Initialiser la carte et ajout de marqueurs
Ajouter une carte à SwiftUI est aussi simple qu'ajouter
un composant Map() sans aucun paramètre.
Vous pouvez personnaliser la carte à l'aide d'un module de
création de contenu. Cela vous permet d'y intégrer divers
éléments, tels que des marqueurs, des annotations et même la
position de l'utilisateur. De plus, vous pouvez y intégrer
différentes commandes afin d'améliorer l'interaction de
l'utilisateur avec la carte.
Exemple :
import SwiftUI
import MapKit
struct MapKitView: View {
var collegeLaCite: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude:
45.439327, longitude: -75.626782)
var montFortHospital: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude:
45.445718, longitude: -75.638822)
var body: some View {
Map() {
Marker("College LaCite", coordinate: collegeLaCite)
.tint(.orange)
Annotation("MontFort Hospital", coordinate: montFortHospital) {
2
ZStack {
RoundedRectangle(cornerRadius: 5)
.fill([Link])
Text("🎓")
.padding(5)
}
}
}
}
}
2. Style de la carte
Il existe trois styles de carte pour l'affichage de la carte :
1. Standard — Plan de ville avec les noms des rues et des
lieux
2. Imagerie — Image satellite de la zone
3. Hybride — Image satellite de la zone incluant les routes et
les noms des lieux
3
Tous les styles de carte prennent en charge l'affichage
horizontal automatic, flat vertical et realistic horizontal (3D). De plus,
les styles de carte horizontal standard et horizontal hybrid fournissent
également des informations sur l'état du trafic en temps réel.
Exemple :
.mapStyle(.hybrid(elevation: .realistic))
3. Quelques commandes de la carte
Voici un exemple :
.mapControls {
MapUserLocationButton()
MapCompass()
MapScaleView()
}
4. Comment gérer la sélection du marqueur.
Pour activer la sélection de marqueurs ou d'annotations, il est
nécessaire de configurer une liaison de sélection. Utilisez une
étiquette si le marqueur et les annotations n'ont pas le même type
d'identité.
Voici un exemple :
4
import SwiftUI
import MapKit
struct MapKitView: View {
@State private var selectedTag: Int? = nil
var collegeLaCite: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude:
45.439327, longitude: -75.626782)
var montFortHospital: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude:
45.445718, longitude: -75.638822)
var body: some View {
Map(selection: $selectedTag) {
Marker("College LaCite", coordinate: collegeLaCite)
.tint(.orange)
.tag(1)
Annotation("MontFort Hospital", coordinate: montFortHospital) {
ZStack {
RoundedRectangle(cornerRadius: 5)
.fill([Link])
Text("🎓")
.padding(5)
}
}
.tag(2)
}
.mapStyle(.hybrid(elevation: .realistic))
.mapControls {
MapUserLocationButton()
MapCompass()
MapScaleView()
}
}
}
5. LookAroundPreview
L'une des caractéristiques remarquables de MapKit est LookAroundPreview. Il a la capacité à offrir une
vue panoramique à 360 degrés des rues à un endroit géographique choisi.
L'aperçu LookAroundPreview offre une représentation visuelle de l'emplacement sélectionné, permettant
d'en visualiser l'aspect. Cet aperçu inclut un objet LookAroundPreview MKLookAroundScene, obtenu
grâce à la fonction LookAroundPreview MKLookAroundSceneRequest. Cette
fonction getLookAroundScene() récupère l'objet LookAroundPreview MKLookAroundScene lors de
l'affichage initial de la vue et également à chaque modification du marqueur sélectionné.
La vue LocationPreviewView affiche des marqueurs sur une carte et un aperçu de l'emplacement
sélectionné. La carte gère la sélection des marqueurs et, lorsque la sélection change, la vue
LocationPreviewLookAroundView devient visible.
Voici un exemple :
5
struct LocationPreviewLookAroundView: View {
@State private var lookAroundScene: MKLookAroundScene?
var selectedResult: MyFavoriteLocation
var body: some View {
LookAroundPreview(initialScene: lookAroundScene)
.overlay(alignment: .bottomTrailing) {
HStack {
Text("\([Link])")
}
.font(.caption)
.foregroundStyle(.white)
.padding(18)
}
.onAppear {
getLookAroundScene()
}
.onChange(of: selectedResult) {
getLookAroundScene()
}
}
func getLookAroundScene() {
lookAroundScene = nil
Task {
let request = MKLookAroundSceneRequest(coordinate:
[Link])
lookAroundScene = try? await [Link]
}
}
}
struct LocationPreviewView: View {
@State private var selection: UUID?
let myFavoriteLocations = [
MyFavoriteLocation(name: "Empire state building",
coordinate: .empireStateBuilding),
MyFavoriteLocation(name: "Columbia University",
coordinate: .columbiaUniversity),
MyFavoriteLocation(name: "Weequahic Park", coordinate: .weequahicPark),
MyFavoriteLocation(name: "Aeroport de Ottawa", coordinate: .ottawaAirport),
MyFavoriteLocation(name: "Musee de l'aviation", coordinate: .museeAviation),
MyFavoriteLocation(name: "Musee de l'histoire", coordinate: .museeHistoire),
]
var body: some View {
Map(selection: $selection) {
ForEach(myFavoriteLocations) { location in
Marker([Link], coordinate: [Link])
.tint(.orange)
}
}
.safeAreaInset(edge: .bottom) {
HStack {
Spacer()
6
VStack(spacing: 0) {
if let selection {
if let item = [Link](where: { $[Link] == selection
}) {
LocationPreviewLookAroundView(selectedResult: item)
.frame(height: 128)
.clipShape(RoundedRectangle(cornerRadius: 10))
.padding([.top, .horizontal])
}
}
}
Spacer()
}
.background(.thinMaterial)
}
.onChange(of: selection) {
guard let selection else { return }
guard let item = [Link](where: { $[Link] == selection
}) else { return }
print([Link])
}
}
}
struct MyFavoriteLocation: Identifiable, Equatable {
var id = UUID()
var name: String
var coordinate: CLLocationCoordinate2D
static func == (lhs: MyFavoriteLocation, rhs: MyFavoriteLocation) -> Bool {
return [Link] == [Link]
}
}
#Preview {
MapKitView()
}
extension CLLocationCoordinate2D {
static let weequahicPark = CLLocationCoordinate2D(latitude: 40.7063, longitude:
-74.1973)
static let empireStateBuilding = CLLocationCoordinate2D(latitude: 40.7484,
longitude: -73.9857)
static let columbiaUniversity = CLLocationCoordinate2D(latitude: 40.8075,
longitude: -73.9626)
static let ottawaAirport = CLLocationCoordinate2D(latitude: 45.32275, longitude:
-75.66736)
static let museeAviation = CLLocationCoordinate2D(latitude: 45.459392,
longitude: -75.643750)
static let museeHistoire = CLLocationCoordinate2D(latitude: 45.429321,
longitude: -75.708654)
static let collegeLaCite = CLLocationCoordinate2D(latitude: 45.439327,
longitude: -75.626782)
7
6. Contenu de superposition
MapCircle
Utilisez cette fonction MapCircle pour afficher une superposition
circulaire sur une coordonnée spécifique, avec un rayon ajustable.
Le modificateur mapOverlayLevel permet de définir la position de la
superposition par rapport aux autres éléments de la carte.
Voici un exemple :
struct MapCircleView: View {
var body: some View {
Map {
MapCircle(center: .museeAviation, radius: CLLocationDistance(250))
.foregroundStyle(.[Link](0.60))
.mapOverlayLevel(level: .aboveLabels)
MapCircle(center: .museeHistoire, radius: CLLocationDistance(350))
.foregroundStyle(.[Link](0.60))
.mapOverlayLevel(level: .aboveRoads)
}
}
}
CartePolygon
Créez un polygone de carte en spécifiant des coordonnées à l'aide
de MapPolygon.
Voici un exemple :
struct MapPolygoneView: View {
let destination: [CLLocationCoordinate2D] = [
.museeAviation,
.museeHistoire,
.collegeLaCite,
.ottawaAirport
]
8
var body: some View {
Map {
MapPolygon(coordinates: destination)
.foregroundStyle(.[Link](0.60))
}
}
}
MapPolyline
Cette fonctionnalité MapPolyline s'avère précieuse pour l'affichage de
superpositions de segments de ligne connectés, notamment pour
indiquer un itinéraire entre deux points. Grâce à elle MKDirections,
nous pouvons préparer une requête précisant le point de départ,
la destination et les préférences de transport. MapKit traite cette
requête sans difficulté et fournit rapidement les détails de
l'itinéraire ainsi que la durée estimée du trajet.
Voici un exemple :
import SwiftUI
import MapKit
struct RouteView: View {
@State private var route: MKRoute?
@State private var travelTime: String?
private let gradient = LinearGradient(colors: [.red, .orange],
startPoint: .leading, endPoint: .trailing)
private let stroke = StrokeStyle(lineWidth: 5, lineCap: .round,
lineJoin: .round, dash: [8, 8])
var body: some View {
Map {
if let route {
MapPolyline([Link])
.stroke(.blue, lineWidth: 8)
// .stroke(gradient, style: stroke)
}
}
.overlay(alignment: .bottom, content: {
HStack {
if let travelTime {
Text("Travel time: \(travelTime)")
.padding()
9
.font(.headline)
.foregroundStyle(.black)
.background(.ultraThinMaterial)
.cornerRadius(15)
}
}
})
.onAppear(perform: {
fetchRouteFrom(.empireStateBuilding, to: .columbiaUniversity)
})
}
}
extension RouteView {
private func fetchRouteFrom(_ source: CLLocationCoordinate2D, to destination:
CLLocationCoordinate2D) {
let request = [Link]()
[Link] = MKMapItem(placemark: MKPlacemark(coordinate: source))
[Link] = MKMapItem(placemark: MKPlacemark(coordinate:
destination))
[Link] = .automobile
Task {
let result = try? await MKDirections(request:
request).calculate()
route = result?.[Link]
getTravelTime()
}
}
private func getTravelTime() {
guard let route else { return }
let formatter = DateComponentsFormatter()
[Link] = .abbreviated
[Link] = [.hour, .minute]
travelTime = [Link](from: [Link])
}
}
10