How to control crossfade between two UIImage's Without Animation? - ios

There are a lot of posts about crossfade of UIImages using an animation. But I can't find how to control the crossfade without animation, but instead by myself; for example with a parameter between 0.0 and 1.0 that controls the amount of crossfade.
I could put two UIImageViews behind each other and control the alpha (top one going from 1.0 to 0.0, and the bottom one at 1.0), but that's not a proper crossfade AFAIK.
To make it more graphic: On screen there's a slider that gives a value between 0.0 and 1.0, above it is an image. What I want is to crossfade between the initially shown image (when slider is 0.0) and another image (which if fully visible when slider is 1.0). So, when you'd slowly move the slider, you'd see the other image slowly appear.

You can use the image view alpha approach. How correct this is depends on the effect you're looking for. Using a value between 0 and 1 makes this approach relatively simple and is the obvious choice.
You could also look at rendering both images into a context and using CGContextSetBlendMode, possibly with kCGBlendModeMultiply, to combine the images. No parameters are available with this so you would still need to change the alpha of the rendering to get an acceptable merge / fade.

If you use two UIImageViews with clear backgrounds and vary the alpha channels from 0-1, 1-0, you should get very close to the effect you're looking for. I've found it works better if there's a black background behind both of them. It's perhaps not a true crossfade, but comes close enough for most usages.

To achieve that I used CATransition animations:
This a snippet from an old code
CATransition *fadeTransition = [CATransition animation];
fadeTransition.duration = 1.0f;
fadeTransition.type = kCATransitionFade;
fadeTransition.endProgress = 0.75;
[imageView setImage:/*YourImage*/];
[imageView.layer addAnimation:fadeTransition forKey:nil];
With -endProgress property you can set the end before it completes, but I have not a clear idea of what you want to achieve.

Related

CABasicAnimation animate (seek) to a position in time over an entire timeline

