IOS之笑臉app

ios笑臉app實現

import UIKit

@IBDesignable
class FaceView: UIView {

    @IBInspectable
    var lineWidth:CGFloat=3{didSet{setNeedsLayout()}}
    @IBInspectable
    var color:UIColor = UIColor.blueColor(){didSet{setNeedsLayout()}}
    @IBInspectable
    var 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.FaceRadiusToEyeRadiusRatio
        static let FaceRadiusToEyeOffsetRatio: CGFloat = 3
        //大圓與小圓的偏移率,此數越大,小圓的圓心距大圓越近
        static let FaceRadiusToEyeSeparationRatio: CGFloat = 1.5
        //兩個小圓之間在大圓內的分離比率
        static let FaceRadiusToEyeMounthWidthRatio: CGFloat = 1
        static let FaceRadiusToEyeMounthHeightRatio: CGFloat = 3
        static 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 = faceCenter
        eyeCenter.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.FaceRadiusToEyeMounthOffsetRatio

        let smileHeight = CGFloat(max(min(fractionOfMaxSmile, 1), -1)) * mouthHeight
        //此處max(min(fractionOfMaxSmile, 1), -1)限定了笑臉指數只能在-1到1之間,fractionOfMaxSmile這個參數可以自行設定,如果設定的大於1,則只取1,設定小於-1,則只取-1

        let 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)  //設置曲線點2

        let path = UIBezierPath()
        path.moveToPoint(start)
        path.addCurveToPoint(end, controlPoint1: cp1, controlPoint2: cp2)
        path.lineWidth = lineWidth
        return path
    }


    override func drawRect(rect: CGRect) {
        let facePath=UIBezierPath(arcCenter: faceCenter, radius: faceRadius, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true)
        facePath.lineWidth=lineWidth
        color.set()
        facePath.stroke()

        bezierPathForEye(.Left).stroke()
        bezierPathForEye(.Right).stroke()

        let smiliness = 0.8
        let 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=self
            faceView.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:
            fallthrough
        case .Changed:
            let translation=sender.translationInView(faceView)

            let happinessChange = -Int(translation.y/Constants.HappinessGestureScale)

            if happinessChange != 0{
                happiness+=happinessChange
                sender.setTranslation(CGPoint.zero, inView: faceView)
            }
        default:
            break

        }
    }


    func scale(gesture:UIPinchGestureRecognizer){
        if gesture.state == .Changed{

            scale*=gesture.scale

            gesture.scale=1
        }
    }

源代碼:Happiness

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章