Skip to content

Instantly share code, notes, and snippets.

@gallaugher
Created December 1, 2025 18:10
Show Gist options
  • Select an option

  • Save gallaugher/e8f5bfd0f210735d85a216e3c3946027 to your computer and use it in GitHub Desktop.

Select an option

Save gallaugher/e8f5bfd0f210735d85a216e3c3946027 to your computer and use it in GitHub Desktop.
AllTeamsMapView.swift
import SwiftUI
import MapKit
import FirebaseFirestore
struct AllTeamsMapView: View {
@FirestoreQuery(collectionPath: "teams") var teams: [Team]
@State private var cameraPosition: MapCameraPosition = .automatic
var body: some View {
Map(position: $cameraPosition) {
ForEach(teams) { team in
if team.latitude != 0 && team.longitude != 0 {
Marker(
team.name.isEmpty ? team.university : team.name,
coordinate: CLLocationCoordinate2D(
latitude: team.latitude,
longitude: team.longitude
)
)
.tint(.red)
}
}
}
.mapStyle(.standard(pointsOfInterest: .all))
.mapControls {
MapCompass()
MapScaleView()
}
.onChange(of: teams) {
updateCameraPosition()
}
.onAppear {
updateCameraPosition()
}
}
private func updateCameraPosition() {
// Filter teams that have valid coordinates
let validTeams = teams.filter { $0.latitude != 0 && $0.longitude != 0 }
guard !validTeams.isEmpty else { return }
// If only one team, center on it with a reasonable zoom
if validTeams.count == 1 {
let team = validTeams[0]
cameraPosition = .region(MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: team.latitude, longitude: team.longitude),
latitudinalMeters: 10000,
longitudinalMeters: 10000
))
return
}
// Calculate bounds for all teams
let latitudes = validTeams.map { $0.latitude }
let longitudes = validTeams.map { $0.longitude }
let minLat = latitudes.min()!
let maxLat = latitudes.max()!
let minLong = longitudes.min()!
let maxLong = longitudes.max()!
// Calculate center
let centerLat = (minLat + maxLat) / 2
let centerLong = (minLong + maxLong) / 2
// Calculate span with some padding (20% extra on each side)
let latDelta = (maxLat - minLat) * 1.4
let longDelta = (maxLong - minLong) * 1.4
// Ensure minimum span so we're not too zoomed in
let finalLatDelta = max(latDelta, 0.05)
let finalLongDelta = max(longDelta, 0.05)
cameraPosition = .region(MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: centerLat, longitude: centerLong),
span: MKCoordinateSpan(latitudeDelta: finalLatDelta, longitudeDelta: finalLongDelta)
))
}
}
#Preview {
AllTeamsMapView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment