Created
August 2, 2018 23:38
-
-
Save RustyKnight/9663a0b3a5f3c93d7a117ca4b86a658f to your computer and use it in GitHub Desktop.
A implementation of a circular progress image based on a UIImageView
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import UIKit | |
public class ImageViewProgess: UIImageView { | |
fileprivate var actualImage: UIImage? | |
fileprivate var grayScaleImage: UIImage? | |
@IBInspectable public override var image: UIImage? { | |
didSet { | |
actualImage = image | |
if imageLayer != nil { | |
imageLayer.contents = actualImage?.cgImage | |
} | |
grayScaleImage = actualImage?.noir?.with(alpha: actualGrayScaleAlpha) | |
super.image = grayScaleImage | |
} | |
} | |
fileprivate var actualGrayScaleAlpha: Double = 1.0 { | |
didSet { | |
grayScaleImage = actualImage?.noir?.with(alpha: actualGrayScaleAlpha) | |
setNeedsLayout() | |
setNeedsDisplay() | |
} | |
} | |
@IBInspectable var greyScaleAlpha: Double { | |
set { | |
actualGrayScaleAlpha = Swift.min(1.0, Swift.max(newValue, 0.0)) | |
setNeedsLayout() | |
setNeedsDisplay() | |
} | |
get { | |
return actualGrayScaleAlpha | |
} | |
} | |
@IBInspectable var startAngle: Double = -90.0 { | |
didSet { | |
guard shapeLayer != nil else { | |
return | |
} | |
shapeLayer.path = path(at: progress).cgPath | |
setNeedsLayout() | |
setNeedsDisplay() | |
} | |
} | |
@IBInspectable var progress: Double = 0.0 { | |
didSet { | |
guard shapeLayer != nil else { | |
return | |
} | |
shapeLayer.path = path(at: progress).cgPath | |
setNeedsLayout() | |
setNeedsDisplay() | |
} | |
} | |
internal var shapeLayer: CAShapeLayer! | |
internal var imageLayer: CALayer! | |
public override func awakeFromNib() { | |
super.awakeFromNib() | |
commonInit() | |
} | |
internal func commonInit() { | |
actualImage = image | |
grayScaleImage = actualImage?.noir?.with(alpha: actualGrayScaleAlpha) | |
image = actualImage | |
shapeLayer = CAShapeLayer() | |
shapeLayer.frame = bounds | |
shapeLayer.contentsGravity = .center | |
shapeLayer.path = path(at: progress).cgPath | |
shapeLayer.fillColor = UIColor.red.cgColor | |
imageLayer = CALayer() | |
imageLayer.frame = bounds | |
imageLayer.contentsGravity = .center | |
imageLayer.contents = actualImage?.cgImage | |
imageLayer.mask = shapeLayer | |
layer.addSublayer(imageLayer) | |
} | |
public override func prepareForInterfaceBuilder() { | |
super.prepareForInterfaceBuilder() | |
commonInit() | |
startAngle = -90.0 | |
greyScaleAlpha = 1.0 | |
} | |
public override func layoutSubviews() { | |
super.layoutSubviews() | |
shapeLayer.frame = bounds | |
imageLayer.frame = bounds | |
} | |
internal func path(at progress: Double) -> UIBezierPath { | |
let size = bounds.size | |
let center = CGPoint(x: size.width / 2.0, y: size.height / 2.0) | |
// Want to "over fill" the image area, so the mask can be applied | |
// to the entire image | |
let radius = Swift.max(size.width, size.height) | |
let startAngle = -90.0 | |
let clockwise = true; | |
let path = UIBezierPath(arcCenter: center, | |
radius: CGFloat(radius), | |
startAngle: CGFloat(startAngle.degreesToRadians), | |
endAngle: CGFloat((startAngle + (360.0 * progress)).degreesToRadians), | |
clockwise: clockwise) | |
path.addLine(to: center) | |
path.close() | |
return path | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment