Core Animation Some demo summary (dynamic switching pictures, large turntable, picture folding, progress bar and other animation effects) _android

Source: Internet
Author: User

The previous article summarizes some basic knowledge of core Animation, this one is mainly the core Animation of some applications, involving Cashapelayer, careplicatorlayer and other layers of knowledge.

First look at the effect of the picture:

1. Switch Pictures:


2. Lottery turntable

3, Picture folding

4, progress bar rotation

5. Particle effect

One, switch pictures

Animations that look very complex can be implemented simply by using a small amount of computation and coding. To do this, you need to study the core animation and core graphics framework in iOS development. In daily work, for a lot of things superficial understanding, just bring over to use, even do not study, encapsulation of others code, this practice is very bad. I like to build my own wheels, the wheels are made more, and the development experience and thinking are promoted.

This animation implementation is relatively simple, using the cabasicanimation, Cakeyframeanimation and Caanimationgroup. It seems that the two pictures have their own different animation, is actually just an animation method, its translation direction and rotation angle of different.

I used the cabasicanimation set the view's Zposition value, the Cakeyframeanimation object designed the picture's displacement and the rotation animation, then puts it inside the Caanimationgroup object, starts the animation.

Here is a note, that is, the core animation set animation displacement, rotation, scaling is just an illusion, the actual view of how or how, has not really changed. So, at the end of the animation, want the correct effect, then you need to set the view of the Zposition value, the larger the value, the more the view in front (Z axis direction of "front").

Code:

#import "ViewController.h" @interface Viewcontroller () @property (nonatomic, strong) Nsmutablearray *images;
@property (nonatomic, assign) int currentindex;
@property (Weak, nonatomic) Iboutlet Uiimageview *currentimageview;
@property (Weak, nonatomic) Iboutlet Uiimageview *behindimageview;

