On this page

    Fly Between Different Locations - Swift SDK

    This example leverages the mobile SDKs to animate transitions between major U.S. locations and visualize school distribution using a single, high-performance cluster layer. The FlyTo feature ensures smooth, clear movement between locations.


    
    import SwiftUI
    import MapTilerSDK
    import CoreLocation
    
    struct FlyToAnimationView: View {
      @State public var mapView = MTMapView(
        options: MTMapOptions(center: CLLocationCoordinate2D(latitude: 38.17, longitude: -97.04),
          zoom: 3.9)
      )
    
      private let sourceId = "schools"
      private let clustersLayerId = "schools-clusters"
    
      @State private var animationTask: Task<Void, Never>? = nil
    
      // Note: Best practice is to set the API key at app startup (App/Scene or AppDelegate).
      // It's set here for standalone copy-paste convenience.
      init() {
        Task { await MTConfig.shared.setAPIKey("YOUR_API_KEY") }
      }
    
      var body: some View {
        MTMapViewContainer(map: mapView) {
          MTGeoJSONSource(
            identifier: sourceId,
            url: URL(string: "https://docs.maptiler.com/sdk-js/assets/Public_School_Characteristics_2020-21_no_prop.geojson")!,
            isCluster: true,
            clusterMaxZoom: 12,
            clusterRadius: 90
          )
        }
        .referenceStyle(.dataviz)
        .styleVariant(.light)
        .didInitialize {
          Task {
            await setupSchoolLayers()
            startLocationAnimation()
          }
        }
        .onDisappear { animationTask?.cancel() }
      }
    
      @MainActor
      private func setupSchoolLayers() async {
        guard let style = mapView.style else { return }
    
        let clusters = MTCircleLayer(identifier: clustersLayerId, sourceIdentifier: sourceId)
        clusters.maxZoom = 10.5
        clusters.filterExpression = MTFilter.all([
          MTFilter.clusters(),
          .array([.string(">="), MTExpression.get(.pointCount), .number(100)])
        ])
    
        clusters.radius = .expression(
          MTExpression.step(
            input: MTExpression.get(.pointCount),
            default: .number(16.0),
            stops: [
              (100.0, .number(22.0)),
              (750.0, .number(30.0))
            ]
          )
        )
    
        let yellow = UIColor(hex: "#f1f075") ?? .systemYellow
        let orange = UIColor(hex: "#f59e0b") ?? .systemOrange
        let red = UIColor(hex: "#ef4444") ?? .systemRed
        clusters.color = .expression(
          MTExpression.step(
            input: MTExpression.get(.pointCount),
            default: .color(yellow),
            stops: [
              (100.0, .color(orange)),
              (750.0, .color(red))
            ]
          )
        )
    
        try? await style.addLayer(clusters)
    
        await mapView.setPaintProperty(
          forLayerId: clustersLayerId,
          property: .opacity,
          value: .array([
            .string("interpolate"),
            .array([.string("linear")]),
            .array([.string("zoom")]),
            .number(3.0), .number(0.85),
            .number(10.0), .number(0.85),
            .number(10.5), .number(0.0)
          ])
        )
      }
    
      @MainActor
      private func startLocationAnimation() {
        struct Location { let zoom: Double; let center: CLLocationCoordinate2D }
    
        let locations: [Location] = [
          Location(zoom: 11.37, center: CLLocationCoordinate2D(latitude: 40.7684, longitude: -73.9757)), // NYC
          Location(zoom: 11.82, center: CLLocationCoordinate2D(latitude: 42.37131, longitude: -71.07515)), // Boston
          Location(zoom: 11.48, center: CLLocationCoordinate2D(latitude: 41.8699, longitude: -87.6922)), // Chicago
          Location(zoom: 3.9,  center: CLLocationCoordinate2D(latitude: 38.17, longitude: -97.04)), // USA overview
          Location(zoom: 10.62, center: CLLocationCoordinate2D(latitude: 47.6127, longitude: -122.3241)), // Seattle
          Location(zoom: 10.3,  center: CLLocationCoordinate2D(latitude: 37.6689, longitude: -122.3634)), // SF Bay
          Location(zoom: 11.15, center: CLLocationCoordinate2D(latitude: 29.75, longitude: -95.3843)), // Houston
          Location(zoom: 3.9,  center: CLLocationCoordinate2D(latitude: 38.17, longitude: -97.04)) // USA overview
        ]
    
        var idx = 0
    
        let fly = MTFlyToOptions(curve: nil, minZoom: nil, speed: 0.2, screenSpeed: nil, maxDuration: nil)
    
        animationTask?.cancel()
        animationTask = Task { @MainActor in
          // Initial delay to ensure map is fully idle
          try? await Task.sleep(nanoseconds: 2_500_000_000)
    
          while !Task.isCancelled {
            let loc = locations[idx % locations.count]
    
            await mapView.flyTo(loc.center, options: fly, animationOptions: nil)
    
            idx += 1
            try? await Task.sleep(nanoseconds: 2_000_000_000)
          }
        }
      }
    }
    

    Was this helpful?

    Mobile SDK
    iOS
    Fly Between Different Locations - Swift SDK
    Fly Between Different Locations