-
Notifications
You must be signed in to change notification settings - Fork 185
Open
Labels
bug 🪲Something is broken!Something is broken!
Description
Environment
- Xcode version: 26.0 (17A324)
- iOS version: 26.0
- Devices affected: Simulator, iPhone 12 mini
- Maps SDK Version: 11.16.0
Observed behavior and steps to reproduce
- Place the component below in a new project:
ViewController.swift
import UIKit
import MapboxMaps
class ViewController: UIViewController {
private var startDistance: Double = 0
private var currrentDistance: Double = 0
private var targetDistance: Double = 0
private var startTimestamp: CFTimeInterval = 0
private var displayLink: CADisplayLink? {
didSet { oldValue?.invalidate() }
}
private var cancelables = Set<AnyCancelable>()
private var mapView: MapView!
private var mapCenterAnimator: BasicCameraAnimator?
private var mapPanAnimator: BasicCameraAnimator?
private let line = LineString(
[
.init(latitude: 42.36360, longitude: -71.05085),
.init(latitude: 41.81250, longitude: -71.42216),
]
)
private let duration: Double = 1
deinit {
displayLink?.invalidate()
}
override func viewDidLoad() {
super.viewDidLoad()
mapView = MapView(frame: view.bounds, mapInitOptions: .init())
mapView.mapboxMap.styleURI = .standard
mapView.mapboxMap.onStyleLoaded.observeNext { _ in
var source = GeoJSONSource(id: "source-point")
source.data = .geometry(.point(.init(self.line.coordinates[0])))
try! self.mapView.mapboxMap.addSource(source)
var circleOuterLayer = CircleLayer(id: "layer-circle-outer", source: "source-point")
circleOuterLayer.circleRadius = .constant(15)
circleOuterLayer.circleColor = .constant(.init(hue: 1, saturation: 1, lightness: 1)!)
try! self.mapView.mapboxMap.addLayer(circleOuterLayer)
var circleInnerLayer = CircleLayer(id: "layer-circle-inner", source: "source-point")
circleInnerLayer.circleRadius = .constant(12)
circleInnerLayer.circleColor = .constant(.init(hue: 0.7, saturation: 0.8, lightness: 0.5)!)
try! self.mapView.mapboxMap.addLayer(circleInnerLayer)
}.store(in: &cancelables)
self.view.addSubview(mapView)
Timer.scheduledTimer(withTimeInterval: duration, repeats: true) { _ in
self.move()
}
}
private func move() {
startTimestamp = CACurrentMediaTime()
startDistance = currrentDistance
targetDistance += 60
let currentPoint = line.coordinateFromStart(distance: targetDistance)!
let bounds = CoordinateBounds(
southwest: currentPoint.coordinate(at: 200, facing: 45),
northeast: currentPoint.coordinate(at: 200, facing: 180 + 45),
)
var cameraOptions: CameraOptions
do {
cameraOptions = try mapView.mapboxMap.camera(
for: [bounds.northeast, bounds.southwest],
camera: .init(
padding: .zero,
bearing: currentPoint.direction(to: line.coordinateFromStart(distance: targetDistance + 100)!),
pitch: 60
),
coordinatesPadding: nil,
maxZoom: nil,
offset: nil
)
} catch {
print("MapView | Error setting camera: \(error)")
return
}
mapCenterAnimator?.stopAnimation()
mapCenterAnimator = mapView.camera.makeAnimator(duration: duration, curve: .linear) { transition in
transition.center.toValue = bounds.center
}
mapCenterAnimator!.startAnimation()
mapPanAnimator?.stopAnimation()
mapPanAnimator = mapView.camera.makeAnimator(duration: duration, curve: .linear) { transition in
transition.zoom.toValue = cameraOptions.zoom
transition.bearing.toValue = cameraOptions.bearing
transition.pitch.toValue = cameraOptions.pitch
}
mapPanAnimator!.startAnimation()
displayLink = CADisplayLink(target: self, selector: #selector(updateFromDisplayLink(displayLink:)))
displayLink?.add(to: .current, forMode: .common)
}
@objc private func updateFromDisplayLink(displayLink: CADisplayLink) {
let progressRatio = (CACurrentMediaTime() - startTimestamp) / duration
guard progressRatio <= 1 else {
displayLink.invalidate()
self.displayLink = nil
return
}
currrentDistance = startDistance + (targetDistance - startDistance) * progressRatio
let point = line.coordinateFromStart(distance: currrentDistance)!
mapView.mapboxMap.updateGeoJSONSource(
withId: "source-point",
geoJSON: .geometry(.point(.init(point)))
)
}
}
- Build and run the project.
Expected behavior
The dot should smoothly slide along with the map.
Notes / preliminary analysis
Instead, the dot occasionally flickers off of its intended coordinates. See video, or an example normal/bad frame comparison:


It appears that the "bad" frame shows the normal layer joined with a slightly offset version of the layer.
Metadata
Metadata
Assignees
Labels
bug 🪲Something is broken!Something is broken!