原文: Hit testing animating layers
我有一个疑问,当我们看到一个平滑的动画执行期间,它的动画属性值是立马变成我们设置的那个值还是根本就没有变?
当你想知道在动画执行期间,这个作用于渲染层的值是如何变化的时候,你会这么做?
剧透:答案是非常简单的,可以移驾去看一下 presentation layer 的属性值
我们来做一个小实验
你可以写一些可用于与模型层和呈现层交互的demo,直观明了,可以有助于你理解。你可以从中学到很多关于Core Animation 的知识。但今天我们这里,只选择关键帧动画作为演示。
好的,我们开始编码
首先我们创建一个 layer 并把它添加到我们的主视图层级中。别忘了将这个层级声明成全局变量,因为我们在后面的点击测试中会用到它。
CALayer * movingLayer = [CALayer layer];
[movingLayer setBounds: CGRectMake(0, 0, layerSize, layerSize)];
[movingLayer setBackgroundColor:[UIColor orangeColor].CGColor];
[movingLayer setPosition:CGPointMake(layerCenterInset, layerCenterInset)];
// Additional styling of the layer ...
[[[self view] layer] addSublayer:movingLayer];
[self setMovingLayer:movingLayer];
接下来我们创建关键帧动画,设置它的位置,然后把这个动画添加到上面新建的layer 上。
CAKeyframeAnimation * moveLayerAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
[moveLayerAnimation setValues:[NSArray arrayWithObjects: /* some NSValue-wrapped CGPoints */, nil]];
[moveLayerAnimation setDuration:10.0];
[moveLayerAnimation setRepeatCount:HUGE_VALF];
[moveLayerAnimation setTimingFunction: [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
[[self movingLayer] addAnimation:moveLayerAnimation forKey:@"move"];
为了能够让layer 与用户交互,我们需要给self.view添加手势,这里手势使用下面方法,如下:
- (IBAction)pressedLayer:(UIGestureRecognizer *)gestureRecognizer {
CGPoint touchPoint = [gestureRecognizer locationInView:[self view]];
if ([[[self movingLayer] presentationLayer] hitTest:touchPoint]) {
[self blinkLayerWithColor:[UIColor yellowColor]];
} else if ([[self movingLayer] hitTest:touchPoint]) {
[self blinkLayerWithColor:[UIColor redColor]];
}
}
通过设置层级的背景色来观察
- (void)blinkLayerWithColor:(UIColor *)color {
CABasicAnimation * blinkAnimation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
[blinkAnimation setDuration:0.1];
[blinkAnimation setAutoreverses:YES];
[blinkAnimation setFromValue:(id)[[self movingLayer] backgroundColor]];
[blinkAnimation setToValue:(id)color.CGColor];
[[self movingLayer] addAnimation:blinkAnimation forKey:@"blink"];
}
OK,万事俱备,接下来让我们仔细观察一下
当我们运行程序,首先看到的是一个移动的橘黄色的方块:
当你点击layer的原始位置,发现方块慢慢的变成了红色,你也可以等着橘色方块远离了原始位置时,再去点击,发现效果都一样。发生了什么,它不是移动了嘛,为什么点击原始位置还会起作用。你在仔细观察在动画期间他位置的真实值。
你也可以注意到当我们点击移动的区块时,发现它又慢慢的变成了黄色。
还有一些其他好玩的东西
回到我们的关键帧动画的代码,改变这个动画的calculation mode,添加下面这一行代码:
[moveLayerAnimation setCalculationMode:kCAAnimationCubic];
现在,再次运行程序,你将会看到layer沿着一个非常酷的,非常平滑的曲线轨迹运动,而不是一个非常乏味的直线运动。哈哈,是不是很棒。还要注意,虽然layer是沿着这条曲线运动,但你仍然可以点击它,多么神奇。
我们发现,它的原始位置的值没有变,也很好理解,CAKeyFrameAninmation 是显式动画。
显示动画是不会改变它的动画属性值的,像 CABasicAnimation 和CAKeyFrameAninmation。而仅仅隐式动画才会改变动画属性值。