ios笑脸app实现

  1. import UIKit
  2. @IBDesignable
  3. class FaceView: UIView {
  4. @IBInspectable
  5. var lineWidth:CGFloat=3{didSet{setNeedsLayout()}}
  6. @IBInspectable
  7. var color:UIColor = UIColor.blueColor(){didSet{setNeedsLayout()}}
  8. @IBInspectable
  9. var scale:CGFloat=0.9{didSet{setNeedsLayout()}}
  10. var faceCenter:CGPoint{
  11. return convertPoint(center, fromView: superview)
  12. }
  13. var faceRadius:CGFloat{
  14. return min(bounds.size.width, bounds.size.height)/2*scale
  15. }
  16. private struct Scaling {
  17. static let FaceRadiusToEyeRadiusRatio: CGFloat = 10
  18. //大圆半径(face半径)与小圆半径(eye半径)的比率,次数越小,小圆越大.因为 下面bezierPathForEye的方法中定义 eyeRadius = faceRadius / Scaling.FaceRadiusToEyeRadiusRatio
  19. static let FaceRadiusToEyeOffsetRatio: CGFloat = 3
  20. //大圆与小圆的偏移率,此数越大,小圆的圆心距大圆越近
  21. static let FaceRadiusToEyeSeparationRatio: CGFloat = 1.5
  22. //两个小圆之间在大圆内的分离比率
  23. static let FaceRadiusToEyeMounthWidthRatio: CGFloat = 1
  24. static let FaceRadiusToEyeMounthHeightRatio: CGFloat = 3
  25. static let FaceRadiusToEyeMounthOffsetRatio: CGFloat = 3
  26. }
  27. private enum Eye {
  28. case Left , Right
  29. }
  30. private func bezierPathForEye(whichEye: Eye) -> UIBezierPath {
  31. //此处定义的方法为设置一只眼睛的位置,上面定义了左右眼的枚举,可通过调用.Left.Right来实现两个位置的设定
  32. let eyeRadius = faceRadius / Scaling.FaceRadiusToEyeRadiusRatio
  33. //定义小圆半径是大圆半径的几分之几,此处因为FaceRadiusToEyeRadiusRatio: CGFloat = 10 故为十分之一
  34. let eyeVerticalOffset = faceRadius / Scaling.FaceRadiusToEyeOffsetRatio
  35. //小圆的垂直偏距
  36. let eyeHorizontalSeparation = faceRadius / Scaling.FaceRadiusToEyeSeparationRatio
  37. //小圆的水平距离
  38. var eyeCenter = faceCenter
  39. eyeCenter.y -= eyeVerticalOffset
  40. //此处相当于是用大圆圆心的y坐标减去小圆圆心的y坐标,故小圆圆心在大圆圆心之上.若为加,则在下
  41. switch whichEye {
  42. case .Left: eyeCenter.x -= eyeHorizontalSeparation / 2
  43. //相当于大圆圆心的x坐标减去(小圆圆心的x坐标除以2),即在大圆圆心的左侧
  44. case .Right: eyeCenter.x += eyeHorizontalSeparation / 2
  45. //此处加,即在右侧
  46. }
  47. let path = UIBezierPath(arcCenter: eyeCenter, radius: eyeRadius, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true) //画圆
  48. path.lineWidth = lineWidth //设定线宽
  49. return path
  50. }
  51. private func bezierPathForSmile(fractionOfMaxSmile: Double) -> UIBezierPath {
  52. let mouthWidth = faceRadius / Scaling.FaceRadiusToEyeMounthWidthRatio
  53. //大圆半径与线宽的比率,此处线宽=大圆半径
  54. let mouthHeight = faceRadius / Scaling.FaceRadiusToEyeMounthHeightRatio
  55. //mouthHeight即线的中点到圆心的距离
  56. let mouthVerticalOffset = faceRadius / Scaling.FaceRadiusToEyeMounthOffsetRatio
  57. let smileHeight = CGFloat(max(min(fractionOfMaxSmile, 1), -1)) * mouthHeight
  58. //此处max(min(fractionOfMaxSmile, 1), -1)限定了笑脸指数只能在-1到1之间,fractionOfMaxSmile这个参数可以自行设定,如果设定的大于1,则只取1,设定小于-1,则只取-1
  59. let start = CGPoint(x: faceCenter.x - mouthWidth / 2, y: faceCenter.y + mouthVerticalOffset) //设置起点
  60. let end = CGPoint(x: start.x + mouthWidth, y: start.y) //设置终点
  61. let cp1 = CGPoint(x: start.x + mouthWidth / 3 , y: start.y + smileHeight) //设置曲线点1,此处mouthWidth / 3用于调节曲线的弧度
  62. let cp2 = CGPoint(x: end.x - mouthWidth / 3, y: cp1.y) //设置曲线点2
  63. let path = UIBezierPath()
  64. path.moveToPoint(start)
  65. path.addCurveToPoint(end, controlPoint1: cp1, controlPoint2: cp2)
  66. path.lineWidth = lineWidth
  67. return path
  68. }
  69. override func drawRect(rect: CGRect) {
  70. let facePath=UIBezierPath(arcCenter: faceCenter, radius: faceRadius, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true)
  71. facePath.lineWidth=lineWidth
  72. color.set()
  73. facePath.stroke()
  74. bezierPathForEye(.Left).stroke()
  75. bezierPathForEye(.Right).stroke()
  76. let smiliness = 0.8
  77. let smilePath = bezierPathForSmile(smiliness)
  78. smilePath.stroke()
  79. }
  80. }
  • IBDesignable可以在storyboard中看到自定义的uiview
  • IBInspectable使属性可以改变

