Mac OS: CAAnimation - seamlessly update the animation - objective-c

I'm making custom UI element and I need to animate it. The problem is that at some point I need to update my animation, but when I update it, there is a visible lag/gap between current animation position (state) and new animation.
In other words, when I'm applying new animation, this animation starts from 0 position (state), while the actual (visible) state of the previous animation is different.
Here is example: (link)
<blockquote class="imgur-embed-pub" lang="en" data-id="a/q3NA31f"></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
Code for animation:
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
anim.duration = time;
anim.repeatCount = INFINITY;
anim.fromValue = from;
anim.byValue = by;
[self.myLayer addAnimation:anim forKey:kActivityAnimationKey];
First applied animation have different time/from/by parameters.
ANY advices will be much appreciated, since I stuck on it on two days and tried everything that comes to head by this time.

I was able to finish this task and I will give a general answer to this question.
If you want to update your current ongoing animation, but you're in the middle of it, you need to replace current animation with animation that will end current animation on the right place.
For example, in my question there is an animation that have fromValue and byValue. It means, that if you'll start the same animation with different duration, it will change its current rotation state to fromValue.
To fix this behaviour, we need to add animation that will finish our animation from current rotation state to fromValue. To get your current rotation, or other property you need to animate, we have presentationLayer of CALayer. We can set the values from it to our "closing" animation.
How we can know when our closing animation is ended? The answer is CAAnimationDelegate. Just set up a delegate to the closing animation and when it's done - add another animation with different parameters. You can seamlessly update your animation now.
Keep in mind that closing animation time must be a fraction of your original animation time to make things smooth. You can calculate it like this: (end state - current state) * original duration.

Related

Cycle animation background issue

CABasicAnimation enter foreground(repeatCount = 5). Add animation again, this animation will run twice. If not, this animation will not disappear when done and don't carry out animationDidStop.
However, a month has passed.Like the reply above, i answered myself! Briefly, every 5 seconds, the number of cycles is decremented by one, by using NSTimer.

Animating a circle UIImageView to disappear

If I have a UIImageView of a circle, how could Core Animation make it disappear like in this question?
How to use CoreAnimation to animate a circle like a clock countdown
Create a CAShapeLayer. Set its path to your “clock” shape. Set it as the layer mask of your image view (e.g. imageView.layer.mask = shapeLayer).
Then you can try using a CAKeyframeAnimation to animate the shape layer's path, but I suspect the results won't be pleasing. Instead you'll probably want to use a CADisplayLink as a timer and update the shape layer's path every time it fires.
What you are looking for is known as a "clock wipe" transition.
David is pointing you in the right direction. I have a sample project on Github that shows exactly what you are looking for:
iOS Core Animation Demo
When you run the app, click on the "Mask Animation" button. It does what you're talking about. It shows an image view with a clock wipe, and then hides it again. It would be a simple matter to switch it around to have the image fully visible at first and then animate a clock wipe to hide it.

How can I set the end dragging velocity of a UICollectionView with custom flow layout?

I'm working on a UICollectionView with a custom flow layout subclass which, among other things, does some custom "paging". Everything's fine but for the fact that depending on how I drag, when I release and after - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity gets called, the collection view (or some part of the UICollectionViewFlowLayout which I did not yet know I need to override) is controlling the velocity with which the animation of an item snapping happens.
That is, if I slightly offset an item from the center of the
collection view qnd release, it snaps back to its position pretty
quickly (desired).
But If I drag the item, say, half way past the collection view's
frame and/or change swiping directions while still dragging and then
release, the "snap" animation takes too long (not desired: I'd like the velocity to adjust so that the end drag animation takes the same amount of time always, regardless of distance).
I tried modifying the decelerationRate of the collection view but it doesn't seem to do anything. And I'm thinking of writing my own animation block in one of the collection view delegate methods, but I'm wondering if there is a different way (perhaps from within the flow layout subclass?).
Well, actually setting self.collectionView.decelerationRate = 0.; seems to work for now. It at least does not decelerate the scrolling and so it looks like constant velocity which is not exactly what I wanted but feels almost right.

How do I change the setPosition of a layer mid animation

I am currently animating an objects position to move across the x-axis in intervals of 50. However, I want to be able to stop the object and change its animation during certain circumstances, such as the user laying an object in front of it.
I have to use [self.layer setPosition:newPosition] or the object will bounce back to its original position after animation completes. If the object is dropped to stop it, the object bounces to the setPosition point before committing the new animation. How do I make it stop and stay where it is AND perform a new animation?
You are using implicit layer animation to animate the positions of your layers. To cancel an animation before it is complete, you would use:
[self.layer removeAllAnimations];
This would have the side effect of jumping your layer to the final animation position. If you want the layer to stop where it is, then you need to get the current presentationLayer position.
CGPoint currentAnimationPosition = self.presentationLayer.position;
self.layer.position = currentAnimationPosition;
[self.layer removeAllAnimations];
To perform a new animation, you can simply set a new position on the layer as you were doing before.

Animate the drawing of a line (Quartz 2D?)

How would you go about animating the drawing of a line in a UIView on the iPhone? Is this possible? It can be drawn but can it easily be animated so it appears to be hand drawn?
There's no built-in way to do this no. You'd have to redraw the line repeatedly, interpolating between the start and end points using a timer callback to invalidate the view and trigger a redraw. Of course the redraw would have to draw everything in the area of the view bring redrawn which is potentially slow.
What I would do if I had a series of lines I wanted to draw over a period of time is to have two subviews - they would cover the same area and the top one would have a transparent background. Have the top one draw just the line that I am currently animating and when it's finished, draw the full length of it in the lower view. Then repeat, animating the next line in the top view.
With the new API you can do that easily, using strokeEnd property of CGPath.
You can read more details here: What's the easiest way to animate a line?