どこかで見たことあるアニメーションを自作してみました。

IMG_0986.TRIM

UIViewのExtensionに波紋を表示するためのメソッド

extension UIView {

    func 波紋(touch: UITapGestureRecognizer) {
       
        // ①: タップされた場所にlayerを置き、半径200の円を描画
        let location = touch.location(in: self)
        let layer = CAShapeLayer.init()
        self.layer.addSublayer(layer)
        layer.frame = CGRect.init(x: location.x, y: location.y, width: 100, height: 100)
        layer.position = CGPoint.init(x: location.x, y: location.y)
        layer.contents = {
            let size: CGFloat = 200.0
            UIGraphicsBeginImageContext(CGSize.init(width: size, height: size))
            let context = UIGraphicsGetCurrentContext()!
            context.saveGState()
            context.setFillColor(UIColor.clear.cgColor)
            context.fill(self.frame)
            let r = CGFloat.init(size/2-10)
            let center = CGPoint.init(x: size/2, y: size/2)
            let path : CGMutablePath = CGMutablePath()
            path.addArc(center: center, radius: r, startAngle: 0, endAngle: CGFloat(Double.pi*2), clockwise: false)
            context.addPath(path)
            context.setFillColor(UIColor.lightGray.cgColor)
            context.setStrokeColor(UIColor.lightGray.cgColor)
            context.drawPath(using: .fillStroke)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            context.restoreGState()
            return image!.cgImage
        }()

        // ②: 円を拡大しつつ透明化するAnimationを用意
        let animationGroup: CAAnimationGroup = {
            let animation: CABasicAnimation = {
                let animation = CABasicAnimation(keyPath: "transform.scale")
                animation.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseOut)
                animation.duration = 0.5
                animation.isRemovedOnCompletion = false
                animation.fillMode = kCAFillModeForwards
                animation.fromValue = NSNumber(value: 0.5)
                animation.toValue = NSNumber(value: 5.0)
                return animation
            }()
           
            let animation2: CABasicAnimation = {
                let animation = CABasicAnimation(keyPath: "opacity")
                animation.duration = 0.5
                animation.isRemovedOnCompletion = false
                animation.fillMode = kCAFillModeForwards
                animation.fromValue = NSNumber(value: 0.5)
                animation.toValue = NSNumber(value: 0.0)
                return animation
            }()
           
            let group = CAAnimationGroup()
            group.beginTime = CACurrentMediaTime()
            group.animations = [animation, animation2]
            group.isRemovedOnCompletion = false
            group.fillMode = kCAFillModeBackwards
            return group
        }()
       
        // ③: layerにAnimationを適用
        CATransaction.setAnimationDuration(5.0)
        CATransaction.setCompletionBlock({
            layer.removeFromSuperlayer()
        })
        CATransaction.begin()
        layer.add(animationGroup, forKey: nil)
        layer.opacity = 0.0
        CATransaction.commit()
    }
}

使い方:

override func awakeFromNib() {
    super.awakeFromNib()

    let tapGesture = UITapGestureRecognizer.init(target: self, action: #selector(self.tapContentView(touch:)))
    self.contentView.addGestureRecognizer(tapGesture)
}

@objc func tapContentView(touch: UITapGestureRecognizer) {

    self.contentView.波紋(touch: touch)
}

Post Navigation