@end @implementation Viewcontroller-(Nsmutablearray *) images {if (_images = = nil) {_images = [Nsmutablearray array];
for (int i = 1; I <= 7; i++) {UIImage *image = [uiimage imagenamed: [NSString stringwithformat:@ "%d", I]];
[_images Addobject:image];
} return _images;

}-(void) viewdidload {[Super viewdidload];
Self.currentindex = 0;
Self.currentImageView.image = Self.images[_currentindex]; }-(void) Addanimatewithpoint: (cgpoint) point angle: (cgfloat) angle Fromz: (cgfloat) Fromz Toz: (cgfloat) Toz view: (UIView * View {cabasicanimation *zposition = [[Cabasicanimation alloc] init]; zposition.keypath = @ "Zposition"; zposition.fromv
Alue = @ (FROMZ);
Zposition.tovalue = @ (TOZ); Zposition.duratIon = 1.2;
Cakeyframeanimation *rotation = [[Cakeyframeanimation alloc] init];
Rotation.keypath = @ "Transform.rotation";
rotation.values = @[@ (0), @ (angle), @ (0)];
Rotation.duration = 2; Rotation.timingfunctions = @[[Camediatimingfunction functionwithname:kcamediatimingfunctioneaseineaseout], [
Camediatimingfunction Functionwithname:kcamediatimingfunctioneaseineaseout]];
Cakeyframeanimation *position = [[Cakeyframeanimation alloc] init];
Position.keypath = @ "position";
Cgpointmake ( -20) position.values = @[[Nsvalue Valuewithcgpoint:cgpointzero], [Nsvalue Valuewithcgpoint:point],
[Nsvalue Valuewithcgpoint:cgpointzero]]; Position.timingfunctions = @[[Camediatimingfunction functionwithname:kcamediatimingfunctioneaseineaseout], [
Camediatimingfunction Functionwithname:kcamediatimingfunctioneaseineaseout]];
Position.additive = YES;
Position.duration = 1.2;
Caanimationgroup *animategroup = [[Caanimationgroup alloc] init];
Animategroup.animations = @[zposition, rotation, position];Animategroup.begintime = 0.5;
Animategroup.delegate = self;
Animategroup.duration = 1.2;
[Animategroup setvalue:view forkey:@ "View"]; 
[View.layer Addanimation:animategroup Forkey:nil];

View.layer.zPosition = Toz; }-(void) Animationdidstop: (Caanimation *) Anim finished: (BOOL) flag {caanimationgroup *group = [Anim valueforkey:@ "View"
];
if (group!= nil) {self.currentImageView.image = Self.images[_currentindex]; self.currentImageView.layer.zPosition = 1;
Self.behindImageView.image = nil;
Self.behindImageView.layer.zPosition =-1; }-(Ibaction) Previous: (ID) Sender {self.currentindex = (self.currentindex + 1)% Self.images.count; Self.behindimagevie

W.image = Self.images[_currentindex];
[Self Addanimatewithpoint:cgpointmake ( -90) angle:0.15 fromz:-1 toz:1 View:self.behindImageView];
[Self Addanimatewithpoint:cgpointmake ( -20) angle:-0.15 fromz:1 toz:-1 View:self.currentImageView]; }-(Ibaction) Next: (ID) Sender {self.currentindex = (self.currentindex + 6)% Self.images.count;
Self.behindImageView.image = Self.images[_currentindex];
[Self Addanimatewithpoint:cgpointmake ( -90) angle:-0.15 fromz:-1 toz:1 View:self.behindImageView];
[Self Addanimatewithpoint:cgpointmake ( -20) angle:0.15 fromz:1 toz:-1 View:self.currentImageView]; } @end

Second, the lottery turntable

The main difficulty in the implementation of this animation is the button placement, as long as the button is placed, the other is a simple animation to add a process.

12 Constellations, you need 12 button. In placing them, I set the button's Anchorpoint to (0.5, 1), set the button's position as the center of the centre circle, and then set the transform to rotate them, to achieve the purpose of placing them around a circle.

What you need to know is that, in general, the control's anchorpoint is the center of the control, so when we do the rotation, translation, and so on, that is, a series of operations around the center point. However, most of the time, just set the animation around the center point, it will be very complex, Calayer provides a Anchorpoint property, allows us to change their values freely, so as to achieve more complex animation.

There is the button click event, in fact, because a sector is the top of the big, small below, if not to do the corresponding restrictions, when the user clicks on the area below, it is likely not to select the current button, so to make a certain limit. Here I've customized a button that rewrites the Hittest:wwthevent: method, which sets the range of events you want to listen to.

Code:

#import "ZYWheelView.h" #define ZYIMAGEW #define ZYIMAGEH @interface Zybutton:uibutton @end @implementation zybut Ton/** * Override this method to intercept the button's Click * * * * * * (UIView *) HitTest: (cgpoint) point withevent: (Uievent *) Event {cgfloat BTNW = Self.boun
Ds.size.width;
CGFloat BTNH = self.bounds.size.height;
CGFloat x = 0;
CGFloat y = btnh/2;
CGFloat w = btnw;
CGFloat h = y;
CGRect rect = CGRectMake (x, Y, W, h); if (Cgrectcontainspoint (rect, point)) {return nil;}
else{return [Super Hittest:point withevent:event];}
-(CGRect) Imagerectforcontentrect: (CGRect) contentrect {cgfloat ImageX = (contentrect.size.width-zyimagew) * 0.5;
CGFloat imagey = 18;
Return CGRectMake (ImageX, Imagey, Zyimagew, Zyimageh); }-(void) sethighlighted: (BOOL) highlighted {} @end @interface Zywheelview () @property (weak, nonatomic) Iboutlet Uiimag

Eview *wheelview;

@property (nonatomic, weak) UIButton *lastselectedbtn;
@property (nonatomic, strong) Cadisplaylink *timer; @end @implementation Zywheelview + (InstanCetype) Wheelview {return [[[NSBundle Mainbundle] loadnibnamed:@ "Zywheelview" Owner:nil Options:nil] lastObject];-(VO
ID) awakefromnib {self.wheelView.userInteractionEnabled = YES;

CGFloat angle = 2 * m_pi/12.0;
UIImage *normalimage = [uiimage imagenamed:@ "Luckyastrology"];
UIImage *selectedimage = [uiimage imagenamed:@ "luckyastrologypressed"];
for (int bi = 0; bi < bi++) {Zybutton *btn = [[Zybutton alloc] init];
[Btn setbackgroundimage:[uiimage imagenamed:@ "luckyrototeselected"] forstate:uicontrolstateselected]; Cut the picture, set the cut picture to the button///Cgimage rect is used as pixel to use//Uikit is the point coordinate system//coordinate system features: If on the Retain screen 1 points equals 1 pixels//On the Retain screen 1 dots equals 2 pixels cgflo
at imageh = Zyimageh * [UIScreen Mainscreen].scale;
CGFloat Imagew = Zyimagew * [UIScreen Mainscreen].scale;
CGFloat imagey = 0;
CGFloat ImageX = bi * IMAGEW;
CGRect rect = CGRectMake (ImageX, Imagey, Imagew, Imageh);
Cgimageref normalref = Cgimagecreatewithimageinrect (normalimage.cgimage, rect); Cgimageref Selectedref = CgimagecreatewithimageiNrect (Selectedimage.cgimage, rect);
[btn Setimage:[uiimage Imagewithcgimage:normalref] forstate:uicontrolstatenormal];
[btn Setimage:[uiimage Imagewithcgimage:selectedref] forstate:uicontrolstateselected];
Btn.bounds = CGRectMake (0, 0, 58, 143);
Btn.layer.anchorPoint = Cgpointmake (0.5, 1);
Btn.layer.position = Cgpointmake (self.frame.size.width * 0.5, Self.frame.size.height * 0.5);
Btn.transform = cgaffinetransformmakerotation (angle * bi);
[Btn addtarget:self Action: @selector (CLICKBTN:) forcontrolevents:uicontroleventtouchupinside];
[Self.wheelview ADDSUBVIEW:BTN];
} [self startrotating]; }-(void) startrotating {if (self.timer) return; self.timer = [Cadisplaylink displaylinkwithtarget:self selector: @select
or (Updatetimer)];
[Self.timer Addtorunloop:[nsrunloop Mainrunloop] formode:nsrunloopcommonmodes]; }-(void) stoprotating {[Self.timer invalidate]; self.timer = nil;}-(void) CLICKBTN: (UIButton *) btn {self.lastselected
btn.selected = NO;
btn.selected = YES; SELF.LASTSELECTEDBTN = BTN
}-(Ibaction) CLICKCENTERBTN: (ID) Sender {self.userinteractionenabled = NO;
[Self stoprotating];
Cabasicanimation *basicanimation = [cabasicanimation animationwithkeypath:@ "transform.rotation"];
Basicanimation.tovalue = @ (M_PI * 2 * 5);
Basicanimation.duration = 2;
Basicanimation.timingfunction = [Camediatimingfunction functionwithname:kcamediatimingfunctioneaseineaseout];
Basicanimation.removedoncompletion = NO;
Basicanimation.fillmode = Kcafillmodeforwards;
Basicanimation.delegate = self;
[Self.wheelView.layer addanimation:basicanimation Forkey:nil]; }-(void) Animationdidstop: (Caanimation *) Anim finished: (BOOL) flag {self.userinteractionenabled = YES; Gets the rotation degree according to the selected button,//Gets the angle through the transform cgfloat angle = atan2 (SELF.LASTSELECTEDBTN.TRANSFORM.B,
SELF.LASTSELECTEDBTN.TRANSFORM.A);
From actually rotating turntable self.wheelView.transform = cgaffinetransformmakerotation (-angle); Dispatch_after (Dispatch_time (Dispatch_time_now, (int64_t) (1 * nsec_per_sec)), Dispatch_get_main_queue (), ^{[self StartroTating]; 
}); }-(void) Updatetimer {self.wheelView.transform = Cgaffinetransformrotate (Self.wheelView.transform, m_pi/200);}-(Voi D) dealloc {[Self stoprotating];} @end

3, Picture folding

The effect looks cool, but actually it's easier to do. Requires three view, two Uiimageview, a view that accepts drag action. Calayer inside has a contentrect attribute, it can set layer inside display content, use this attribute, we can do when downloading picture, download a little show effect. Here, I use this property to come here is the two uiimageview each show half of the picture, and then the two pieces of ImageView together, display the complete picture.

Add a drag gesture to the view that covers the entire picture to implement the animation process.

Here's a new layer that needs to be learned, Cagradientlayer, which is used to make color gradients, similar to the usage of Calayer:

Property Code:

Cagradientlayer *gradientlayer = [Cagradientlayer layer];
Gradientlayer.frame = self.bottomView.bounds;
gradientlayer.opacity = 0;
Gradientlayer.colors = @[(ID) [Uicolor clearcolor]. Cgcolor, (ID) [Uicolor blackcolor]. Cgcolor];
Self.gradientlayer = Gradientlayer;
[Self.bottomView.layer Addsublayer:gradientlayer];
Set gradient color
//gradientl.colors = @[(ID) [Uicolor redcolor]. Cgcolor, (ID) [Uicolor greencolor]. Cgcolor, (ID) [Uicolor yellowcolor]. Cgcolor];
Set gradient locator point
//gradientl.locations = @[@0.1,@0.4,@0.5];
Sets the gradient start point, taking the value 0~1
//gradientl.startpoint = Cgpointmake (0, 1);

After setting up, in the pan gesture method to constantly change the gradientlayer opacity can achieve the desired effect.

Catransform3d has a M34 property, you can set the perspective, typically set this value to-1/500.0, specific requirements can fine-tune this value.

Code:

#import "ViewController.h" @interface Viewcontroller () @property (weak, nonatomic) Iboutlet Uiimageview;
@property (Weak, nonatomic) Iboutlet Uiimageview *bottomview;
@property (Weak, nonatomic) Iboutlet UIView *containview;
@property (nonatomic, weak) Cagradientlayer *gradientlayer; @end @implementation Viewcontroller-(void) viewdidload {[Super viewdidload];//do no additional setup after loading T
He view, typically from a nib.
[Self setupotherview];
Sets the shadow of a gradient [self setupshadow]; }-(void) Setupotherview {//Set Contentsrect used to indicate the size of the picture display, you can do the side of the download side of the UI effect, take the value is (0--1) Self.topView.layer.contentsRect =
CGRectMake (0, 0, 1, 0.5);
Self.topView.layer.anchorPoint = Cgpointmake (0.5, 1);
Self.bottomView.layer.contentsRect = CGRectMake (0, 0.5, 1, 0.5);
Self.bottomView.layer.anchorPoint = cgpointmake (0.5, 0);
Uipangesturerecognizer *gesture = [[Uipangesturerecognizer alloc] initwithtarget:self action: @selector (pan:)];
[Self.containview Addgesturerecognizer:gesture];
}-(void) Setupshadow{Cagradientlayer *gradientlayer = [Cagradientlayer layer]; gradientlayer.frame = self.bottomView.bounds;
gradientlayer.opacity = 0; Gradientlayer.colors = @[(ID) [Uicolor clearcolor]. Cgcolor, (ID) [Uicolor blackcolor].
Cgcolor];
Self.gradientlayer = Gradientlayer;
[Self.bottomView.layer Addsublayer:gradientlayer]; Set gradient color//gradientl.colors = @[(ID) [Uicolor redcolor]. Cgcolor, (ID) [Uicolor greencolor]. Cgcolor, (ID) [Uicolor yellowcolor].
Cgcolor];
Set gradient anchor//gradientl.locations = @[@0.1,@0.4,@0.5];
Sets the gradient start point, taking the value 0~1//gradientl.startpoint = Cgpointmake (0, 1);  }-(void) pan: (Uipangesturerecognizer *) recognizer {cgfloat y = [recognizer translationinview:self.containview].y; if (y
>=) y = 300;
if (y <= -300) y =-300;
Rotation angle, downward counter-clockwise rotation cgfloat angle =-y/320.0 * M_PI;
Self.topView.layer.transform = catransform3didentity;
Catransform3d transfrom = catransform3didentity;
TRANSFROM.M34 = -1/500.0;
Self.topView.layer.transform = Catransform3drotate (Transfrom, Angle, 1, 0, 0); Self. gradientlayer.opacity = y/300.0; if (recognizer.state = = uigesturerecognizerstateended) {//Spring effect animation//springwithdamping: elasticity coefficient, smaller, spring effect more obvious [UIView animate withduration:0.5 delay:0 usingspringwithdamping:0.3 initialspringvelocity:11 options:
Uiviewanimationoptioncurveeaseinout animations:^{self.topView.layer.transform = catransform3didentity;
self.gradientLayer.opacity = 0;
} Completion:nil]; }} @end

