Я работаю над приложением IOS, которое должно помочь людям в туристическом регионе разобраться в транспортных средствах.Чтобы им было кристально ясно, как добраться от А до Б, маршруты анимированы с помощью объектов аннотаций.Например, когда пользователь выбирает просмотр маршрута от A до D, объект канатной дороги скользит от A к B. После завершения объект Shuttle Bus движется по дороге от B до C, а затем катер, скользящий от C доД.
Итак, я написал следующие функции.Этот объект позволяет объекту transportMode (маленькому изображению лодки, канатной дороги и т. Д.) Скользить по прямой линии от A до B или от B до A.
func animateLinearRoute(transportMode: TransportAnnot, startcoor:
CLLocationCoordinate2D, destcoor: CLLocationCoordinate2D){
UIView.animate(withDuration: 3, animations:
{
if (transportMode.coordinate.latitude == startcoor.latitude && transportMode.coordinate.longitude == startcoor.longitude) {
transportMode.coordinate = destcoor
} else {
transportMode.coordinate = startcoor
}
})
}
Для перемещения объекта по нелинейному маршруту(обычно дорога), нарисованная на карте, я использую следующую функцию:
// pass mode of transport and coordinates along the travel route
func animateNonLinearRoute(transportMode: TransportAnnot, animroute: [CLLocationCoordinate2D]){
let path = UIBezierPath()
// get start point of route from coordinates and start drawing route
let point = self.mapView.convert(animroute[0], toPointTo: self.mapView)
path.move(to: point)
// translate each coordinate along the route into a point in the view for drawing
for coor in animroute {
let point = self.mapView.convert(coor, toPointTo: self.mapView)
path.addLine(to: point)
}
// create keyframe animation to move annotation along the previously drawn path
let animation = CAKeyframeAnimation(keyPath: "position")
animation.path = path.cgPath
animation.duration = 5.0
animation.isRemovedOnCompletion = false
let transportview = self.mapView.view(for: transportMode)
transportview?.layer.add(animation, forKey: "animate position along path")
transportMode.coordinate = animroute[animroute.count - 1]
CATransaction.commit()
}
Теперь полный маршрут может состоять из произвольной цепочки этих методов.Например, пользователь может выбрать точку, которая требует линейного маршрута -> нелинейного маршрута -> линейного маршрута -> нелинейного -> нелинейного.
В конечном итоге анимации должны выполняться строго последовательно, поэтомупользователь не будет сбит с толку (вторая анимация не должна запускаться, пока не завершится первая и т. д.).
Одним из соображений будет анимация ключевого кадра, подобная этой:
UIView.animateKeyframes(withDuration: 8, delay: 0, options: .calculationModeLinear, animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 5/8, animations: {
self.animateNonLinearRoute(transportMode: self.bus, animroute: self.br.coordinates)
})
UIView.addKeyframe(withRelativeStartTime: 5/8, relativeDuration: 3/8, animations: {
self.animateLinearRoute(transportMode: self.cableCar, startcoor: self.lowerstation, destcoor: self.midstation)
})
// dynamically fill up as needed using appropriate relative start times and durations
}, completion: nil)
Это не выполняет код синхронно, хотя.Я предполагаю, что это конфликтует с таймингами и ключевыми кадрами, определенными в функциях.
Я возился с пользовательскими закрытиями завершения и затем помещал каждый метод в закрытие завершения предыдущего, а также с очередями отправки.Но я не совсем понимаю их, потому что не смог достичь желаемого эффекта.И поскольку маршруты становятся длиннее, вложенные замыкания завершения не кажутся идеальным вариантом, поскольку они делают программу излишне сложной.Любые предложения высоко ценятся.