Created
April 1, 2017 12:41
-
-
Save helloworldsmart/37e0088067fd044b60bbf44aab132b0b to your computer and use it in GitHub Desktop.
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 UIKit | |
| @IBDesignable | |
| class FaceView: UIView { | |
| //Don't type infer | |
| @IBInspectable | |
| var scale: CGFloat = 0.9 | |
| @IBInspectable | |
| var eyesOpen: Bool = true | |
| @IBInspectable | |
| var mouthCurvature: Double = 1.0 | |
| @IBInspectable | |
| var lineWidth: CGFloat = 5.0 | |
| @IBInspectable | |
| var color: UIColor = UIColor.blue | |
| private var skullRadius:CGFloat { | |
| return min(bounds.size.width, bounds.size.height) / 2 * scale | |
| } | |
| private var skullCenter: CGPoint{ | |
| get { | |
| return CGPoint(x: bounds.midX, y: bounds.midY) | |
| } | |
| } | |
| private enum Eye { | |
| case left | |
| case right | |
| } | |
| private func pathForEye(_ eye: Eye) -> UIBezierPath { | |
| func centerOfEye(_ eye: Eye) -> CGPoint { | |
| let eyeOffset = skullRadius / Ratios.skullRadiusToEyeOffset | |
| var eyeCenter = skullCenter | |
| eyeCenter.y -= eyeOffset | |
| eyeCenter.x += ((eye == .left) ? -1 : 1) * eyeOffset | |
| return eyeCenter | |
| } | |
| let eyeRadius = skullRadius / Ratios.skullRadiusToEyeRadius | |
| let eyeCenter = centerOfEye(eye) | |
| let path: UIBezierPath | |
| if eyesOpen { | |
| path = UIBezierPath(arcCenter: eyeCenter, radius: eyeRadius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true) | |
| } else { | |
| path = UIBezierPath() | |
| path.move(to: CGPoint(x: eyeCenter.x - eyeRadius, y: eyeCenter.y)) | |
| path.addLine(to: CGPoint(x: eyeCenter.x + eyeRadius, y: eyeCenter.y)) | |
| } | |
| path.lineWidth = lineWidth //5.0 | |
| return path | |
| } | |
| private func pathForMouth() -> UIBezierPath { | |
| let mouthWidth = skullRadius / Ratios.skullRadiusToMouthWidth | |
| let mouthHeight = skullRadius / Ratios.skullRadiusToMouthHeight | |
| let mouthOffset = skullRadius / Ratios.skullRadiusToEyeOffset | |
| let mouthRect = CGRect( | |
| x: skullCenter.x - mouthWidth / 2, | |
| y: skullCenter.y + mouthOffset, | |
| width: mouthWidth, | |
| height: mouthHeight) | |
| let smileOffset = CGFloat(max(-1, min(mouthCurvature, 1))) * mouthRect.height | |
| let start = CGPoint(x: mouthRect.minX, y: mouthRect.midY) | |
| let end = CGPoint(x: mouthRect.maxX, y: mouthRect.midY) | |
| let cp1 = CGPoint(x: start.x + mouthRect.width / 3, y: start.y + smileOffset) | |
| let cp2 = CGPoint(x: end.x - mouthRect.width / 3, y: start.y + smileOffset) | |
| //let path = UIBezierPath(rect: mouthRect) | |
| let path = UIBezierPath() | |
| path.move(to: start) | |
| path.addCurve(to: end, controlPoint1: cp1, controlPoint2: cp2) | |
| path.lineWidth = lineWidth //5.0 | |
| return path | |
| } | |
| private func pathForSkull() -> UIBezierPath { | |
| let path = UIBezierPath(arcCenter: skullCenter, radius: skullRadius, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: false) | |
| path.lineWidth = lineWidth //5.0 | |
| return path | |
| } | |
| override func draw(_ rect: CGRect) { | |
| //let skullRadius = min(bounds.size.width, bounds.size.height) / 2 * 0.9 | |
| //let skullCenter = convert(center, from: superview) | |
| //let skullCenter = CGPoint(x: bounds.midX, y: bounds.midY) | |
| //let path = UIBezierPath(arcCenter: skullCenter, radius: skullRadius, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: false) | |
| //path.lineWidth = 5.0 | |
| //UIColor.blue.set() | |
| color.set() | |
| //path.stroke() | |
| pathForSkull().stroke() | |
| pathForEye(.left).stroke() | |
| pathForEye(.right).stroke() | |
| pathForMouth().stroke() | |
| } | |
| private struct Ratios { | |
| static let skullRadiusToEyeOffset: CGFloat = 3 | |
| static let skullRadiusToEyeRadius: CGFloat = 10 | |
| static let skullRadiusToMouthWidth: CGFloat = 1 | |
| static let skullRadiusToMouthHeight: CGFloat = 3 | |
| static let skullRadiusToMouthOffset: CGFloat = 3 | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment