最近一个朋友在做图片处理的 App,想要实现类似 MOLDIV App 拼图的UI效果(如何创建不规则的 view),就问我有什么想法。我首先想到的就是 UIBezierPath+CAShapeLayer的方式,为了验证自己的想法,写了一个小 demo

效果图:

demo.gif

实现思路

正常情况下我们创建的 view 都是矩形的。但是我们知道 view 的内容显示靠的是 layer 层,所以可以通过修改 layer 层来实现。代码如下:

func drawMaskLayer() {guard (points != nil) else {return}let bezierPath1 = UIBezierPath()bezierPath1.move(to: points![0])for index in 1..<points!.count {bezierPath1.addLine(to: points![index])}bezierPath1.addLine(to: points![0])let shapeLayer = CAShapeLayer()shapeLayer.path = bezierPath1.cgPathself.layer.mask = shapeLayer}

通过这种方式我们可以创建出任何的多边形的 view。通过这种方式我们可以很容易的创建出上图所示的 UI 布局。但是我们这个时候会发现,当有触摸点在 view 透明的地方时,触摸事件并不能传递给被它遮挡的 view 上,所以需要重写 func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? 方法来判断何时响应。代码如下:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {if points != nil {if (super.hitTest(point, with: event) == scrollV) {print(self,point)print(points!)let isInner = isInnerView(with: point)if isInner {return self.scrollV}else {return nil}}}else {return super.hitTest(point, with: event)}return nil}

那么何时响应,何时不响应呢?应该是如果触摸点在我们绘制的 view 范围内响应,之外的不相应。那么这个时候就需要判断一个点在是否在多边形内,本 demo 使用 射线法。

fileprivate func isInnerView(with point: CGPoint) -> Bool {let pX = point.x , pY = point.yvar flag = falsevar oldIndex = points!.count - 1for newIndex in 0..<points!.count {let newX = points![newIndex].xlet newY = points![newIndex].ylet oldX = points![oldIndex].xlet oldY = points![oldIndex].y// 点与多边形顶点重合if (pX == newX && pY == newY) || (pX == oldX && pY == oldY) {return false}// 判断线段两端点是否在射线两侧if (oldY > pY && newY < pY) || (oldY < pY && newY > pY) {// 线段上与射线 Y 坐标相同的点的 X 坐标let x = newX + (pY - newY) * (oldX - newX) / (oldY - newY)// 点在多边形的边上if(x == pX) {return false}// 射线穿过多边形的边界if(x > pX) {flag = !flag}}oldIndex = newIndex}// 射线穿过多边形边界的次数为奇数时点在多边形内return flag ? true : false}

到了这里 demo 也就基本完成了。希望对需要的人有帮助,有什么不对的欢迎指正。

源代码:
ZCFJointView
环境:
Xcode 8.2 、Swift 3.0
参考资料:
射线法

UIBezierPath和CAShapeLayer创建不规则View(Swift 3.0)相关推荐

  1. UIBezierPath和CAShapeLayer画直线、CGContextRef画直线两种方案

    在view的相关方法中可直接使用UIBezierPath和CAShapeLayer画图形- (void)makeBezierPath {/**CAShapeLayer属于QuartzCore框架,继承 ...

  2. 放肆地使用UIBezierPath和CAShapeLayer画各种图形

    CAShapeLayer 是 CALayer 的子类,但是比 CALayer 更灵活,可以画出各种图形,当然,你也可以使用其他方式来画,随你. 杂谈 在 CAShapeLayer 中,也可以像 CAL ...

  3. 放肆的使用UIBezierPath和CAShapeLayer画各种图形

    CAShapeLayer 是 CALayer 的子类,但是比 CALayer 更灵活,可以画出各种图形,当然,你也可以使用其他方式来画,随你. 杂谈 在 CAShapeLayer 中,也可以像 CAL ...

  4. 放肆的使用UIBezierPath和CAShapeLayer画各种图形(含仿微信视频眼镜Demo)

    Collection/Bookmark/Share for width under 768px CAShapeLayer 是 CALayer 的子类,但是比 CALayer 更灵活,可以画出各种图形, ...

  5. 使用CSS 3创建不规则图形

    2019独角兽企业重金招聘Python工程师标准>>> 前言 CSS 创建复杂图形的技术即将会被广泛支持,并且应用到实际项目中.本篇文章的目的是为大家开启它的冰山一角.我希望这篇文章 ...

  6. 一起谈.NET技术,C#创建不规则窗体的几种方式

    现在,C#创建不规则窗体不是一件难事,下面总结一下:       一.自定义窗体,一般为规则的图形,如圆.椭圆等. 做法:重写Form1_Paint事件(Form1是窗体的名字),最简单的一种情况如下 ...

  7. Swift基础:创建第一个Swift工程:Swift的基本语法

    苹果公司在今年的WWDC大会上,除了发布了iOS8和Max OS X 10.10之外,还发布了一个新的编程语言Swift.不得不说,Swift有较大的转变,也使编程变得更加容易了,下面介绍了Swift ...

  8. Android官方开发文档Training系列课程中文版:创建自定义View之View的创建

    原文地址:http://android.xsoftlab.net/training/custom-views/index.html 引言 Android框架含有大量的View类,这些类用来显示各式各样 ...

  9. android 动态创建view,react-native动态创建Android View 无效果

    问题描述 react-native动态创建Android View 无效果,我想在react-native里面直接点击函数进行创建,也就是通过module中的方法创建View 问题出现的环境背景及自己 ...

最新文章

  1. 在Unity3d中调用外部程序及批处理文件
  2. IKE IPSEC ×××
  3. .net core项目部署到centos7
  4. motan yar php,motan学习笔记 六 opentracing Brave+zipkin实现-Go语言中文社区
  5. acwing2058. 笨拙的手指(进制转换)
  6. [渝粤题库]西北工业大学统计学
  7. 计算机组成原理AB什么运算,计算机组成原理运算器实验.doc
  8. Pentium 4处理器架构/微架构/流水线 (3) - NetBurst微架构
  9. SQL Server 数据库维护脚本合集[007]-删除数据库所有用户表数据
  10. c++ java setobjectarrayelement_java中jni的使用:C/C++操作java中的数组
  11. 【网络安全工程师面试合集】— 渗透资源 操作系统大合集
  12. C#可逆加密-Rijndael算法
  13. plsql查询不显示结果_管理NVivo的查询结果
  14. 快速突破面试算法(内含从简到难的高频题型目录及每题的详解,已经归类整理好并外带博主的免费答疑)
  15. UI中经常出现的下拉框下拉自动筛选效果的实现
  16. mysql linux 安装包下载_mysql官网下载linux版本安装包
  17. 关于达芬奇调色台的那些事儿
  18. 嘉应大学黄林鑫计算机学院,林鑫-中国科学院大学-UCAS
  19. 安卓隐藏摄像_隐藏拍摄app
  20. Vue关于pdf展示问题——第三方电子签章不能正常展示

热门文章

  1. hihoCoder#1384 : Genius ACM
  2. 【转】UIColor对颜色的自定义
  3. 2016.04.09 使用Powerdesigner进行创建数据库的概念模型并转为物理模型
  4. Python学习笔记二:布尔表达式
  5. Mantis 缺陷管理系统配置与安装
  6. 软件测试工程师职业介绍和规划
  7. PHP代码保护——Zend Guard
  8. php扩展xdebug安装以及用kcachegrind系统分析
  9. 【Linux】linux使用mplayer播放摄像头
  10. 【Qt】Qt样式表总结(三):QObject 属性