利用协议与代理联结数据源

  1. protocol FaceViewDataSource:class {
  2. func smilnessForFaceView(sender:FaceView)->Double?
  3. }

手势识别实现缩放与改变笑脸弧度

  1. @IBOutlet weak var faceView: FaceView!{
  2. didSet{
  3. faceView.dataSource=self
  4. faceView.addGestureRecognizer(UIPinchGestureRecognizer(target: faceView, action: "scale:"))
  5. //faceView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: "changeHappiness:"))
  6. }
  7. }
  8. private struct Constants{
  9. static let HappinessGestureScale:CGFloat=4
  10. }
  11. @IBAction func changeHappiness(sender: UIPanGestureRecognizer) {
  12. switch sender.state {
  13. case .Ended:
  14. fallthrough
  15. case .Changed:
  16. let translation=sender.translationInView(faceView)
  17. let happinessChange = -Int(translation.y/Constants.HappinessGestureScale)
  18. if happinessChange != 0{
  19. happiness+=happinessChange
  20. sender.setTranslation(CGPoint.zero, inView: faceView)
  21. }
  22. default:
  23. break
  24. }
  25. }
  26. func scale(gesture:UIPinchGestureRecognizer){
  27. if gesture.state == .Changed{
  28. scale*=gesture.scale
  29. gesture.scale=1
  30. }
  31. }

源代码:Happiness

