Annotations are not clickable until animation ends - ios

As we all know, to move map markers we have to use this code
UIView.animate(withDuration: 10, animations: {
self.marker.coordinate = newCoordinate
})
but in this case, during all 10 seconds my annotation are not clickable!
they only became clickable on 11 second.
I know I can use Timer and calculate coordinates myself as in Google maps, but maybe you know better solution?

change to : options: UIViewAnimationOptions.AllowUserInteraction
UIView.animate(withDuration: TimeInterval(timeLeft), delay: 0, options: UIViewAnimationOptions.AllowUserInteraction, animations: {
Format the code above, you get the idea.
Taken from here where I answered similar question:

Related

Creating an MKMapKit curved / spherical / interpolated camera transition

I would like to animate the camera so that the entire animation feels "curved" rather than "linear."
Right now, with the out-of-the-box camera animation iOS offers, or even when using UIView.animate(), the animation feels like the camera is directly moving from the start to the end. However, I would like the animation to feel like it is curving from the start to the end.
Here's a picture describing what it feels like now vs what I would like it to feel like.
Here is an example from Kakao maps, a Korean app, of what the desired animation would be:
Currently, I'm just using two camera animations, to create a flying-out and flying-in effect. When I create my own custom animations for MKMapView's camera with a curveEaseInOut, the speed of the animation is curvedEaseInOut, but this does not create the desired effect. This creates the undesirable "linear" feeling as depicted in the "What it's now:" diagram above
UIView.animate(withDuration: duration*2,
delay: 0,
options: .curveEaseIn,
animations: {
self.mapView.camera = preRotationCamera
}) { _ in
UIView.animate(withDuration: duration*2,
delay: 0.1,
options: .curveEaseOut,
animations: {
self.mapView.camera = finalCamera
}, completion: completion)
}
I image that using animateKeyframes(withDuration:delay:options:animations:completion:) could be a valid approach. However, I have not been able to successfully animate the MKMapView camera through a series of coordinates with animateKeyframes() — the keyframes seemed to be ignored, and the camera just directly transitions to the final camera.
For example, this code simply transitions the camera directly to finalCamera:
UIView.animateKeyframes(withDuration: duration*2, delay: 0, options: .calculationModeCubic, animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.5) {
self.mapView.camera = preRotationCamera
}
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5) {
self.mapView.camera = finalCamera
}
})
How could one create this kind of spherical / interpolated / curved camera transition for iOS?
For reference, this is with iOS15 and Swift 5.

Please, how do I change this animation from kotlin to swift?

I investigated but I could not find anything like this for Swift. Can you please help me make this animation in Swift?
Val animador = ValueAnimator.ofFloat(0.0f ,1.0f)
animador.repeatCount = ValueAnimator.INFINITE
animador.interpolator= LinearInterpolator()
animador.duration = 10000L
animador.addUpdateListener { animation ->
val progreso = animador.animatedValue as Float
Val anchura = fondo!!.width
fondo!!.traslationx = transicionX
fondo2!!.traslationx = transicion X -anchura
}
animador.start()
This may not be exactly right, but try this:
let anchura = fondo.frame.width
UIView.animate(withDuration: 1, delay: 0, options: [.repeat, .autoreverse], animations: {
fondo.frame.origin.x = CGFloat(transicionX)
fondo2.frame.origin.x = CGFloat(transicionX) - anchura
})
Swift animations start automatically (no need to start() or anything).
Edit:
Inside the animations block, you just put the final value that you want. This means that you don't need to calculate the progress or anything, and you probably don't even need a transicionX variable. Instead, try this:
let anchura = fondo.frame.width /// let's say this is 50
UIView.animate(withDuration: 1, delay: 0, options: [.repeat, .autoreverse], animations: {
fondo.frame.origin.x += anchura /// move fondo to the right by 50
fondo2.frame.origin.x -= anchura /// move fondo2 to the left by 50
})
Another edit: made it += and -= to animate on top of existing values

Custom animation: easing out

