Swift--UIBezierPath和CAShapeLayer画线

  • 时间:2018-12-24 22:36 作者:橘子star 来源:橘子star 阅读:858
  • 扫一扫,手机访问
摘要:UIBezierPath和CAShapeLayer画线(注意:该文章仅对Swift语言的画图部分的学习做简单总结,熟习两种语言的小伙伴,可以随便)<一>UIBezierPath(UIBezierPath官方详情)UIBezierPath继承自NSObject对象。我们可以使用这个类来指定路径的几何形

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下载,觉得有用的点个星吧。有什么错误和不足的地方也欢迎指正。

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】2FA验证器 验证码如何登录(2024-04-01 20:18)
【系统环境|】怎么做才能建设好外贸网站?(2023-12-20 10:05)
【系统环境|软件环境】梦幻仙域游戏攻略(2023-12-19 10:02)
【系统环境|软件环境】梦幻仙域游戏攻略(2023-12-19 10:02)
【系统环境|】卡帕部落揭秘潮玩新宠,探究玩法(2023-12-14 09:45)
【系统环境|数据库】 潮玩宇宙游戏道具收集方法(2023-12-12 16:13)
【系统环境|】如何开发搭建卡帕部落模式源码(2023-12-12 10:44)
【系统环境|】遥遥领先!青否数字人直播系统5.0发布,支持真人接管实时驱动!(2023-10-12 17:31)
【系统环境|服务器应用】克隆自己的数字人形象需要几步?(2023-09-20 17:13)
【系统环境|】Tiktok登录教程(2023-02-13 14:17)
手机二维码手机访问领取大礼包
返回顶部