UIView动画
1.UIView(UIViewAnimation)
- (void)startAnimating
{
[UIView beginAnimations:@"squareAnimation" context:(__bridge void *)(self)];//第一个参数是id,之后会用到,第二个参数context 是上下文的意思。
[UIView setAnimationDelegate:self];
[UIViewsetAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
[UIView setAnimationDuration:0.4]; 设置运动时间,不设置的话默认是0.2
[UIView setAnimationRepeatCount:2];//重复执行次数
[UIView setAnimationRepeatAutoreverses:YES];//动画自动往回走
_square.center = CGPointMake(_square.center.x + 100, _square.center.y);往右偏移100,view移动需要放到最后面执行,要不会和预期的效果不一样
[UIView commitAnimations];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"Flip animation";
_rootView = [[UIView alloc] init];
_rootView.bounds = CGRectMake(0, 0, 50, 50);
_rootView.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
_rootView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_rootView];
_square1 = [[UIView alloc] init];
_square1.backgroundColor = [UIColor orangeColor];
_square1.frame = _rootView.bounds;
[_rootView addSubview:_square1];
_square2 = [[UIView alloc] init];
_square2.backgroundColor = [UIColor yellowColor];
_square2.frame = _square1.frame;
_square2.hidden = YES;
[_rootView addSubview:_square2];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent*)event
{
[self startFliping];
// [self startBlockFliping1];
// [self startBlockFliping2];
}
- (void)startFliping
{
[UIView beginAnimations:@"squareAnimation" context:(__bridge void *)(self)];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:_rootView cache:YES];
_square1.hidden = !_square1.hidden;
_square2.hidden = !_square2.hidden;
[UIView commitAnimations];
}
typedefNS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,//无效果
UIViewAnimationTransitionFlipFromLeft,//从左边翻转
UIViewAnimationTransitionFlipFromRight,//从右边翻转
UIViewAnimationTransitionCurlUp,//向上翻纸的效果
UIViewAnimationTransitionCurlDown,//向下翻纸的效果
};
Block动画实现
UIViewAnimationOptions options = UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat|UIViewAnimationOptionTransitionFlipFromLeft;
[UIView animateWithDuration:0.4 delay:0 options:options animations:^{
[UIView setAnimationRepeatCount:2];
_square.center = CGPointMake(_square.center.x+100, _square.center.y+100);//操作UI的代码要放到最后面才能生效。
}completion:^(BOOLfinished) {
_square.center =CGPointMake(_square.center.x-100, _square.center.y-100);
}];
UIViewAnimationOptionShowHideTransitionViews = 1 << 8,// flip to/from hidden state instead of adding/removing //修改hidden属性来代替adding/removing操作
UIViewAnimationOptionTransitionCrossDissolve = 5 << 20, //渐变效果
UIViewAnimationOptionTransitionFlipFromTop = 6 << 20,向上翻转
UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20,向下翻转
//下面是两种block实现的动画效果
- (void)startBlockFliping1
{
UIViewAnimationOptions options = UIViewAnimationOptionTransitionFlipFromLeft
/* | UIViewAnimationOptionAllowAnimatedContent */;
[UIView transitionWithView:_rootView duration:1 options:options animations:^{
_square1.hidden = !_square1.hidden;
// _square2.hidden = !_square2.hidden;
}completion:nil];
}
- (void)startBlockFliping2
{
UIView *fromView = _square1.hidden ? _square2 : _square1;
UIView *toView = _square1.hidden ? _square1 : _square2;
UIViewAnimationOptions options = UIViewAnimationOptionTransitionFlipFromTop
|UIViewAnimationOptionShowHideTransitionViews
/* | UIViewAnimationOptionAllowAnimatedContent */;
[UIView transitionFromView:fromView toView:toView duration:1 options:options completion:nil];
}
Problem
//
// PlayViewController.m
// UIViewAnimationDemo
//
// Created by Chengyin on 16/7/3.
// Copyright © 2016年 NetEase. All rights reserved.
//
#import "PlayViewController.h"
staticconstCGFloatcoverSize = 150.0f;
staticconstCGFloatdiskSize = 238.0f;
staticconstCGFloatneedleWidth = 162.0f;
staticconstCGFloatneedleHeight = 306.0f;
staticconstCGFloatneedleRotationDegree = -M_PI_4/ 1.5;
staticconstNSTimeIntervaldiskAnimationDuration = 20;
staticconstNSTimeIntervalneedleAnimationDuration = 0.3;
@interface PlayViewController ()
{
@private
UIImageView*_needleView;
UIImageView*_diskImageView;
UIImageView*_coverimageView;
BOOL_playing;
BOOL_animating;
}
@end
@implementationPlayViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = @"Play animation";
self.view.backgroundColor = [UIColor whiteColor];
_coverimageView = [[UIImageView alloc] init];
_coverimageView.image = [UIImage imageNamed:@"Cover.jpg"];
[self.view addSubview:_coverimageView];
_diskImageView = [[UIImageView alloc] init];
_diskImageView.image = [UIImage imageNamed:@"Disk.png"];
[self.view addSubview:_diskImageView];
_needleView = [[UIImageView alloc] init];
_needleView.image = [UIImage imageNamed:@"Needle.png"];
[self.view addSubview:_needleView];
_needleView.transform = CGAffineTransformMakeRotation(needleRotationDegree);//原来的图片是杆子是放下的,所以要让它抬起来需要改变transform
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
_needleView.bounds = CGRectMake(0, 0, needleWidth, needleHeight);
_needleView.center = CGPointMake(CGRectGetMidX(self.view.bounds), 64);
_diskImageView.bounds = CGRectMake(0, 0, diskSize, diskSize);
_diskImageView.center = CGPointMake(CGRectGetMidX(self.view.bounds), 64 + 80 + diskSize / 2);
_coverimageView.bounds = CGRectMake(0, 0, coverSize, coverSize);
_coverimageView.center = _diskImageView.center;
}
#pragma mark - needle
- (void)toggleNeedle:(void(^)(BOOLfinished))completion
{
_animating = YES;
_playing = !_playing;
[UIView animateWithDuration:needleAnimationDuration animations:^{
_needleView.transform = _playing ? CGAffineTransformIdentity : CGAffineTransformMakeRotation(needleRotationDegree);
}completion:^(BOOLfinished) {
_animating=NO;
if(completion)
{
completion(finished);
}
}];
}
#pragma mark - play & stop
- (void)play
{
if (_playing || _animating)
{
return;
}
[selftoggleNeedle:^(BOOLfinished) {
[self startRotation];
}];
}
- (void)stop
{
if (!_playing || _animating)
{
return;
}
[self toggleNeedle:nil];
[self stopRotation];
}
- (void)startRotation
{
[UIView animateKeyframesWithDuration:diskAnimationDuration delay:0 options:UIViewKeyframeAnimationOptionRepeat|UIViewAnimationOptionCurveLinear animations:^{
//不能直接设置360*,系统会自动选择最短路径来弄,所以看到的效果会是没动。需要按照下面的来设置才行。
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.25 animations:^{
_diskImageView.transform = CGAffineTransformMakeRotation(M_PI_2);//1/4
_coverimageView.transform = _diskImageView.transform;
}];
[UIView addKeyframeWithRelativeStartTime:0.25 relativeDuration:0.25 animations:^{
_diskImageView.transform = CGAffineTransformMakeRotation(M_PI);//1/2
_coverimageView.transform = _diskImageView.transform;
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.25 animations:^{
_diskImageView.transform = CGAffineTransformMakeRotation(M_PI_2 * 3);//3/2
_coverimageView.transform = _diskImageView.transform;
}];
[UIView addKeyframeWithRelativeStartTime:0.75 relativeDuration:0.25 animations:^{
_diskImageView.transform = CGAffineTransformMakeRotation(M_PI * 2);//1
_coverimageView.transform = _diskImageView.transform;
}];
}completion:nil];
}
- (void)stopRotation
{
[UIView animateWithDuration:0 animations:^{
_diskImageView.transform = CGAffineTransformIdentity;
_coverimageView.transform = _diskImageView.transform;
}];
}
#pragma mark - touch
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent*)event
{
if (_playing)
{
[self stop];
}
else
{
[self play];
}
}
@end
CoreAnimation(1)
概念一、隐式动画:通过直接给属性赋值来做的
概念二、Layer树
概念三、CATransaction:打包当前时间点的所有动画操作
- (void)testTransaction
{
[CATransaction begin];
[CATransaction setCompletionBlock:^{
NSLog(@"Set position animation completed.");
}];
[CATransaction setDisableActions:YES];
[CATransaction setAnimationDuration:1];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
_myLayer.position = CGPointMake(_myLayer.position.x + 100, _myLayer.position.y);
[CATransaction commit];
}
- (void)disableAnimation
{
[CATransaction begin];
[CATransaction setDisableActions:YES];
_myLayer.position = CGPointMake(_myLayer.position.x + 100, _myLayer.position.y);
[CATransaction commit];
}
#import "CALayer+AnimationControl.h"
#pragma mark - pause & resume
- (void)pause
{
if (!_playing || _animating)
{
return;
}
[self toggleNeedle:nil];
[self pauseRotation];
}
- (void)resume
{
if (_playing || _animating)
{
return;
}
[selftoggleNeedle:^(BOOLfinished) {
[self resumeRotation];
}];
}
- (void)pauseRotation
{
[_diskImageView.layer ac_pause];
[_coverimageView.layer ac_pause];
}
- (void)resumeRotation
{
[_diskImageView.layer ac_resume];
[_coverimageView.layer ac_resume];
}
#import "CALayer+AnimationControl.h"
@implementationCALayer (AnimationControl)
- (void)ac_pause
{
CFTimeInterval localTime = [self convertTime:CACurrentMediaTime() fromLayer:nil];
self.speed= 0.0;
self.timeOffset= localTime;
}
- (void)ac_resume
{
CFTimeInterval lastLocalTime = self.timeOffset;
self.speed= 1.0;
self.timeOffset= 0.0;
self.beginTime= 0.0;
CFTimeInterval localTime = [self convertTime:CACurrentMediaTime() fromLayer:nil];
self.beginTime= localTime - lastLocalTime;
}
@end
类目的地址:https://pan.baidu.com/s/17fdSz4uO7WewOg3EDCjxUg
CoreAnimation 2
一、利用CALayer的锚点来对这个转轴进行抬起,放下操作
前文:用transform是对图片的中心点进行操作旋转
现在用CALayer来实现
staticconstCGFloatneedleWidth = 111.0f;
staticconstCGFloatneedleHeight = 183.0f;
staticconstCGFloatneedleAxisX = 30.0f;//距左30
staticconstCGFloatneedleAxisY = 30.0f;距离上边30
CATransform3D transform = CATransform3DIdentity;
_needleView.layer.anchorPoint = CGPointMake(needleAxisX / needleWidth, needleAxisY / needleHeight);//锚点计算,距离左边,上边30pt,anchorPoint是0到1,这里需要换算所以需要30除于图片宽度和高度
transform.m34 = -1.0/2000;//设置视角才能让唱针显示,因为transform是三维的,这个值需要尽量的小。
_needleView.frame = CGRectMake(self.view.bounds.size.width / 2 - needleAxisX, navigationHeight - needleAxisY, needleWidth, needleHeight);//唱针的frame计算