使用淡入淡出效果动画CALayer蒙版的变化

4
我有一个UIView,其view.layer.mask设置为CAShapeLayer的实例。形状层包含一个路径,现在我想通过添加第二个具有奇偶规则的形状来为这个形状添加一个孔,并淡入此孔的外观。
问题是添加到路径似乎不可动画化。
[UIView animateWithDuration:2 animations:^() {
    CGPathAddPath(parentPath, nil, holePath);
    [v.layer.mask didChangeValueForKey:@"path"];
}];

我该如何为这个添加动画效果?
2个回答

5

经过一些尝试,找到了解决方法:

  1. 创建一个带有两个子层的图层,并使用它作为遮罩
  2. 将第一个没有孔的子层的不透明度从1逐渐变为0。

这样做是因为子CAShapeLayer实例似乎被用作联合。当您隐藏没有孔的第一个子层时,只有孔会被揭示出来,共享区域不会改变。

CGMutablePathRef p = CGPathCreateMutable();

// First path
CGPathAddPath(p, nil, outerPath);
CAShapeLayer *mask1 = [CAShapeLayer layer];
mask1.path = p;

// 2nd path with a hole
CGPathAddPath(p, nil, innerPath);
CAShapeLayer *mask2 = [CAShapeLayer layer];
mask2.path = p;
mask2.fillRule = kCAFillRuleEvenOdd;

CGPathRelease(p);

// Create actual mask that hosts two submasks
CALayer *mask = [CALayer layer];
[mask addSublayer:mask1];
[mask addSublayer:mask2];
myView.layer.mask = mask;
mask.frame = v.layer.bounds;
mask1.frame = mask.bounds;
mask2.frame = mask.bounds;

// ...

// Hide mask #1
CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"opacity"];
a.fromValue = @1.0;
a.toValue = @0.0;
a.duration = 1.0;
a.fillMode = kCAFillModeForwards; // Don't reset back to original state
a.removedOnCompletion = NO;
[mask1 addAnimation:a forKey:@"hideMask1"];

很聪明,干得好(投票)。你应该接受自己的答案。 - Duncan C

1
你不能使用UIView动画来动画CALayers。
大多数图层属性更改默认情况下都会进行动画处理(隐式动画)。据我回忆,形状图层路径更改是一个例外。
您需要创建一个CAAnimation对象,其中您正在动画的属性是遮罩层上的路径。
但是,这可能不会产生您想要的效果。原因是当您在形状图层上更改路径时,核心动画会尝试动画化路径形状的更改。此外,路径更改仅在起始和结束路径具有相同数量和类型的控制点时才能正常工作。
我不确定如何在不大量工作的情况下实现两个不同蒙版之间的交叉淡入淡出。
我能够想到的唯一方法是,在更改的蒙版中创建新视图外观的快照(可能使用Core Image过滤器),然后对显示该快照的图层进行交叉淡入淡出。完成交叉淡入淡出后,您将在没有动画的情况下安装新路径到您的蒙版层中,然后删除快照位图,显示真实的视图底部。
也许有一种更简单的方法可以实现您想要的效果,但我不知道那是什么。也许其中一个为SO做出贡献的CA专家可以在这里发表意见。

我有一种感觉,用这种方式来制作形状动画不会起作用,所以我找到了一个解决方法,使用子图层并改变不透明度。 - Alex B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接