I have successfully created a custom animation in a drawing in a UIView by using a repeating Timer to increment the alpha of the drawing every few milliseconds.
Now, I want to achieve an easing out animation (deceleration) with my drawing. I would like to do this by firing a new timer with a longer interval every time the Timer is called, so that the alpha increments slower, resulting in deceleration.
I know that there is an easeOut animation from CAMediaTiming, but I would like to know if there is any built in function to get the decelerating numbers. For example, if I pass in a constant of 10, every time I call the function I can get decelerating numbers like 15, 18, 20, 21, 21.5, etc.
There is a built-in way to use various sorts of animation curves in standard UIView animations.
var yourView = UIView() // Or whatever your view might be
var yourView.alpha = 0 // Initial alpha value
// Call the animation method. Note options (which can be an array) which applies an ease-out curve to the animation
UIView.animate(withDuration: 1.0, delay: 0.0, options: .curveEaseOut, animations: {
yourView.alpha = 1.0 // Final value of alpha
}, completion: nil)
Other animation curves are available, such as .curveEaseIn and .curveEaseInOut as well as other options. You can read more about animation options here.
You can use the completion handler closure to chain animations too.
If you are insisting on implementing your own means of animation using a timer (which I would not recommend), post some code so that I can consider a way to apply a curve to the changing values.

How to make a visual bounce circle for record voice

I want to make a UIView, circle, that scale based on volume of speak recording. I have this code to obtain the rate:
recorder.updateMeters()
let ALPHA = 0.05
let peakPower = pow(10, (ALPHA * Double(recorder.peakPower(forChannel: 0))))
How can I make this animation? I I make only:
self.audioCircle.transform = CGAffineTransform(scaleX: 1+CGFloat(rate), y: 1+CGFloat(rate))
the animation is too static, I need a more natural bounce effect, how can I do?
thanks!
.transform is what's implicitly animating your views change in size.
In that case, you should try using:
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.75, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
//update view
self.view.layoutIfNeeded()
}, completion: { (completed) in
//animation completed
})
The above animation might be what you want to use to animate your view. It gives a nice bounce effect, and you can play with the parameters to adjust it accordingly.
However, because of the nature of the input, I'm not sure how the animation will fare.
It might be best to update the audioCircle size every so often, as opposed to constantly. This would allow the animation time to preform both correctly and smoothly as opposed to rigidly.
Good luck.

optimal approach to animate radar in iOS

I'm trying to animate the heading line of a naval-style radar (the spinning part below) in iOS, like this:
My current slow, laggy, and high-overhead solution (pseudocode because the real Swift code is a little lengthy):
create NSTimer to call animate() every 1/60 sec
currentAngle = 0
animate():
create UIBezierPath from center of circle to outside edge at currentAngle
add path to new CAShapeLayer, add layer to views layer
add fade out CABasicAnimation to layer (reduces opacity over time)
increase currentAngle
What's the best way to do this without using a .gif? I have implemented the solution above, but the performance (frame rate and CPU use) is awful. How would you approach this problem?
Your approach is too complex. Don't try to re-draw your image during the animation.
Separate out the part that rotates from the part that fades in and out and animate them separately. Make each animation draw partly transparent so the other animation shows through.
Either create a static image of the part that rotates, or build a layer that creates that image.
If you create an image, you can use UIView animation to animate the rotation on the image view.
If you create a layer that draws the heading line and gradient around it, then use a CABasicAnimation that animates the z rotation of the layer's transform.
I've come to a working Swift 3 solution, thanks to Animations in Swift / iOS 8 article :
let scanInProgress = UIImageView()
scanInProgress.image = UIImage(named: "scanInProgress.png")
scanInProgress.frame = CGRect(x: 150, y: 200, width: 80, height: 200)
view.addSubview(scanInProgress)
let fullRotation = CGFloat(Double.pi * 2)
let duration = 2.0
let delay = 0.0
UIView.animateKeyframes(withDuration: duration, delay: delay, options: [.repeat, .calculationModeLinear], animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1/3, animations: {
scanInProgress.transform = CGAffineTransform(rotationAngle: 1/3 * fullRotation)
})
UIView.addKeyframe(withRelativeStartTime: 1/3, relativeDuration: 1/3, animations: {
scanInProgress.transform = CGAffineTransform(rotationAngle: 2/3 * fullRotation)
})
UIView.addKeyframe(withRelativeStartTime: 2/3, relativeDuration: 1/3, animations: {
scanInProgress.transform = CGAffineTransform(rotationAngle: 3/3 * fullRotation)
})
}, completion: {
})

Resources