Can't access the current position of UIImageView - swift

I'v read many questions about this topic but their outdated or I can't understand them. This is the animation:
UIView.animate(withDuration: 20, delay: 0, options: [.curveLinear], animations: {
self.SubmarineImageView.transform = CGAffineTransform(translationX: (-self.frame.width - 80), y: CGFloat(Int(arc4random_uniform(UInt32(self.size.height / 2)))))
})
How do I access the position of the SubmarineImageView during the animation?
Also these images show that the emitter cant update because the position dose't change
Image 1
Image 2

To access SubmarineImageView properties during animation, you can check it's presentationLayer. It can return nil, so you have to unwrap it first. To get a position during animation you can do:
if let presentation = self.submarineImageView.layer.presentation() {
return presentation.position
} else {
return self.submarineImageView.layer.position
}
Also, I'm a bit worried that you try to simply assign this value to emitter's position. That won't work, as the presentation layer's position is changing during animation. If you are trying to make it animate with the submarine, you should also modify the emitter's position in the animation block or add the emitter as a sublayer of the submarineImageView.

Related

Setting the image on UIImageView changes the animation

I have a UIImageView that I wish to animate at the click of a button. But before the animation, I set its image. However, this image-setting messes up the animation. When I comment out the image-set, the animation works as expected.
var busFrame = self.newBusView.frame
let sourceFrame = self.buttonA.superview?.convert(self.buttonA.frame.origin, to: nil)
busFrame.origin.y = sourceFrame!.y
busFrame.origin.x = sourceFrame!.x
self.newBusView.frame = busFrame
//the following line messes up the animation
// self.newBusView.image = UIImage(named: "back_blue")
UIView.animate(withDuration: 2.0, delay: 0.3, options: .curveEaseOut, animations: {
busFrame = self.newBusView.frame
let desstinationFrame = self.buttonD.superview?.convert(self.buttonD.frame.origin, to: nil)
busFrame.origin.y = desstinationFrame!.y
busFrame.origin.x = desstinationFrame!.x
self.newBusView.frame = busFrame
}, completion: { finished in
print("Done!")
//same thing happening here
//self.newBusView.image = UIImage(named: "Background 1")
})
Also note that the buttons are in separate Stack views (hence the need for superview?.convert)
UPDATE:
So it was noticed that whenever I have a button.setImage() the positions go wrong (Even if the button has nothing to do with the animation). But instead of setImage, if I use button.imageView.image = something, then it has no side effects on animations. What is happening?
Expected:
Actual:
As we do not know the "expected" animation, I could not repeat the problem that you have. When I set same image again in the commented line, I get the same animation.
It may be about the area that the image covers. New image's ratio may be different than the default, therefore you see different animation although view's animation is same. You actually animate the view. Hence, you should focus on frames.
I believe that as #musakokcen mentioned your image have different size.
Try to use:
yourImageView.layer.masksToBounds = yes

Changing MKMapView Center coordinate at a different speed then its region.span

I'm trying to make my map view have a custom animation whenever an annotation on the map is selected.
This custom animation needs to consist of the map view's center coordinate changing at a different speed than the map view's span. (I want the map view to simultaneously quickly adjust its center then zoom in slowly after)
I've managed to somewhat accomplish this by performing the animations one after another like so:
MKMapView.animate(withDuration: 0.1, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.homeMapView.centerCoordinate = region.center
}, completion: {
(value: Bool) in
MKMapView.animate(withDuration: 1.5, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.homeMapView.region.span = region.span
}, completion: {
(value: Bool) in
print ("finished animation")
})
})
The problem is, this does not look smooth and I would ideally like both animations starting at the same time and running concurrently. This could be accomplished with a CAAnimation and the center coordinate value being additive while the span changes, but unfortunately I'm dealing with a MKMapView not a CALayer.
Any ideas or help would be much appreciated! Thanks!

Stopping and Resetting a CGAffineTransform

I'm trying to write code where when a trigger happens an instance of UIImageView creates a slow "growing" effect with a CGAffineTransform running for 20 seconds.
The issue happens when the trigger happens again before the first transform has completed. Instead of the image resetting back to it's original size, it shrinks exponentially, depending on when the trigger happened during the first transformation.
Here is my current code:
func changeCategoryImage() {
self.categoryPanoramaImageView.transform = CGAffineTransform.identity
UIView.transition(with: self.categoryPanoramaImageView, duration: 0.4, options: .transitionCrossDissolve, animations: {
self.categoryPanoramaImageView.image = self.newPanoramaImage
}) { (done) in
UIView.animate(withDuration: 10, animations: {
self.categoryPanoramaImageView.transform = CGAffineTransform(scaleX: 5.0, y: 5.0)
})
}
}
I was under the impression that CGAffineTransform.identity would reset the image back to it's original size. This is seems to not be the case.
How can I halt and reset the current running transformation in order to start a new one?
I was under the impression that CGAffineTransform.identity would reset the image back to it's original size. This is seems to not be the case.
Correct. It isn't the case. That's not how animations work. You are making a direct change to the underlying view (i.e. the model layer), but the animation is still present (i.e. the presentation layer).
Thus, you are setting the view's transform to the identity, but you are not removing the existing animation. And animations are additive by default. Hence the result you are observing.
Try inserting
self.categoryPanoramaImageView.layer.removeAllAnimations()
as the first line of your function. That way, you will remove the animation and start over from the identity.

How can I increment a value while UIViewPropertyAnimator is going through the animation process?

How can I increment a value while UIViewPropertyAnimator is going through the animation process? As I have set my object in motion I would like to increment its value as it drops on my screen but I am not sure how to link that with my Animator. Any suggestions? Here is how I have initiated the
let toTravel = CGFloat(blockSize * newInstance.distanceToTravel()) //checks how far it needs to go.
let frame = CGRect(x: x, y: startY, width: width, height: height)
super.init(frame: frame)
backgroundColor = UIColor.clear
addSubBlocksToView(grid: grid, blockSize: blockSize)
animator = UIViewPropertyAnimator(duration: 10.0, curve: .linear) { [unowned self] in
self.center.y += toTravel // need to calculate CODE this it is a static right now
}
As you can see it takes 10 seconds to travel the distance I have calculated. I would like to keep track of each few pixels (30) it has traveled with a counter.
Set up a CADisplayLink when you start the animation. During the animation, you can check the current position (given that it is a linear animation, you could do this easily by initialPosition + time/10 * distance). Once the animation has completed, you can invalidate the display link. The display link provides you with a callback for every frame, which you can use to update your onscreen counter.
Alternatively you could consider using a CADisplayLink to drive the entire animation (and use a custom animation curve driven by your own code.)

turn animation 180 degrees in swift

I am using a curl up animation when swiping up, which makes a card fly away to the top - it works fine. I'd like to use the same animation, but to swipe down, so that the card flies away down. I guess I'd have to somehow turn the swipe up animation 180 degrees. Is that possible?
let views = (frontView: self.frontView, backView: self.frontView)
// set a transition style
let transitionOptions = UIViewAnimationOptions.TransitionCurlUp
UIView.transitionWithView(self.flashCardView, duration: 0.5, options: transitionOptions, animations: {
views.frontView.removeFromSuperview()
self.flashCardView.addSubview(views.frontView)
}, completion: { finished in
// any code entered here will be applied
})
The UIViewAnimationOptions struct has another option that will solve this for you:
let transitionOptions = UIViewAnimationOptions.TransitionCurlDown