4. Rotating progress bar

Circle rotation is usually placed on the HUD bar. Remember before I have done a similar function, at that time did not have such a knowledge reserve, can only be done with cakeyframeanimation, so that the artist made a top is a small white dot, in addition, very long that part is for the Clearcolor small rectangle, Then I set it to Anchorpoint, add a round path to cakeyframeanimation, and then rotate around the path and do it reluctantly, but it's not easy to see.

Now you can have a better choice, Careplicatorlayer (copy layer). We can add a instance layer inside the duplicate layer, if the duplicate layer is set InstanceCount, if InstanceCount = = 5, then the duplicate layer will automatically help us copy 5 layers of the same layer (in fact, We can at the beginning of the instance layer set animation, then in the copy, the same animation will be copied over, in addition, you can also set the copy layer inside the instance layer of Transfrom, so as to achieve a certain layout. There is also a instancedelay in the duplicate layer, which indicates how much time the delay began to animate and so on.

This demo is using the above mentioned implementation of the Code:

#import "ViewController.h" @interface Viewcontroller () @property (weak, nonatomic) Iboutlet UIView; @end @implementation Viewcontroller-(void) viewdidload {[Super viewdidload];//do no additional setup after loading th

E view, typically from a nib.
[Self setupreplicatorlayerandanimation];
}-(void) setupreplicatorlayerandanimation {careplicatorlayer *replicatorlayer = [Careplicatorlayer layer];
Replicatorlayer.frame = Self.containView.layer.bounds;
[Self.containView.layer Addsublayer:replicatorlayer];
Calayer *layer = [Calayer layer];
Layer.frame = CGRectMake (self.containView.frame.size.width * 0.5, 20, 16, 16); Layer.backgroundcolor = [Uicolor Redcolor].
Cgcolor;
Layer.cornerradius = LAYER.FRAME.SIZE.WIDTH/2;
This sentence can remove the initial process Layer.transform = Catransform3dmakescale (0, 0, 0);
[Replicatorlayer Addsublayer:layer];
Replicatorlayer.instancecount = 22;
Cabasicanimation *basican = [cabasicanimation animationwithkeypath:@ "Transform.scale"];
Basican.fromvalue = @1; Basican. Tovalue = @0;
Basican.duration = 1;
Basican.repeatcount = maxfloat;
[Layer Addanimation:basican Forkey:nil];
Replicatorlayer.instancedelay = basican.duration/(double) replicatorlayer.instancecount;
Replicatorlayer.instancetransform = catransform3dmakerotation (2 * m_pi/replicatorlayer.instancecount, 0, 0, 1); } @end

