ios 如何在Swift中连续创建涟漪效果并在延迟后重复该过程

jchrr9hc  于 2023-05-02  发布在  iOS
关注(0)|答案(1)|浏览(104)

我正在开发一个iOS应用程序,我需要在UIView上创建涟漪效果。我能够创建涟漪效应,但我不能定制它。这就是我想要实现的:

这是我当前的输出

我想实现的是连续创造4-5个涟漪,然后经过一些延迟,再创造4-5个涟漪,无限重复这个过程。但目前我只能创建1个涟漪(它确实无限)。
下面是我的代码:

func addRipple(rView: UIView) {
    let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: rView.bounds.size.width, height: rView.bounds.size.height))

    let shapePosition = CGPoint(x: rView.bounds.size.width / 2.0, y: rView.bounds.size.height / 2.0)
    let rippleShape = CAShapeLayer()
    rippleShape.bounds = CGRect(x: 0, y: 0, width: rView.bounds.size.width, height: rView.bounds.size.height)
    rippleShape.path = path.cgPath
    rippleShape.fillColor = UIColor.clear.cgColor
    rippleShape.strokeColor = UIColor.systemBlue.cgColor
    rippleShape.lineWidth = 1
    rippleShape.position = shapePosition
    rippleShape.opacity = 0
    
    rView.layer.addSublayer(rippleShape)

    let scaleAnim = CABasicAnimation(keyPath: "transform.scale")
    scaleAnim.fromValue = NSValue(caTransform3D: CATransform3DIdentity)
    scaleAnim.toValue = NSValue(caTransform3D: CATransform3DMakeScale(2, 2, 1))

    let opacityAnim = CABasicAnimation(keyPath: "opacity")
    opacityAnim.fromValue = 1
    opacityAnim.toValue = nil

    let animation = CAAnimationGroup()
    animation.animations = [scaleAnim, opacityAnim]
    animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
    animation.duration = 1
    animation.repeatCount = Float.infinity
    animation.isRemovedOnCompletion = false
    rippleShape.add(animation, forKey: "rippleEffect")
}

这就是我调用addRipple方法的方式

@IBOutlet weak var sView: UIView!
override func viewDidLoad() {
    super.viewDidLoad()
    sView.layer.cornerRadius = sView.frame.size.width / 2
    sView.layer.borderWidth = 2
    sView.layer.borderColor = UIColor.systemBlue.cgColor
    addRipple(to: sView)
}

我想我已经很接近了,但我无法弄清楚。
先谢谢你了。

qgelzfjb

qgelzfjb1#

如果我没理解错的话,你想一次在屏幕上出现多个这样的涟漪。在这种情况下,如果创建多个圆子层,并使用不同的timeOffset设置每个子层的动画,则会更方便。

let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: rView.bounds.size.width, height: rView.bounds.size.height))
let shapePosition = CGPoint(x: rView.bounds.size.width / 2.0, y: rView.bounds.size.height / 2.0)

for i in 0..<4 {
    let rippleShape = CAShapeLayer()
    
    // set up rippleShape as usual here...
    
    rView.layer.addSublayer(rippleShape)
    
    // set these up as usual too...
    let scaleAnim = ...
    let opacityAnim = ...

    let animation = CAAnimationGroup()
    animation.animations = [scaleAnim, opacityAnim]
    animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
    animation.repeatCount = Float.infinity
    animation.duration = 2
    animation.isRemovedOnCompletion = false

    // this is the important section
    let timeInBetweenRipples = 0.2
    animation.timeOffset = timeInBetweenRipples * Double(i)
    animation.speed = 0.5
    // You can tweak speed, timeInBetweenRipples, and duration as you see fit

    // don't forget to give each animation a different key
    rippleShape.add(animation, forKey: "rippleEffect\(i)")
}

下面是动画的一帧:

相关问题