你如何创造一个“羽毛”呢;圆圈擦拭“;iOS中的动画?

你如何创造一个“羽毛”呢;圆圈擦拭“;iOS中的动画?,ios,animation,caanimation,cagradientlayer,radial-gradients,Ios,Animation,Caanimation,Cagradientlayer,Radial Gradients,我的问题需要相当多的解释。如果你想跳到问题的末尾,寻找粗体的“问题:”一词 使用核心动画和遮罩,在iOS或Mac OS中创建“循环擦除”动画相当容易 一种方法是在视图(通常是图像视图)上安装一个CAShapeLayer作为遮罩,在形状层中安装一个圆,并将圆的大小从0设置为足以覆盖整个图像的大小(r=sqrt(高度^2+宽度^2) 另一种方法是使用RadiancGradientLayer作为遮罩,将渐变中心设置为不透明颜色,然后进行突然过渡以清除图像角以外的区域。然后设置渐变层的“位置”值的动画,

我的问题需要相当多的解释。如果你想跳到问题的末尾,寻找粗体的“问题:”一词

使用核心动画和遮罩,在iOS或Mac OS中创建“循环擦除”动画相当容易

一种方法是在视图(通常是图像视图)上安装一个CAShapeLayer作为遮罩,在形状层中安装一个圆,并将圆的大小从0设置为足以覆盖整个图像的大小(
r=sqrt(高度^2+宽度^2

另一种方法是使用RadiancGradientLayer作为遮罩,将渐变中心设置为不透明颜色,然后进行突然过渡以清除图像角以外的区域。然后设置渐变层的“位置”值的动画,将透明颜色移到图像中心

这两种方法都会创建一个边缘锐利的“圆形擦除”,使图像收缩到某一点并消失

该效果如下所示:

然而,经典的电影圆形擦除动画有一个羽状边缘,而不是锐利的边界。圆形的外边缘是完全透明的。当你向中心移动时,图像在相当短的距离内变得越来越坚实,然后图像从那里进入中心是完全不透明的。当圆形收缩时油墨中,从透明到不透明的过渡厚度保持不变,圆圈逐渐变为一个点并消失。(掩模是一个圆圈,在中间是不透明的,边缘略微模糊,半径减小到0,而模糊边缘的厚度保持不变。)< /P> 这是一个老派圆圈擦拭的例子。从技术上讲,这是一个“虹膜出”,过渡到黑色,但想法是一样的:

我不知道如何使用形状层作为遮罩,使用羽状边缘实现圆擦拭。形状层始终是锐利的边缘。我可以通过使用形状层获得相当接近的效果,在形状层中,圆以50%的不透明度进行笔划,并且圆的中间以100%的不透明度填充颜色,但这无法从中获得平滑过渡我追求的是透明到不透明

我尝试过的另一种方法是使用带有3种颜色的径向渐变。我将内部颜色设置为不透明,外部颜色设置为清晰。我将外部颜色的位置设置为>1(例如1.2),中间位置设置为1,内部位置设置为0。位置数组包含
[1.2,1.0,0]
使遮罩覆盖图像的整个部分不透明,通过图像边缘的羽状过渡到透明

然后我分两步制作位置数组的动画。 在第一步中,我将locations数组设置为
[0,0,0.2]
。这会导致羽化带从拐角处移入,并在距离图像中心0.2处停止

在第二步中,我将位置数组从
[0,0,0.2]
设置为
[0,0,0]
。这会导致内部透明到不透明的中心收缩到一个点并消失

效果还可以,如果我用一个窄的模糊带和一个快速的持续时间来运行它,它看起来不错,但并不完美

以下是模糊范围为0.2,持续时间(我认为)为0.25秒时的效果:

但是,如果我在动画步骤之间引入停顿,您可以看到效果中的瑕疵:

问题:有没有一种方法可以使用核心动画将模糊半径较小(5点左右)的圆从视图的完整大小设置为0?

同样的问题也适用于其他类型的擦拭动画:锁孔、星形、侧边擦拭、长方体和其他许多类型。对于这些,我用于羽化圆擦拭的径向渐变技巧根本不起作用。(您可以使用CAShapeLayer(您要设置动画的形状)创建这些专门的擦拭动画,然后将其大小从大调整为小

通过先绘制一个圆,然后对其应用核心图像模糊过滤器,很容易创建静态模糊圆(或其他形状),但在iOS中无法设置动画,而且iOS上的CI模糊过滤器速度太慢,即使可以

这里有一个链接,指向我在本文中使用我描述的3色径向渐变创建动画的项目:

编辑: 根据James的评论,我尝试使用一个带有阴影的形状层作为遮罩。效果是正确的,但从图像的不透明部分到被阴影层遮罩的大部分透明部分仍然有一个明显的过渡。即使阴影不透明度为1.0,阴影仍然大部分透明。下面是它的内容看起来像:

使圆形状的线颜色部分透明有一定的帮助,并在图像的不透明部分和大部分透明阴影之间进行过渡。上图是以2点的线宽和0.6的不透明度抚摸形状层:

编辑#2:解决了! James使用阴影路径的想法就是解决方案。在遮罩层中,除了阴影路径之外,你不需要任何东西。如果你这样做,你可以使用shadowRadius属性来控制模糊的程度,并在一个步骤中平滑地设置阴影路径的动画,从完全包围视图的圆到消失点

我已经在更新了我的github项目,以包括径向渐变动画和阴影路径动画,以进行比较

以下是完成后的效果,首先是5像素的模糊半径:

然后使用30像素的模糊半径:


您可以使用
CAShapeLayer
上的
阴影路径创建一个轮廓模糊的圆,用作遮罩

创建一个没有填充或笔划的形状层(我们只想看到
let shapeLayer = CAShapeLayer()
shapeLayer.shadowColor = UIColor.black.cgColor
shapeLayer.shadowOffset = CGSize(width: 0, height: 0)
shapeLayer.shadowOpacity = 1
shapeLayer.shadowRadius = 5
self.maskLayer = shapeLayer
self.layer.mask = shapeLayer
func show(_ show: Bool) {
    
    let center = CGPoint(x: self.bounds.width/2, y: self.bounds.height/2)
    var newPath: CGPath
    if show {
        let radius = sqrt(self.bounds.height*self.bounds.height + self.bounds.width*self.bounds.width)/2 //assumes view is square
        newPath = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true).cgPath
    } else {
        newPath = UIBezierPath(arcCenter: center, radius: 0.01, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true).cgPath
    }
    
    let shadowAnimation = CABasicAnimation(keyPath: "shadowPath")
    shadowAnimation.fromValue = self.maskLayer.shadowPath
    shadowAnimation.toValue = newPath
    shadowAnimation.duration = totalDuration

    self.maskLayer.shadowPath = newPath
    self.maskLayer.add(shadowAnimation, forKey: "shadowAnimation")

}