swift 实现一个点击水波纹效果的动画

2024-06-03  本文已影响0人  流星阁

直接上代码

extension UIView {
 /// 实现一个点击扩散的水波纹动画
    /// - Parameters:
    ///   - point: 点击点
    ///   - color: 波纹的颜色
    ///   - duration: 动画时长
    public func runRippleAnimation(
        point: CGPoint,
        color: UIColor = .red,
        duration: TimeInterval = 0.3
    ) {
        let layerName = "ripperAnimation"
        layer.sublayers?.forEach { layer in
            if layer.name == layerName {
                layer.removeFromSuperlayer()
            }
        }

        let rippleLayer = CAShapeLayer()
        rippleLayer.backgroundColor = UIColor.clear.cgColor
        rippleLayer.path = UIBezierPath(ovalIn: CGRect(
            x: point.x - 5,
            y: point.y - 5,
            width: 10,
            height: 10
        )).cgPath
        rippleLayer.cornerRadius = bounds.height / 2
        rippleLayer.fillColor = color.cgColor
        layer.insertSublayer(rippleLayer, at: 0)

        let maxXDistance = max(point.x, bounds.width - point.x)
        let maxYDistance = max(point.y, bounds.height - point.y)
        // 计算两点之间的最大距离
        let maxDistance = sqrt(pow(maxXDistance, 2) + pow(maxYDistance, 2))

        CATransaction.begin()
        CATransaction.setCompletionBlock {
            rippleLayer.removeFromSuperlayer()
        }

        // 路径动画
        let animation = CABasicAnimation(keyPath: "path")
        animation.fromValue = rippleLayer.path
        animation.toValue = UIBezierPath(ovalIn: CGRect(
            x: point.x - maxDistance,
            y: point.y - maxDistance,
            width: 2 * maxDistance,
            height: 2 * maxDistance
        )).cgPath
        animation.timingFunction = CAMediaTimingFunction(name: .easeOut)
        animation.fillMode = .forwards

        // 透明度变化
        let opacityAnimation = CABasicAnimation(keyPath: "opacity")
        opacityAnimation.fromValue = 1
        opacityAnimation.toValue = 0

        let animationGroup = CAAnimationGroup()
        animationGroup.duration = duration
        animationGroup.timingFunction = CAMediaTimingFunction(name: .easeOut)
        animationGroup.animations = [
            animation,
            opacityAnimation,
        ]

        rippleLayer.add(animationGroup, forKey: "rippleAnimation")

        // 动画开始
        CATransaction.commit()
    }
}
上一篇 下一篇

猜你喜欢

热点阅读