All docsMaps SDK for iOSExamplesAdd animated weather data

Add animated weather data

Load a raster image to a style using ImageSource and display it on a map as animated weather data using RasterLayer.

This example uses an image source. See the data format on GitHub.

ViewController.swift
import MapboxMaps
class ViewController: UIViewController {
var mapView: MapView!
var sourceId = "radar-source"
var timer: Timer?
var imageNumber = 0
override func viewDidLoad() {
super.viewDidLoad()
let center = CLLocationCoordinate2D(latitude: 41.874, longitude: -75.789)
let cameraOptions = CameraOptions(center: center, zoom: 5)
let mapInitOptions = MapInitOptions(cameraOptions: cameraOptions, styleURI: .dark)
mapView = MapView(frame: view.bounds, mapInitOptions: mapInitOptions)
mapView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
// Hide the `scaleBar` at all zoom levels.
mapView.ornaments.options.scaleBar.visibility = .hidden
// This also updates the color of the info button to match the map's style.
mapView.tintColor = .lightGray
// Set the map's `CameraBoundsOptions` to limit the map's zoom level.
try? mapView.mapboxMap.setCameraBounds(with: CameraBoundsOptions(maxZoom: 5.99, minZoom: 4))
view.addSubview(mapView)
mapView.mapboxMap.onNext(.mapLoaded) { _ in
self.addImageLayer()
}
}
func addImageLayer() {
let style = mapView.mapboxMap.style
// Create an `ImageSource`. This will manage the image displayed in the `RasterLayer` as well
// as the location of that image on the map.
var imageSource = ImageSource()
// Set the `coordinates` property to an array of longitude, latitude pairs.
imageSource.coordinates = [
[-80.425, 46.437],
[-71.516, 46.437],
[-71.516, 37.936],
[-80.425, 37.936]
]
// Get the file path for the first radar image, then set the `url` for the `ImageSource` to that path.
let path = Bundle.main.path(forResource: "radar0", ofType: "gif")!
imageSource.url = path
// Create a `RasterLayer` that will display the images from the `ImageSource`
var imageLayer = RasterLayer(id: "radar-layer")
imageLayer.source = sourceId
// Set `rasterFadeDuration` to `0`. This prevents visible transitions when the image is updated.
imageLayer.rasterFadeDuration = .constant(0)
do {
try style.addSource(imageSource, id: sourceId)
try style.addLayer(imageLayer)
// Add a tap gesture recognizer that will allow the animation to be stopped and started.
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(manageTimer))
mapView.addGestureRecognizer(tapGestureRecognizer)
} catch {
print("Failed to add the source or layer to style. Error: \(error)")
}
manageTimer()
}
@objc func manageTimer() {
if timer == nil {
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
guard let self = self else { return }
// There are five radar images, number 0-4. Increment the count. When that would
// result in an `imageNumber` value greater than 4, reset `imageNumber` to `0`.
if self.imageNumber < 4 {
self.imageNumber += 1
} else {
self.imageNumber = 0
}
// Create a `UIImage` from the file at the specified path.
let path = Bundle.main.path(forResource: "radar\(self.imageNumber)", ofType: "gif")
let image = UIImage(contentsOfFile: path!)
do {
// Update the image used by the `ImageSource`.
try self.mapView.mapboxMap.style.updateImageSource(withId: self.sourceId, image: image!)
} catch {
print("Failed to update style image. Error: \(error)")
}
}
} else {
timer?.invalidate()
timer = nil
}
}
deinit {
timer?.invalidate()
}
}