5. Particle effect

This is the combination of Careplicatorlayer (duplicate layer) and core graphics, I use Uibezierpath to draw the line, then I will assign the path to the animation of the ball, and then add the ball to the duplicate layer , set the next InstanceCount, set the delay time, the effect came out.

Code:

#import "ZYDrawView.h" @interface Zydrawview () @property (nonatomic, strong) Uibezierpath *bezierpath;
@property (nonatomic, weak) Careplicatorlayer *replicatorlayer;
@property (nonatomic, weak) Calayer *norlayer;
@end static int _count = 0; @implementation Zydrawview-(Uibezierpath *) Bezierpath {if (_bezierpath = = nil) {_bezierpath = [[Uibezierpath alloc] In
It];
return _bezierpath; }-(void) awakefromnib {careplicatorlayer *replicatorlayer = [Careplicatorlayer layer]; replicatorlayer.frame = Self.bou
Nds
[Self.layer Addsublayer:replicatorlayer];
Calayer *layer = [Calayer layer];
Layer.frame = CGRectMake (0,-200, 10, 10);
Layer.cornerradius = layer.frame.size.width * 0.5; Layer.backgroundcolor = [Uicolor Redcolor].
Cgcolor;
[Replicatorlayer Addsublayer:layer];
Self.replicatorlayer = Replicatorlayer;
Self.norlayer = layer; }-(void) Touchesbegan: (Nsset<uitouch *> *) touches withevent: (Uievent *) Event {Cgpoint Curpoint = [[Touches AnyObje
CT] locationinview:self]; [Self.bezieRpath Movetopoint:curpoint];
}-(void) touchesmoved: (Nsset<uitouch *> *) touches withevent: (Uievent *) event {_count++;
Cgpoint Curpoint = [[Touches anyobject] locationinview:self];
[Self.bezierpath Addlinetopoint:curpoint];
[Self setneedsdisplay];
}-(void) startanimation {cakeyframeanimation *keyframean = [cakeyframeanimation animationwithkeypath:@ "position"];
Keyframean.path = Self.bezierPath.CGPath;
Keyframean.duration = 4;
Keyframean.repeatcount = maxfloat;
[Self.norlayer Addanimation:keyframean Forkey:nil];
Self.replicatorLayer.instanceCount = _count;
Self.replicatorLayer.instanceDelay = 0.1;
}-(void) Redraw {_bezierpath = nil; _count = 1;

[Self.norlayer removeallanimations];
[Self setneedsdisplay]; }-(void) DrawRect: (cgrect) rect {[Self.bezierpath stroke];} @end

The above content is small series to introduce the core animation some demo summary (dynamic switch pictures, large turntable, picture folding, progress bar and other animation effects), I hope that the above help!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.