- 两指缩放
- 上下滑动可以改变笑脸弧度
@IBDesignable 使View可以在storyBoard中实时预览
@IBInspectable 使属性可以在storyBoard中设置
HappinessViewController.swift
import UIKit public class HappinessViewController: UIViewController ,FaceViewDataSource{ var happiness:Int = 25 { //0 = vary sad,100 = ecstatic didSet{ happiness = min(max(happiness,0),100) println("happiness = \(happiness)") updateUI() } } private struct Constants{ static let HappinessGestureScale:CGFloat = 4 } // 滑动的事件 @IBAction func changeHappiness(gesture: UIPanGestureRecognizer) { switch gesture.state{ case .Ended:fallthrough case .Changed: let translation = gesture.translationInView(faceView) let happinessChange = -Int(translation.y / Constants.HappinessGestureScale) if happiness != 0 { happiness += happinessChange gesture.setTranslation(CGPointZero, inView: faceView) } default :break } } @IBOutlet weak var faceView: FaceUIView!{ didSet{ faceView.dataSource = self // 添加缩放事件,调用的是daceView里面的scale方法 faceView.addGestureRecognizer(UIPinchGestureRecognizer(target: faceView, action: "scale:")) // faceView.addGestureRecognizer(UIPanGestureRecognizer(target: faceView, action: "scale:")) } } private func updateUI(){ faceView.setNeedsDisplay() } func smilinessForFaceView(sender:FaceUIView) -> Double?{ return Double(happiness-50)/50 } }
FaceUIView.swift
import UIKit protocol FaceViewDataSource :class{ func smilinessForFaceView(sender: FaceUIView) -> Double? } @IBDesignable class FaceUIView: UIView { // @IBInspectable 使属性可以在storyBoard中设置 @IBInspectable var lineWidth:CGFloat = 3{didSet{setNeedsDisplay()}} @IBInspectable var color:UIColor = UIColor.blueColor() { didSet{setNeedsDisplay() } } @IBInspectable var scale:CGFloat = 0.90{didSet { setNeedsDisplay() } } var faceCenter:CGPoint{return convertPoint(center,fromView:superview)} // 笑脸的半径 var faceRadius:CGFloat { return min(bounds.size.width, bounds.size.height) / 2 * scale } weak var dataSource: FaceViewDataSource? // 缩放 func scale(gesture:UIPinchGestureRecognizer){ if gesture.state == .Changed{ scale *= gesture.scale gesture.scale = 1 } } 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 = dataSource?.smilinessForFaceView(self) ?? 0.0 let smilePath = bezierPathForSmile(smiliness) smilePath.stroke() } private struct Scaling { static let FaceRadiusToEyeRadiusRatio:CGFloat = 10 static let FaceRadiusToEyeOffsetRatio:CGFloat = 3 static let FaceRadiusToEyeSeparationRatio:CGFloat = 1.5 static let FaceRadiusToMouthWidthRatio:CGFloat = 1 static let FaceRadiusToMouthHeightRatio:CGFloat = 3 static let FaceRadiusToMouthOffsetRatio:CGFloat = 3 } private enum Eye {case Left,Right} // 画眼睛 private func bezierPathForEye(whichEye:Eye) -> UIBezierPath{ let eyeRadius = faceRadius / Scaling.FaceRadiusToEyeRadiusRatio let eyeVerticaloffset = faceRadius / Scaling.FaceRadiusToEyeOffsetRatio let eyeHorizontalSeparation = faceRadius / Scaling.FaceRadiusToEyeSeparationRatio var eyeCenter = faceCenter eyeCenter.y -= eyeVerticaloffset switch whichEye { case .Left: eyeCenter.x -= eyeHorizontalSeparation / 2 case .Right: eyeCenter.x += eyeHorizontalSeparation / 2 default :break } 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.FaceRadiusToMouthWidthRatio let mouthHeight = faceRadius / Scaling.FaceRadiusToMouthHeightRatio let mouthVerticalOffset = faceRadius / Scaling.FaceRadiusToMouthOffsetRatio let smileheight = CGFloat(max(min(fractionOfmaxSmile,1), -1)) * mouthHeight 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) let cp2 = CGPoint(x:end.x - mouthWidth/3, y: cp1.y) let path = UIBezierPath() path.moveToPoint(start) path.addCurveToPoint(end, controlPoint1: cp1, controlPoint2: cp2) path.lineWidth = lineWidth return path } }
时间: 2024-11-06 07:09:48