Swift–UIBezierPath和CAShapeLayer画线
UIBezierPath和CAShapeLayer画线
(注意:该文章仅对Swift语言的画图部分的学习做简单总结,熟习两种语言的小伙伴,可以随便)
<一>UIBezierPath(UIBezierPath官方详情)UIBezierPath继承自NSObject对象。我们可以使用这个类来指定路径的几何形状。路径可以定义简单的形状,如矩形、椭圆和弧,也可以定义包含直线和曲线段混合的复杂多边形。定义形状之后,可以使用该类的其余方法在当前绘图上下文中呈现路径。
UIBezierPath中的方法
<1>创立UIBezierPath对象
(1)创立一个矩形路径的UIBezierPath对象
public convenience init(rect: CGRect)
(2)创立一个矩形路径的UIBezierPath对象,并且四个角为圆角,cornerRadius是圆角半径
public convenience init(roundedRect rect: CGRect, cornerRadius: CGFloat)
(3)创立一个矩形路径的UIBezierPath对象, byRoundingCorners可以设置某些角为圆角,cornerRadius是圆角半径
public convenience init(roundedRect rect: CGRect, byRoundingCorners corners: UIRectCorner, cornerRadii: CGSize)//UIRectCornerd的枚举public struct UIRectCorner : OptionSet { public init(rawValue: UInt) public static var topLeft: UIRectCorner { get } public static var topRight: UIRectCorner { get } public static var bottomLeft: UIRectCorner { get } public static var bottomRight: UIRectCorner { get } public static var allCorners: UIRectCorner { get }}
(4)创立一个圆形路径的UIBezierPath对象,也可以用此方法画画圆弧,arcCenter:圆心,radius:半径,startAngle:圆形路径的起点,endAngle:圆形路径的终点,clockwise:方向能否是顺时针方向
public convenience init(arcCenter center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool)
(5)创立并返回一个新的UIBezierPath对象,该对象由核心图形路径的内容初始化。
public convenience init(cgPath CGPath: CGPath)
(6)创立一个UIBezierPath对象
public init()
(7)创立并返回一个新的UIBezierPath对象,该对象的路径是当前对象的路径的反向。
open func reversing() -> UIBezierPath
<2>构建UIBezierPath路径
(1) UIBezierPath路径的起点
open func move(to point: CGPoint)
(2)UIBezierPath路径沿途经过的点
open func addLine(to point: CGPoint)
(3) UIBezierPath画圆形或者弧线,arcCenter:圆心,radius:半径,startAngle:圆形路径的起点,endAngle:圆形路径的终点,clockwise:方向能否是顺时针方向
open func addArc(withCenter center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool)
(4) UIBezierPath画二次贝塞尔曲线,endPoint:贝塞尔曲线终点,controlPoint:贝塞尔曲线控制点
open func addQuadCurve(to endPoint: CGPoint, controlPoint: CGPoint)
(5)UIBezierPath画二次贝塞尔曲线,endPoint:贝塞尔曲线终点,controlPoint1:第一个贝塞尔曲线控制点, controlPoint2:第二个贝塞尔曲线控制点
open func addCurve(to endPoint: CGPoint, controlPoint1: CGPoint, controlPoint2: CGPoint)
(6)关闭最近增加的子路径。
open func close()
(7)删除所有子路径。
open func removeAllPoints()
(8)将指定路径对象的内容追加到接收方的路径。
open func append(_ bezierPath: UIBezierPath)
(9)展现核心图形的路径。
open var cgPath: CGPath
(10)图形路径中的当前点
open var currentPoint: CGPoint { get }
<3>UIBezierPath的其余属性
**** UIBezierPath的线宽open var lineWidth: CGFloat ()
****描边时路径端点的形状。/* Line cap styles. */描边时路径端点的形状的枚举public enum CGLineCap : Int32 { case butt//表示path延伸到终点时 将不在延伸 case round//表示path延伸到终点时 画一个圆形 半径为UIBezierPath的线宽的一半 case square//表示path延伸到终点时 画一个正方形 边长为UIBezierPath的线宽}open var lineCapStyle: CGLineCap
****The shape of the joints between connected segments of a stroked path.(曲线路径连接部分之间的形状)/* Line join styles. */public enum CGLineJoin : Int32 { case miter//路径连接部分 尖状 case round//路径连接部分 圆形 case bevel//路径连接部分 平型 没有尖状}open var lineJoinStyle: CGLineJoin
****The limiting value that helps avoid spikes at junctions between connected line segments.open var miterLimit: CGFloat
****曲线路径段绘制精度open var flatness: CGFloat
****指示绘制路径时能否使用奇偶绕线规则。open var usesEvenOddFillRule: Bool
****设置路径的行描模式。open func setLineDash(_ pattern: UnsafePointer<CGFloat>?, count: Int, phase: CGFloat)open func getLineDash(_ pattern: UnsafeMutablePointer<CGFloat>?, count: UnsafeMutablePointer<Int>?, phase: UnsafeMutablePointer<CGFloat>?)
<4>UIBezierPath画出路径
(1)使用当前绘图属性绘制路径所包围的区域。
open func fill()
(2)使用当前绘制属性沿接收方路径绘制一条线。
open func stroke()
(3)使用指定的混合模式和透明度值绘制接收方路径包围的区域。
open func fill(with blendMode: CGBlendMode, alpha: CGFloat)
(4)使用指定的混合模式和透明度值沿接收方路径绘制一条线。
open func stroke(with blendMode: CGBlendMode, alpha: CGFloat)
(5)将接收方路径包围的区域与当前图形上下文的裁剪路径相交,使结果形状成为当前的裁剪路径。
open func addClip()
(6)用于判断当前path组成的范围内,能否包含某个点(CGPoint)
open func contains(_ point: CGPoint) -> Bool
(7)The bounding rectangle of the path.
open var bounds: CGRect { get }
(8)使用指定的仿射变换矩阵对路径中的所有点进行变换。
open func apply(_ transform: CGAffineTransform)
<二> CAShapeLayer(CAShapeLayer官方详情)CAShapeLayer是继承自CALayer类,属于QuartzCore框架。一般画图都需要UIBezierPath和CAShapeLayer结合来实现,UIBezierPath的作用主要是绘制路径,CAShapeLayer主要是对UIBezierPath的路径进行渲染,显示路径,并将CAShapeLayer对象增加到subLayer中,当然CAShapeLayer也可以完成动画等一系列操作,笔者总结一下画图过程中CAShapeLayer类中主要用到的方法。
CAShapeLayer中的方法
(1) CAShapeLayer的初始化
public init()
(2)定义要绘制的路径。
open var path: CGPath?
(3)路径的起点和终点连接的直线和路径上的其余线构成一块区域,fillColor是这块区域的填充色
open var fillColor: CGColor?
(4)填充路径时使用的填充规则。可选non-zero和even-odd两种,默认non-zero
open var fillRule: String
(5)路径的颜色
open var strokeColor: CGColor?
(6)线宽
open var lineWidth: CGFloat
(7)绘制路径时使用的斜接极限。可以做成动画。
/* The miter limit used when stroking the path. Defaults to ten. * Animatable. */ open var miterLimit: CGFloat
(8)绘制路径终点的相对位置。可以做成动画。 区间为0到1
open var strokeEnd: CGFloat
上面是详情了绘图的UIBezierPath和CAShapeLayer的基本属性和方法,我们只要要创立出一个UIBezierPath对象和CAShapeLayer对象,而后将UIBezierPath对象的cgPath属性赋值给CAShapeLayer对象的path属性,layer层增加CAShapeLayer对象就可绘制各种图形。即:
layer.path = path.cgPathself.view.layer.addSublayer(layer)
<一>画直线
效果图:
屏幕快照 2018-12-17 上午9.56.09.png
实现
// 线的路径 let linePath = UIBezierPath.init() //MARK: 动画 // 起点 linePath.move(to: CGPoint.init(x: 20, y: 300)) // 其余点 linePath.addLine(to: CGPoint.init(x: 200, y: 200)) //可以增加n多个点 可为折线,直线等// linePath.addLine(to: CGPoint.init(x: 90, y: 70)) let lineLayer = CAShapeLayer.init() lineLayer.lineWidth = 1 lineLayer.strokeColor = UIColor.green.cgColor lineLayer.path = linePath.cgPath lineLayer.fillColor = UIColor.clear.cgColor //动画1 let animation = CABasicAnimation(keyPath: "strokeEnd") animation.fromValue = 0 animation.toValue = 1 animation.duration = 2 lineLayer.add(animation, forKey: "") self.view.layer.addSublayer(lineLayer)
<二>画阴影图
自己的实现思路:路径的起点和终点连接的直线和路径上的其余线构成一块区域。利用CAShapeLayer的填充色完成
效果图:
屏幕快照 2018-12-17 上午10.04.03.png
实现
// 线的路径 let linePath = UIBezierPath.init() //MARK: 动画 // 起点 linePath.move(to: CGPoint.init(x: 20, y: 400)) // 其余点 linePath.addLine(to: CGPoint.init(x: 20, y: 300)) linePath.addLine(to: CGPoint.init(x: 30, y: 200)) linePath.addLine(to: CGPoint.init(x: 50, y: 267)) linePath.addLine(to: CGPoint.init(x: 100, y: 267)) linePath.addLine(to: CGPoint.init(x: 150, y: 200)) linePath.addLine(to: CGPoint.init(x: 200, y: 188)) linePath.addLine(to: CGPoint.init(x: 200, y: 400)) let lineLayer = CAShapeLayer.init() lineLayer.lineWidth = 1 lineLayer.strokeColor = UIColor.green.cgColor lineLayer.path = linePath.cgPath lineLayer.fillColor = UIColor.orange.withAlphaComponent(0.3).cgColor//闭合区域的填充色 //动画1 let animation = CABasicAnimation(keyPath: "strokeEnd") animation.fromValue = 0 animation.toValue = 1 animation.duration = 2 lineLayer.add(animation, forKey: "") self.view.layer.addSublayer(lineLayer)
<三>画多边形
自己的实现思路:绘制完成路径后,使用path.close()//图层封闭方法。
效果图:
屏幕快照 2018-12-17 上午10.07.46.png
实现
let path = UIBezierPath.init() ////layer起点 path.move(to: CGPoint.init(x: 30, y: NavigationBarHeight+50)) ////layer整条路径上经过的其余点 用此方法也可以画多边形 path.addLine(to: CGPoint.init(x: 30, y: NavigationBarHeight+100)) path.addLine(to: CGPoint.init(x: 200, y: NavigationBarHeight+100))// path.addLine(to: CGPoint.init(x: 200, y: NavigationBarHeight+50)) path.close()//图层封闭 let layer = CAShapeLayer.init() layer.path = path.cgPath layer.lineWidth = 1 layer.strokeColor = UIColor.orange.cgColor layer.fillColor = UIColor.clear.cgColor//填充色 self.view.layer.addSublayer(layer)
<四>画圆形或者椭圆
自己的实现思路:画圆形或者椭圆,可以使用绘制一个view,为其增加蒙版效果实现,若视图为长方形 ,则绘制椭圆 ,正方形,则为圆形。另外还可以使用UIBezierPath类中的open func addArc(withCenter center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool)画圆。
效果图:
屏幕快照 2018-12-17 上午10.20.13.png
实现
class PaintCilcleViewVC: BaseViewController { override func viewDidLoad() { super.viewDidLoad() ////画圆形或者椭圆 drawCircleView() //画圆形或者椭圆 2 drawCircleViewSecond() } /** 画圆形或者椭圆 1 */ func drawCircleView() { // 需要圆视图 若视图为长方形 则绘制椭圆 正方形,则为圆形 let circleView = UIView.init(frame: CGRect.init(x: (kScreenWidth-200)/2, y: NavigationBarHeight*2, width: 200, height: 100)) circleView.backgroundColor = UIColor.orange self.view.addSubview(circleView) // 线的路径 let path = UIBezierPath.init(ovalIn:circleView.bounds) let pathLayer = CAShapeLayer.init() pathLayer.lineWidth = 1 pathLayer.strokeColor = UIColor.green.cgColor pathLayer.path = path.cgPath pathLayer.fillColor = nil circleView.layer.addSublayer(pathLayer) circleView.layer.mask = pathLayer // layer 的 mask属性,增加蒙版 } /** 画圆形 */ func drawCircleViewSecond() { let path = UIBezierPath.init() path.addArc(withCenter: CGPoint.init(x: kScreenWidth/2, y: 500), radius: 30, startAngle: 0, endAngle: 2*CGFloat(Double.pi), clockwise: true) let layer = CAShapeLayer.init() layer.lineWidth = 1 layer.strokeColor = UIColor.green.cgColor layer.path = path.cgPath layer.fillColor = nil self.view.layer.addSublayer(layer) }}
<五>画圆角矩形
自己的实现思路:首先需要我们创立一个需要绘制圆角的View,绘制四个圆角,可以使用public convenience init(roundedRect rect: CGRect, cornerRadius: CGFloat)该方法,假如想要实现某个角为圆角或者者多个角为圆角,可以使用public convenience init(roundedRect rect: CGRect, byRoundingCorners corners: UIRectCorner, cornerRadii: CGSize)方法。
效果图:
屏幕快照 2018-12-17 上午10.25.26.png
实现
class PaintRoundedRectangleVC: BaseViewController { override func viewDidLoad() { super.viewDidLoad() //四角切圆角 drawQuadRangle() //单角切圆角 drawUnicornous() } /** 四角切圆角 */ func drawQuadRangle() { // 需要画圆角矩形 let view = UIView.init(frame: CGRect.init(x: (kScreenWidth-200)/2, y: NavigationBarHeight, width: 100, height: 100)) view.backgroundColor = UIColor.orange self.view.addSubview(view) //线的路径 let path = UIBezierPath.init(roundedRect: view.bounds, cornerRadius: 20) let layer = CAShapeLayer.init() layer.lineWidth = 1 layer.strokeColor = UIColor.green.cgColor layer.path = path.cgPath view.layer.mask = layer } /** 单角切圆角 (多个角进行圆角切) */ func drawUnicornous() { // 需要画圆角矩形 let view = UIView.init(frame: CGRect.init(x: (kScreenWidth-200)/2, y: NavigationBarHeight+150, width: 100, height: 100)) view.backgroundColor = UIColor.orange self.view.addSubview(view) //线的路径 //此方法可以用来对多个角进行圆角切// let path = UIBezierPath.init(roundedRect: view.bounds, byRoundingCorners: UIRectCorner(rawValue: UIRectCorner.RawValue(UInt8(UIRectCorner.topLeft.rawValue) | UInt8(UIRectCorner.bottomRight.rawValue))) , cornerRadii: CGSize.init(width: 20, height: 0)) //此方法可以用来对单个角进行圆角切 let path = UIBezierPath.init(roundedRect: view.bounds, byRoundingCorners: UIRectCorner.topLeft, cornerRadii: CGSize.init(width: 20, height: 0)) let layer = CAShapeLayer.init() layer.lineWidth = 1 layer.strokeColor = UIColor.green.cgColor layer.path = path.cgPath view.layer.mask = layer }}
<六>画弧线
自己的实现思路:画圆是从0绘制到2pi的位置,画弧线就是角度可以自己随便绘制。
效果图:
屏幕快照 2018-12-17 上午10.32.39.png
实现
class PaintTrajectoryViewVC: BaseViewController { override func viewDidLoad() { super.viewDidLoad() //在矩形中画一条圆弧 paintTrajectory() //折线和弧线构成的曲线 lineAndTrajectoryView() } /** 在矩形中画一条圆弧 */ func paintTrajectory() { let view = UIView.init(frame: CGRect.init(x: (kScreenWidth-200)/2, y: NavigationBarHeight, width: 100, height: 100)) view.backgroundColor = UIColor.orange self.view.addSubview(view) //线的路径 let viewCenter = CGPoint.init(x: view.frame.width/2, y: view.frame.height/2)// 画弧的中心点,相对于view let path = UIBezierPath.init(arcCenter: viewCenter, radius: 33, startAngle: CGFloat(0), endAngle: CGFloat(1.6*Double.pi), clockwise: true) let layer = CAShapeLayer.init() layer.lineWidth = 1 layer.strokeColor = UIColor.green.cgColor layer.fillColor = nil layer.path = path.cgPath view.layer.addSublayer(layer) } /** 折线和弧线构成的曲线 */ func lineAndTrajectoryView() { let view = UIView.init(frame: CGRect.init(x: (kScreenWidth-200)/2, y: NavigationBarHeight+200, width: 150, height: 150)) view.backgroundColor = UIColor.orange self.view.addSubview(view) //线的路径 let viewCenter = CGPoint.init(x: view.frame.width/2, y: view.frame.height/2)// 画弧的中心点,相对于view let path = UIBezierPath.init() path.move(to: CGPoint.init(x: 0, y: 0)) path.addLine(to: viewCenter) // 增加一条弧线 path.addArc(withCenter: viewCenter, radius: 50, startAngle: 0, endAngle: CGFloat(Double.pi), clockwise: true) let layer = CAShapeLayer.init() layer.lineWidth = 1 layer.strokeColor = UIColor.green.cgColor layer.fillColor = nil layer.path = path.cgPath view.layer.addSublayer(layer) }}
<七>绘制饼状图
自己的实现思路:绘制饼状图其实就是绘制n个圆弧,可以将其CAShapeLayer的fillColor设置为透明色,strokeColor是圆弧的颜色,可以设置为自己想要的颜色,通过设置lineWidth路径的宽度来调整圆弧的大小。饼状图也可是实现点击效果,重写func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)方法来实现。
效果图:
屏幕快照 2018-12-17 上午10.39.02.png
实现
/*饼状图*/class RYQPieChartView: UIView { //设置圆点 var centerPoint:CGPoint! var radius:CGFloat! var layerWidth = 40*m6Scale//圆环宽度 var startAngle:Float = 0 var endAngle:Float = 0 var allValue:Float = 0 var dataSource = [456, 567, 559] var colors = [UIColor.green, UIColor.orange, UIColor.gray] var outBezerArrs = [Any]() var outLayers = [Any]() override init(frame: CGRect) { super.init(frame: frame) radius = frame.size.height*0.4-layerWidth centerPoint = CGPoint.init(x: frame.size.width/2, y: frame.size.height/2) //画图 drawPieChartView() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }}/** 画图 */extension RYQPieChartView { func drawPieChartView() { for index in 0...dataSource.count-1 { let value = dataSource[index] allValue = allValue+Float(value) } //for循环画图 for index in 0...dataSource.count-1 { bezierPaint(index: index) } } //贝塞尔和CASherLayer画图 func bezierPaint(index:Int) { let targetValue = dataSource[index] let ratioString = String(format: "%.5f", Float(targetValue)/Float(allValue)) endAngle = startAngle + (Float(ratioString)!-0.005)*2*Float(Double.pi) //bezierPath形成闭合的扇形路径 外弧形 let bezierOutPath = UIBezierPath.init() // 增加一条弧线 bezierOutPath.addArc(withCenter: centerPoint, radius: radius, startAngle: CGFloat(startAngle), endAngle: CGFloat(endAngle), clockwise: true) //////外弧形渲染 let outLayer = CAShapeLayer.init() outLayer.lineWidth = layerWidth outLayer.fillColor = clear.cgColor outLayer.strokeColor = colors[index].cgColor outLayer.path = bezierOutPath.cgPath self.layer.addSublayer(outLayer) let start = dataSource[index] let scaleString = String(format: "%.5f", Float(start)/Float(allValue)) startAngle = startAngle+(Float(scaleString)!-1)*2*Float(Double.pi) //动画1 let animation = CABasicAnimation(keyPath: "strokeEnd") animation.fromValue = 0 animation.toValue = 1 animation.duration = 1 outLayer.add(animation, forKey: "") outBezerArrs.append(bezierOutPath) outLayers.append(outLayer) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let touch:UITouch = ((touches as NSSet).anyObject()! )as!UITouch let point = touch.location(in: self) var start:Float = 0 var end:Float = 0 for index in 0...outBezerArrs.count-1 { let targetValue = dataSource[index] let ratioString = String(format: "%.5f", Float(targetValue)/Float(allValue)) end = start + (Float(ratioString)!-0.005)*2*Float(Double.pi) let bezierOutPath = outBezerArrs[index] as! UIBezierPath let outLayer = outLayers[index] as! CAShapeLayer layerWidth = 40*m6Scale if bezierOutPath.contains(point) { layerWidth = 60*m6Scale } //移除path上的所有点 重新绘制 bezierOutPath.removeAllPoints() // 增加一条弧线 bezierOutPath.addArc(withCenter: centerPoint, radius: radius, startAngle: CGFloat(start), endAngle: CGFloat(end), clockwise: true) //外弧形渲染 outLayer.path = bezierOutPath.cgPath outLayer.lineWidth = layerWidth let newstart = dataSource[index] let scaleString = String(format: "%.5f", Float(newstart)/Float(allValue)) start = start+(Float(scaleString)!-1)*2*Float(Double.pi) } }}
<八>不规则渐变色图形
自己的实现思路:使用CGContextRef属性,获取上下文生成图片,再次绘制UIBezierPath,将生成的图片填充到CAShapeLayer的填充色中。
效果图:
屏幕快照 2018-12-17 上午10.44.19.png
实现
class IrregularGradientVC: BaseViewController { override func viewDidLoad() { super.viewDidLoad() //绘制UIBezierPath路径 let path = UIBezierPath.init() path.move(to: CGPoint.init(x: 0, y: NavigationBarHeight)) path.addLine(to: CGPoint.init(x: 0, y: 150+NavigationBarHeight)) path.addCurve(to: CGPoint.init(x: kScreenWidth, y: 150+NavigationBarHeight), controlPoint1: CGPoint.init(x: kScreenWidth*0.3, y: 200+NavigationBarHeight), controlPoint2: CGPoint.init(x: kScreenWidth*0.8, y: 350+NavigationBarHeight)) path.addLine(to: CGPoint.init(x: kScreenWidth, y: NavigationBarHeight)) //绘制渐变 图片 let img = drawLinearGradient(startColor: UIColor.green.cgColor, endColor: UIColor.red.cgColor) let layer = CAShapeLayer.init() //本质上生成一张渐变色图片 作为layer的填充背景 layer.fillColor = UIColor.init(patternImage: img).cgColor layer.path = path.cgPath self.view.layer.addSublayer(layer) } /** 绘制渐变 */ func drawLinearGradient(startColor:CGColor, endColor:CGColor) -> UIImage { //创立CGContextRef UIGraphicsBeginImageContext(self.view.bounds.size) let context = UIGraphicsGetCurrentContext() let path = UIBezierPath.init() path.move(to: CGPoint.init(x: 0, y: NavigationBarHeight)) path.addLine(to: CGPoint.init(x: 0, y: kScreenHeight)) path.addLine(to: CGPoint.init(x: kScreenWidth, y: kScreenHeight)) path.addLine(to: CGPoint.init(x: kScreenWidth, y: 0)) let colorSpace = CGColorSpaceCreateDeviceRGB() let locations = [CGFloat(0.0), CGFloat(1.0)] let colors = [startColor, endColor] let gradient = CGGradient.init(colorsSpace: colorSpace, colors: colors as CFArray, locations: locations) let pathRect: CGRect = path.cgPath.boundingBox //具体方向可根据需求修改 let startPoint = CGPoint.init(x: pathRect.minX, y: pathRect.midY) let endPoint = CGPoint.init(x: pathRect.maxX, y: pathRect.midY) context?.saveGState() context?.addPath(path.cgPath) context?.clip() context?.drawLinearGradient(gradient!, start: startPoint, end: endPoint, options: CGGradientDrawingOptions(rawValue: 0)) context?.restoreGState() //获取绘制的图片 let img = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return img! }}
<九>二次贝塞尔曲线
效果图:
屏幕快照 2018-12-17 上午10.59.31.png
实现
class QuadRaticBezierVC: BaseViewController { override func viewDidLoad() { super.viewDidLoad() quadRaticBezierView() sameEndPointQuadRaticBezierView() } /** 总结:起点和终点的距离越小,趋向控制点结束越早,趋向终点开始越早,曲线弧度越大。 起点终点相同,控制点不同 */ func quadRaticBezierView() { let view = UIView.init(frame: CGRect.init(x: (kScreenWidth-200)/2, y: NavigationBarHeight, width: 200, height: 200)) view.backgroundColor = UIColor.orange self.view.addSubview(view) // 绿色二次贝塞尔曲线 let greenPath = UIBezierPath.init() greenPath.move(to: CGPoint.init(x: 0, y: 100)) let end1Point = CGPoint.init(x: 200, y: 50) //二次贝塞尔曲线 greenPath.addQuadCurve(to: end1Point, controlPoint: CGPoint.init(x: 100, y: 200)) let layer1 = CAShapeLayer.init() layer1.lineWidth = 1 layer1.strokeColor = UIColor.green.cgColor layer1.fillColor = nil layer1.path = greenPath.cgPath view.layer.addSublayer(layer1) // 红色二次贝塞尔曲线 let redPath = UIBezierPath.init() redPath.move(to: CGPoint.init(x: 0, y: 100)) let end2Point = CGPoint.init(x: 100, y: 50) // 二次贝塞尔曲线 redPath.addQuadCurve(to: end2Point, controlPoint: CGPoint.init(x: 100, y: 200)) let layer2 = CAShapeLayer.init() layer2.lineWidth = 1 layer2.strokeColor = UIColor.red.cgColor layer2.fillColor = nil layer2.path = redPath.cgPath view.layer.addSublayer(layer2) } /** 总结:控制点与起点和终点所在直线偏移距离越大,曲线弧度越大。 */ func sameEndPointQuadRaticBezierView() { let view = UIView.init(frame: CGRect.init(x: (kScreenWidth-200)/2, y: NavigationBarHeight+300, width: 200, height: 200)) view.backgroundColor = UIColor.orange self.view.addSubview(view) let startPoint = CGPoint.init(x: 0, y: 100) let endPoint = CGPoint.init(x: 200, y: 50) // 绿色二次贝塞尔曲线 let greenPath = UIBezierPath.init() greenPath.move(to: startPoint) //二次贝塞尔曲线 greenPath.addQuadCurve(to: endPoint, controlPoint: CGPoint.init(x: 100, y: 200)) let layer1 = CAShapeLayer.init() layer1.lineWidth = 1 layer1.strokeColor = UIColor.green.cgColor layer1.fillColor = nil layer1.path = greenPath.cgPath view.layer.addSublayer(layer1) // 红色二次贝塞尔曲线 let redPath = UIBezierPath.init() redPath.move(to: CGPoint.init(x: 0, y: 100)) // 二次贝塞尔曲线 redPath.addQuadCurve(to: endPoint, controlPoint: CGPoint.init(x: 100, y: 150)) let layer2 = CAShapeLayer.init() layer2.lineWidth = 1 layer2.strokeColor = UIColor.red.cgColor layer2.fillColor = nil layer2.path = redPath.cgPath view.layer.addSublayer(layer2) }}
<十>三次贝塞尔曲线
效果图:
屏幕快照 2018-12-17 上午11.03.08.png
实现
/** 三次贝塞尔曲线 比较于二次贝塞尔曲线 多了一个控制点 - (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2 三次贝赛尔曲线,起点用 moveToPoint方法给出;endPoint:贝赛尔曲线终点;controlPoint1:控制点1;controlPoint2:控制点2; 曲线是由起点趋向控制点1,之后趋向控制点2,最后到达终点(不会经过控制点)的曲线。在起点和终点所在直线方向上,曲线在起点和控制点1之间,趋向控制点1;在控制点2和终点之间,趋向控制点2.控制点与起点和终点所在直线的偏移影响曲线的偏移程度 */class TripleBezierVC: BaseViewController { override func viewDidLoad() { super.viewDidLoad() let view = UIView.init(frame: CGRect.init(x: (kScreenWidth-200)/2, y: NavigationBarHeight, width: 200, height: 200)) view.backgroundColor = UIColor.orange self.view.addSubview(view) let startPoint = CGPoint.init(x: 0, y: 100) let endPoint = CGPoint.init(x: 200, y: 50) // 绿色三次贝塞尔曲线 let path = UIBezierPath.init() path.move(to: startPoint) //三次贝塞尔曲线 path.addCurve(to: endPoint, controlPoint1: CGPoint.init(x: 10, y: 0), controlPoint2: CGPoint.init(x: 70, y: 180)) //在加 可画出n次贝塞尔曲线// path.addCurve(to: startPoint, controlPoint1: CGPoint.init(x: 40, y: 40), controlPoint2: CGPoint.init(x: 90, y: 120)) let layer = CAShapeLayer.init() layer.lineWidth = 1 layer.strokeColor = UIColor.green.cgColor layer.fillColor = nil layer.path = path.cgPath //动画1 let animation = CABasicAnimation(keyPath: "strokeEnd") animation.fromValue = 0 animation.toValue = 1 animation.duration = 2 layer.add(animation, forKey: "") view.layer.addSublayer(layer) }}
想下载Demo的小伙伴,Demo下载,觉得有用的点个星吧。有什么错误和不足的地方也欢迎指正。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Swift–UIBezierPath和CAShapeLayer画线