123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- //
- // ShutterButton.swift
- // WeScan
- //
- // Created by Boris Emorine on 2/26/18.
- // Copyright © 2018 WeTransfer. All rights reserved.
- //
- import UIKit
- @available(iOS 10, *)
- /// A simple button used for the shutter.
- final class ShutterButton: UIControl {
-
- private let outterRingLayer = CAShapeLayer()
- private let innerCircleLayer = CAShapeLayer()
-
- private let outterRingRatio: CGFloat = 0.80
- private let innerRingRatio: CGFloat = 0.75
-
- private let impactFeedbackGenerator = UIImpactFeedbackGenerator(style: .light)
-
- override var isHighlighted: Bool {
- didSet {
- if oldValue != isHighlighted {
- animateInnerCircleLayer(forHighlightedState: isHighlighted)
- }
- }
- }
-
- // MARL: Life Cycle
-
- override init(frame: CGRect) {
- super.init(frame: frame)
- layer.addSublayer(outterRingLayer)
- layer.addSublayer(innerCircleLayer)
- backgroundColor = .clear
- isAccessibilityElement = true
- accessibilityTraits = UIAccessibilityTraitButton
- impactFeedbackGenerator.prepare()
- }
-
- required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- // MARK: - Drawing
-
- override func draw(_ rect: CGRect) {
- outterRingLayer.frame = rect
- outterRingLayer.path = pathForOutterRing(inRect: rect).cgPath
- outterRingLayer.fillColor = UIColor.white.cgColor
- outterRingLayer.rasterizationScale = UIScreen.main.scale
- outterRingLayer.shouldRasterize = true
-
- innerCircleLayer.frame = rect
- innerCircleLayer.path = pathForInnerCircle(inRect: rect).cgPath
- innerCircleLayer.fillColor = UIColor.white.cgColor
- innerCircleLayer.rasterizationScale = UIScreen.main.scale
- innerCircleLayer.shouldRasterize = true
- }
-
- // MARK: - Animation
-
- private func animateInnerCircleLayer(forHighlightedState isHighlighted: Bool) {
- let animation = CAKeyframeAnimation(keyPath: "transform")
- var values = [CATransform3DMakeScale(1.0, 1.0, 1.0), CATransform3DMakeScale(0.9, 0.9, 0.9), CATransform3DMakeScale(0.93, 0.93, 0.93), CATransform3DMakeScale(0.9, 0.9, 0.9)]
- if isHighlighted == false {
- values = [CATransform3DMakeScale(0.9, 0.9, 0.9), CATransform3DMakeScale(1.0, 1.0, 1.0)]
- }
- animation.values = values
- animation.isRemovedOnCompletion = false
- animation.fillMode = kCAFillModeForwards
- animation.duration = isHighlighted ? 0.35 : 0.10
-
- innerCircleLayer.add(animation, forKey: "transform")
- impactFeedbackGenerator.impactOccurred()
- }
-
- // MARK: - Paths
-
- private func pathForOutterRing(inRect rect: CGRect) -> UIBezierPath {
- let path = UIBezierPath(ovalIn: rect)
-
- let innerRect = rect.scaleAndCenter(withRatio: outterRingRatio)
- let innerPath = UIBezierPath(ovalIn: innerRect).reversing()
-
- path.append(innerPath)
-
- return path
- }
-
- private func pathForInnerCircle(inRect rect: CGRect) -> UIBezierPath {
- let rect = rect.scaleAndCenter(withRatio: innerRingRatio)
- let path = UIBezierPath(ovalIn: rect)
-
- return path
- }
-
- }
|