ios笑脸app实现
import UIKit@IBDesignable
class FaceView: UIView {@IBInspectablevar lineWidth:CGFloat=3{didSet{setNeedsLayout()}}@IBInspectablevar color:UIColor = UIColor.blueColor(){didSet{setNeedsLayout()}}@IBInspectablevar scale:CGFloat=0.9{didSet{setNeedsLayout()}}var faceCenter:CGPoint{return convertPoint(center, fromView: superview)}var faceRadius:CGFloat{return min(bounds.size.width, bounds.size.height)/2*scale}private struct Scaling {static let FaceRadiusToEyeRadiusRatio: CGFloat = 10//大圆半径(face半径)与小圆半径(eye半径)的比率,次数越小,小圆越大.因为 下面bezierPathForEye的方法中定义 eyeRadius = faceRadius / Scaling.FaceRadiusToEyeRadiusRatiostatic let FaceRadiusToEyeOffsetRatio: CGFloat = 3//大圆与小圆的偏移率,此数越大,小圆的圆心距大圆越近static let FaceRadiusToEyeSeparationRatio: CGFloat = 1.5//两个小圆之间在大圆内的分离比率static let FaceRadiusToEyeMounthWidthRatio: CGFloat = 1static let FaceRadiusToEyeMounthHeightRatio: CGFloat = 3static let FaceRadiusToEyeMounthOffsetRatio: CGFloat = 3}private enum Eye {case Left , Right}private func bezierPathForEye(whichEye: Eye) -> UIBezierPath {//此处定义的方法为设置一只眼睛的位置,上面定义了左右眼的枚举,可通过调用.Left.Right来实现两个位置的设定let eyeRadius = faceRadius / Scaling.FaceRadiusToEyeRadiusRatio//定义小圆半径是大圆半径的几分之几,此处因为FaceRadiusToEyeRadiusRatio: CGFloat = 10 故为十分之一let eyeVerticalOffset = faceRadius / Scaling.FaceRadiusToEyeOffsetRatio//小圆的垂直偏距let eyeHorizontalSeparation = faceRadius / Scaling.FaceRadiusToEyeSeparationRatio//小圆的水平距离var eyeCenter = faceCentereyeCenter.y -= eyeVerticalOffset//此处相当于是用大圆圆心的y坐标减去小圆圆心的y坐标,故小圆圆心在大圆圆心之上.若为加,则在下switch whichEye {case .Left: eyeCenter.x -= eyeHorizontalSeparation / 2//相当于大圆圆心的x坐标减去(小圆圆心的x坐标除以2),即在大圆圆心的左侧case .Right: eyeCenter.x += eyeHorizontalSeparation / 2//此处加,即在右侧}let path = UIBezierPath(arcCenter: eyeCenter, radius: eyeRadius, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true) //画圆path.lineWidth = lineWidth //设定线宽return path}private func bezierPathForSmile(fractionOfMaxSmile: Double) -> UIBezierPath {let mouthWidth = faceRadius / Scaling.FaceRadiusToEyeMounthWidthRatio//大圆半径与线宽的比率,此处线宽=大圆半径let mouthHeight = faceRadius / Scaling.FaceRadiusToEyeMounthHeightRatio//mouthHeight即线的中点到圆心的距离let mouthVerticalOffset = faceRadius / Scaling.FaceRadiusToEyeMounthOffsetRatiolet smileHeight = CGFloat(max(min(fractionOfMaxSmile, 1), -1)) * mouthHeight//此处max(min(fractionOfMaxSmile, 1), -1)限定了笑脸指数只能在-1到1之间,fractionOfMaxSmile这个参数可以自行设定,如果设定的大于1,则只取1,设定小于-1,则只取-1let start = CGPoint(x: faceCenter.x - mouthWidth / 2, y: faceCenter.y + mouthVerticalOffset) //设置起点let end = CGPoint(x: start.x + mouthWidth, y: start.y) //设置终点let cp1 = CGPoint(x: start.x + mouthWidth / 3 , y: start.y + smileHeight) //设置曲线点1,此处mouthWidth / 3用于调节曲线的弧度let cp2 = CGPoint(x: end.x - mouthWidth / 3, y: cp1.y) //设置曲线点2let path = UIBezierPath()path.moveToPoint(start)path.addCurveToPoint(end, controlPoint1: cp1, controlPoint2: cp2)path.lineWidth = lineWidthreturn path}override func drawRect(rect: CGRect) {let facePath=UIBezierPath(arcCenter: faceCenter, radius: faceRadius, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true)facePath.lineWidth=lineWidthcolor.set()facePath.stroke()bezierPathForEye(.Left).stroke()bezierPathForEye(.Right).stroke()let smiliness = 0.8let smilePath = bezierPathForSmile(smiliness)smilePath.stroke()}
}
- IBDesignable可以在storyboard中看到自定义的uiview
- IBInspectable使属性可以改变
利用协议与代理联结数据源
protocol FaceViewDataSource:class {func smilnessForFaceView(sender:FaceView)->Double?
}
手势识别实现缩放与改变笑脸弧度
@IBOutlet weak var faceView: FaceView!{didSet{faceView.dataSource=selffaceView.addGestureRecognizer(UIPinchGestureRecognizer(target: faceView, action: "scale:"))//faceView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: "changeHappiness:"))}}private struct Constants{static let HappinessGestureScale:CGFloat=4}@IBAction func changeHappiness(sender: UIPanGestureRecognizer) {switch sender.state {case .Ended:fallthroughcase .Changed:let translation=sender.translationInView(faceView)let happinessChange = -Int(translation.y/Constants.HappinessGestureScale)if happinessChange != 0{happiness+=happinessChangesender.setTranslation(CGPoint.zero, inView: faceView)}default:break}}func scale(gesture:UIPinchGestureRecognizer){if gesture.state == .Changed{scale*=gesture.scalegesture.scale=1}}
源代码:Happiness