I'm wondering if the following is possible with CoreAnimation.
Like the title says, I'd like to animate or seek if you will, to a position in time over an entire timeline animation.
For example, say I create a CABasicAnimation which animates a CALayer's color from blue to red over an entire timeline of 10 seconds with an easing function of EaseOut.
Rather than playing that animation from start to finish, I'd prefer finer control.
For example, I'd like to say animateTo(50%) of the entire animation. This would result in an animation starting at 0% and animating to 50% of the entire animation with an ease out function. So the animation would last 5 seconds and we'd be in the middle of our color transform.
After this I could say, animateTo(20%). This would result in an animation starting from our current position of 50% and animating in reverse to 20% of the total animation. So we'd end up with a 3 second animation and we'd be 20% into our color transform from blue to red.
In the end we're just animating to a position in time over the entire timeline. I could easily say animateTo(5 seconds) rather than animateTo(50%). Or animateTo(2 seconds) rather than animateTo(20%).
I've been reading up on CoreAnimation and it appears I am un-able to get this kind of control. Has anyone else tried this with CoreAnimation?
Thanks!
The latest SDK adds a bit to UIKit animation.
It might suit your needs...
According to the documentation:
New object-based, fully interactive and interruptible animation support that lets you retain control of your animations and link them with gesture-based interactions
The new shiny UIViewPropertyAnimator:
let animator = UIViewPropertyAnimator(duration: 3.0, curve: .easeInOut) {
self.myView.alpha = 0
}
animator.startAnimation()
animator.pauseAnimation()
animator.isReversed = true
animator.fractionComplete = 1.5 / CGFloat(animator.duration)
However there are some limitations:
The PropertyAnimator requires targeting iOS 10 (which is still in beta as at the time of writing).
Also the animations are limited to UIView Animatable Properties, which are:
frame
bounds
center
transform
alpha
backgroundColor
contentStretch
If you seek more flexibility and features take a look at some open source libraries like TRX and Advance:
import TRX
let tween = Tween(from: 0, to: 1, time:3, ease:Ease.Quad.easeOut) {
anyObject.anyProperty = $0
}
let reversed = tween.reversed()
reversed.seek(1.5)
reversed.start()
As already pointed out, there is no built-in function. But if you want to create your own solution, here are a few notes and useful functions that are already there.
The CABasicAnimation conforms to the `CAMediaTiming´ protocol and contains some neat functionality for your use case:
timeOffset - this value determines at what time into the animation you actually want to start, if you have a animation with a duration of 2 seconds and timeOffset set to 1, it will cause the animation to start in the middle.
speed - setting that value to -1 would cause the animation to reverse (e.g. for the case of from 50% to 20%)
duration - might be changed if you want to change the duration of the animation for shorter changes e.g. form 40% to 50%.
timingFunction - I was hoping it might be possible to provide a custom timing function here, which for example just completes the animation after 1 second even if the duration is set to be 5 seconds, meaning: a linear function between 0 and 1 and after that just constant. It may however be possible to achieve an approximation of that with a bezierPath as well.

Using a UIButton to mask a moving UIView

I want to bind two views to a button's border like a mask. The effect I want is seen in the image below
So I have a custom controller that uses a PageViewController to swipe between two UIViewControllers. I also have two views (the red one and the blue one). I can track the direction and degree of the page turning, so I can link that to the movement of the two views. All I need to do is apply a mask to the moving boxes so that all the movement stays within the button.
If anyone knows how to do this, I'd be eternally grateful for the information!
My understanding is that you have a view, then you want to transition between its two subviews with a sliding animation. This is fairly straight forward.
First set "Clip Subviews" to true (either in storyboard editor or setting view.clipToBounds=true). If you want a sphere like you show then set layer.cornerRadius = view.frame.size.width/2
The you can just set the frames of your subviews- either animating them with UIView animateWithDuration or setting the frames yourself in your animation loop.
The former in code (for sliding the first element to the left and right element in):
[UIView animateWithDuration:duration animations:^{
[subview1 setFrame:CGRectMake(-subview1.frame.size.width, 0, subview1.frame.size.width, subview1.frame.size.height)];
[subview2 setFrame:CGRectMake(0, 0, subview2.frame.size.width, subview2.frame.size.height)];
}];
The reverse animation is similar. If you're doing it in your own animation loop (which sounds like what you want) then you can do the interpolation yourself pretty easily.
If you want to be more advanced with your mask (i.e. based on an image) then look at something like this: How to mask UIViews in iOS
This solution may not be the optimized one, but do the trick you want. First i wanna make sure that i understand your requirement. I understand that you wanna go away to left the red image & bring in the right blue image in the button with the sliding effect.
If my understanding meet your requirement,Here is the trick
First decide which portion of red & blue image you needed. That must be easy as you know the direction & degree of the turning the UIPageViewController.
Then Crop that decided portions from the red & blue image using the code here.
Now draw both resulted cropped image on the coreGraphics side by side (red on the left & blue on the right) & retrieve the final resulted image.
set the image to the UIButton.
Finally to acquire the round shape you can set the radius property of layer property of the button.
For the third step, how you can you draw image on coreGraphics & retrieve apple give a detail explanation here
You have to do all these steps each time you wanna update the image of the UIButton. There may be a other good way to do this :)
You can use corner radious on the button layer
CGPoint saveCenter = roundedView.center;
CGRect newFrame = CGRectMake(roundedView.frame.origin.x, roundedView.frame.origin.y, newSize, newSize);
button.frame = newFrame;
button.layer.cornerRadius = newSize / 2.0;
button.center = saveCenter;

How can I animate in the entrance of a CAEmitterCell?

Currently my particles appear on screen abruptly in their full shape and form. What I want is for the cells to either start at 0.0 opacity and animate up to full opacity, or start at 0.0 scale and animate up to 1.0 scale. I can't find anything online on how to do this.
You can animate the various properties of a CAEmitterCell, there is a good example at animating the CAEmitterCell Color property that should give you a good idea of what you should do to get the effect you want.
There are lots of great resources on CAEmitters, one good one is Tutorial: Particle Systems in Core Animation with CAEmitterLayer and another is Apple's Fireworks Sample Code

Mimicking the timer in iPad's timer app

If you open up the timer app on your iPad, you get this beautiful grey circle that slowly turns red as you come closer to time running out. I'd like to learn to mimic this. I've found Quartz 2D to be one option, although I've found little information about using it for iOS. I'm quite the n00b at all this, so I could be missing some huge, some easier way to make the circle go around. Plus keep the current time remaining in the middle.
So, if anyone could point me in the right direction, I would be uber grateful. Thanks in advance!
You can do that using CAShapeLayer to make the circle. Use Core Animation to animate the transition from one color to another over time. CAShaperLayer's fillColor property is animatable. It'd go something like this:
CAShapeLayer *myCircleLayer = ...; // create a circle layer and add it to your view
CABasicAnimation* transition = [CABasicAnimation animationWithKeyPath:#"fillColor"];
transition.fromValue = [UIColor grayColor];
transition.toValue = [UIColor redColor];
transition.duration = secondsUntilTimerExpires;
[myCircleLayer addAnimation:transition forKey:#"fillColor"];
You might want to add the animation only when the timer is getting close to expiring. A very long, slow animation, over an hour for example, would make the circle mostly red for a fairly long time, which doesn't help the user determine the time until the timer expires.

minimize window animation, but for iOS?

I have an overlay help text in a UIView that I would like to animate up to a button in the navigationbar, in a way similar to the minimize window animation on Mac OS X.
I can do the basic animations of fading opacity and resizing windows, but this one is difficult.
Any clues how to do this kind of animation with a UIView?
There are two effects for OSX that you can set for that (if I'm understanding this right), the Scale and Genie effects. To mimic the scale one, you need to animate the scale, opacity, and positions.
Example using implicit animation:
view.layer.transform = CATransform3DMakeScale(0.2, 0.2, 1);
view.layer.position = CGPointMake(yournavbarspot.x, yournavbarspot.y);
view.layer.opacity = 0.0f;
To do the genie effect, you'd do the same thing and also alter the shape of the view as it animates. I'm not sure if you can change the geometry of a UIView, so the closest thing I can think of would be to create a mask that you alter the geometry of using UIBezierPaths.

Resources