IOS之笑脸app的更多相关文章

  1. iOS高仿app源码:纯代码打造高仿优质《内涵段子》

    iOS高仿app源码:纯代码打造高仿优质<内涵段子>收藏下来 字数1950 阅读4999 评论173 喜欢133 Github 地址 https://github.com/Charlesy ...

  2. 分分钟解决iOS开发中App启动广告的功能

    前不久有朋友需要一个启动广告的功能,我说网上有挺多的,他说,看的不是很理想.想让我写一个,于是乎,抽空写了一个,代码通俗易懂,简单的封装了一下,各种事件用block回调的,有俩种样式的广告,一种是全屏 ...

  3. iOS UIKit:App

    1.App生命周期 IOS架构是由许多设计模式实现,如model-view-controller 和 delegation模式. 1.1 main函数 与其它框架类似,IOS框架的入口也是从main函 ...

  4. 【HELLO WAKA】WAKA iOS客户端 之一 APP分析篇

    由于后续篇幅比较大,所以调整了内容结构. 全系列 [HELLO WAKA]WAKA iOS客户端 之一 APP分析篇 [HELLO WAKA]WAKA iOS客户端 之二 架构设计与实现篇 [HELL ...

  5. <iOS开发>之App上架流程(2017)

    本文主要介绍了App上架流程,以及上架过程中会遇到的一些问题. 一.App上架前的准备. 上架前,需要开发人员有苹果开发者账号,具体请阅读苹果开发者账号注册申请流程.本文是在已经拥有开发者账号的前提下 ...

  6. ios 推送app badge 数字累加操作

    ios 推送app badge 数字累加操作: 一:此数字需要后台配合: 二:大致原理: 后台发推送时,第一次 传badge 为1,往后,依次累加操作即可: 当用户打开app时,app向后台发送请求, ...

  7. iOS 轻松使用 App 数据统计

    想获取用户各项行为数据吗? 想轻松查看用户行为图表吗? 想高效进行 App 运营管理吗? 想,来我带你玩转 App 数据统计.这里我使用专业.轻便的 JAnalytics. 本文内容分为两部分:代码示 ...

  8. IOS研究之App转让流程须知具体介绍

     网络上有非常多开发人员提问怎么转让App并想知道具体的流程.实际上Appstore的App转让流程还是比較简单的.以下特酷吧依据自己的实际操作总结下iOS Appstore中App的转让流程.供 ...

  9. 有谁知道什么工具测试IOS手机上APP的性能软件啊?

    有谁知道什么工具测试IOS手机上APP的性能软件啊?

随机推荐

  1. java中重载与重写的区别

    (1) 方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型. 重载Overloading是一个类中多态性的一种表现. 然后我们再来谈谈 重写(Over ...

  2. CSS继承总结

    CSS的一个重要特征就是继承,它是依赖于祖先-后代的关系的.继承是一种机制,它允许样式不仅可以应用于某个特定的元素,还可以应用于它的后代. CSS可以继承的属性有: 1.文字相关:font-famil ...

  3. Linux的后台执行进程之nohup

    nohup 用途:LINUX命令用法,不挂断地运行命令.  语法:nohup Command [ Arg ... ] [ & ]  描述:nohup 命令运行由 Command 参数和任何相关 ...

  4. php使用文件缓存

    使用php读取mysql中的数据很简单,数据量不大的时候,mysql的性能还是不错的.但是有些查询可能比较耗时,这时可以把查询出的结果,缓存起来,减轻mysql的查询压力. 缓存的方法有几种:使用me ...

  5. Ubuntu固定ip和dns配置和查看

    1.查看dns: cat /etc/resolv.conf 2.Ubuntu固定ip sudo vim /etc/network/interfaces 修改如下部分: auto p3p1 iface ...

  6. Webclent基本操作

    /** * @Title: webclientTest.java * @Package webclient * @Description: TODO(用一句话描述该文件做什么) * @author A ...

  7. 3. Android程序生成步骤

      主要流程如下图所示:       所需要的工具列表 名称 功能介绍 在操作系统中的路径 aapt Android资源打包工具 ${ANDROID_SDK_HOME}/platform-tools/ ...

  8. 【GoLang】类型和作用在它上面定义的方法必须在同一个包里定义

    cannot define new methods on non-local type int 参考资料: http://wiki.jikexueyuan.com/project/the-way-to ...

  9. Linux 查找指定名称的进程并显示进程详细信息

    实际应用中可能有这样的场景:给定一个进程名称特征串,查找所有匹配该进程名称的进程的详细信息. 解决的办法是: (1) 先用pgrep [str] 命令进行模糊匹配,找到匹配该特征串的进程ID: (2) ...

  10. 《oracle每日一练》oracle截取字符的函数

    转载 在Oracle中 可以使用instr函数对某个字符串进行判断,判断其是否含有指定的字符. 在一个字符串中查找指定的字符,返回被查找到的指定的字符的位置. 语法: instr(sourceStri ...