迅速:创建眩光按钮动画

时间:2018-08-08 17:00:42

标签: ios swift

我的项目中有一个按钮。我想像这样向我的按钮添加眩光动画:

enter image description here

enter image description here

enter image description here

如果用户点击按钮,则删除动画。

如何添加动画?

1 个答案:

答案 0 :(得分:2)

您可以通过向CALayer添加按钮内容的较浅版本,然后遮盖该层并设置遮罩动画来创建类似效果。例如:

extension UIButton {

    func flash() {
        // Take as snapshot of the button and render as a template
        let snapshot = self.snapshot?.withRenderingMode(.alwaysTemplate)
        let imageView = UIImageView(image: snapshot)
        // Add it image view and render close to white
        imageView.tintColor = UIColor(white: 0.9, alpha: 1.0)
        guard let image = imageView.snapshot  else { return }
        let width = image.size.width
        let height = image.size.height
        // Create CALayer and add light content to it
        let shineLayer = CALayer()
        shineLayer.contents = image.cgImage
        shineLayer.frame = bounds

        // create CAGradientLayer that will act as mask clear = not shown, opaque = rendered
        // Adjust gradient to increase width and angle of highlight
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [UIColor.clear.cgColor,
                                UIColor.clear.cgColor,
                                UIColor.black.cgColor,
                                UIColor.clear.cgColor,
                                UIColor.clear.cgColor]
        gradientLayer.locations = [0.0, 0.35, 0.50, 0.65, 0.0]
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)

        gradientLayer.frame = CGRect(x: -width, y: 0, width: width, height: height)
        // Create CA animation that will move mask from outside bounds left to outside bounds right
        let animation = CABasicAnimation(keyPath: "position.x")
        animation.byValue = width * 2
        // How long it takes for glare to move across button
        animation.duration = 3
        // Repeat forever
        animation.repeatCount = Float.greatestFiniteMagnitude
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

        layer.addSublayer(shineLayer)
        shineLayer.mask = gradientLayer

        // Add animation
        gradientLayer.add(animation, forKey: "shine")
    }

    func stopFlash() {
        // Search all sublayer masks for "shine" animation and remove
        layer.sublayers?.forEach {
            $0.mask?.removeAnimation(forKey: "shine")
        }
    }
}

extension UIView {
    // Helper to snapshot a view
    var snapshot: UIImage? {
        let renderer = UIGraphicsImageRenderer(size: bounds.size)

        let image = renderer.image { context in
            layer.render(in: context.cgContext)
        }
        return image
    }
}

您可以像这样使用它:

final class ViewController: UIViewController {

    let button = UIButton()

    override func viewDidLoad() {
        view.backgroundColor = .white
        button.setTitle("My Special Button", for: .normal)
        button.setTitleColor(.red, for: .normal)
        button.sizeToFit()
        button.addTarget(self, action: #selector(didPressButton(_:)), for: .touchUpInside)
        view.addSubview(button)
        let tableView = UITableView()
        tableView.contentInsetAdjustmentBehavior == .never
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        button.flash()
    }

    @objc func didPressButton(_ sender: UIButton) {
        sender.stopFlash()
    }
}

您应该获得如下效果:

button with glare effect