- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
_arrow = [[Arrow alloc]initWithFrame:CGRectMake(0, 0, 40, 100)];
_arrow.opaque = NO;
_arrow.center = self.view.center;
[self.view addSubview:_arrow];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(120, 60, 80, 30);
[button setTitle:@"rotate" forState:UIControlStateNormal];
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:@selector(vibrateArrowRepeat) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
// 使用 CABasicAnimation
//通过动画的方式使罗盘的箭头旋转45度
-(void)rotateArrow
{
// capture the start and end values
/* 1. CATransform3D startValue = _arrow.layer.transform;
CATransform3D endValue =
CATransform3DRotate(startValue, M_PI/4.0, 0, 0, 1);
//change the layer, without implicit animation
[CATransaction setDisableActions:YES];
_arrow.layer.transform = endValue;
//construct the explicit animation
CABasicAnimation *anim =
[CABasicAnimation animationWithKeyPath:@"transform"];
anim.duration = 0.8;
CAMediaTimingFunction *clunk =
[CAMediaTimingFunction functionWithControlPoints:.9 :.1 :.7 :.9];
anim.timingFunction = clunk;
anim.fromValue = [NSValue valueWithCATransform3D:startValue];
anim.toValue = [NSValue valueWithCATransform3D:endValue];
//ask for the explicit animation
[_arrow.layer addAnimation:anim forKey:nil];*/
/*2. 实际上上面的代码可以简化
例如,当fromValue和toValue没有被设置时,之前和当前的属性值会被自动使用。
这是由于,presentation layer仍然保留了之前的属性值,而当前的layer已经有了新的值
简化为如下代码:
*/
[CATransaction setDisableActions:YES];
_arrow.layer.transform =
CATransform3DRotate(_arrow.layer.transform, M_PI/4.0, 0, 0, 1);;
CABasicAnimation *anim =
[CABasicAnimation animationWithKeyPath:@"transform"];
anim.duration = 0.8;
CAMediaTimingFunction *clunk =
[CAMediaTimingFunction functionWithControlPoints:.9 :.1 :.7 :.9];
anim.timingFunction = clunk;
[_arrow.layer addAnimation:anim forKey:nil];
}
//现在我们让箭头左右颤动
-(void)vibrateArrowRepeat
{
/* 1.CATransform3D nowValue = _arrow.layer.transform;
CATransform3D startValue =
CATransform3DRotate(nowValue, M_PI/40.0, 0, 0, 1);
CATransform3D endValue =
CATransform3DRotate(nowValue,- M_PI/40.0, 0, 0, 1);
//change the layer, without implicit animation
[CATransaction setDisableActions:YES];
_arrow.layer.transform = endValue;
//construct the explicit animation
CABasicAnimation *anim =
[CABasicAnimation animationWithKeyPath:@"transform"];
anim.duration = 0.05;
anim.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
anim.repeatCount = 3;
anim.autoreverses = YES;
anim.fromValue = [NSValue valueWithCATransform3D:startValue];
anim.toValue = [NSValue valueWithCATransform3D:endValue];
//ask for the explicit animation
[_arrow.layer addAnimation:anim forKey:nil];*/
/* 2.我们可以基于arrow的当前的transform,通过设置animation的additive值为YES
来计算新的rotation的值。这意味着加到animation的属性值是相对的而不是绝对的值
我们不需要依赖arrow当前的rotation,CAValueFunction告诉animation沿着z轴旋转
*/
CABasicAnimation *anim =
[CABasicAnimation animationWithKeyPath:@"transform"];
anim.duration = 0.05;
anim.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
anim.repeatCount = 3;
anim.autoreverses = YES;
anim.additive = YES; //
anim.valueFunction =
[CAValueFunction functionWithName:kCAValueFunctionRotateZ];
anim.fromValue = @(M_PI/40);
anim.toValue = @(-M_PI/40);
//ask for the explicit animation
[_arrow.layer addAnimation:anim forKey:nil];
/*
需要注意的是,这里没有@“frame”key,如果要用一个layer的frame产生动画,position和bounds 都要改变
例子:where outer is the superview of inner,and inner expands to fill the width of outer
CABasicAnimation *anim1 =
[CABasicAnimation animationWithKeyPath:@"bounds"];
//...omit the change of frame
self.innser.layer.bounds = f;
[self.inner.layer addAnimation:anim1 forKey:nil];
CABasicAnimation *anim2 =
[CABasicAnimation animationWithKeyPath:@"position"];
//...omit the change of position
self.inner.layer.position = p;
[self.inner.layer addAnimation:anim2 forKey:nil];
*/
}
09-05
09-05
09-05