Skip to content

Instantly share code, notes, and snippets.

@helloworldsmart
Created April 1, 2017 12:41
Show Gist options
  • Select an option

  • Save helloworldsmart/37e0088067fd044b60bbf44aab132b0b to your computer and use it in GitHub Desktop.

Select an option

Save helloworldsmart/37e0088067fd044b60bbf44aab132b0b to your computer and use it in GitHub Desktop.
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