如何使用CAShapeLayer和UIBezierPath制作多种颜色的线条?

问题描述 投票:0回答:1

假设我想画一个看起来像这样的图(请原谅我画得不好):

正如你在这里看到的,我想制作一条线上有多种颜色的线。我现在所做的是使用

UIBezierPath
作为路径创建一条线,并使用
CAShapeLayer
来渲染绘图。但我不知道如何设置形状图层的颜色。由于线条可以有多种颜色,我研究了一些答案,但我发现的大多数答案告诉我创建一个
CAGradientLayer
并将形状层作为该渐变层的掩码,如下所示(不是完整的代码,因为其中一些是保密的):

// This function is from a library we used.
import UIKit

struct CurvedSegment {
    var controlPoint1: CGPoint
    var controlPoint2: CGPoint
}

class CurveAlgorithm {
    static let shared = CurveAlgorithm()
    
    public func controlPointsFrom(points: [CGPoint]) -> [CurvedSegment] {
        var result: [CurvedSegment] = []
        
        let delta: CGFloat = 0.3 // The value that help to choose temporary control points.
        
        // Calculate temporary control points, these control points make Bezier segments look straight and not curving at all
        for i in 1..<points.count {
            let A = points[i-1]
            let B = points[i]
            let controlPoint1 = CGPoint(x: A.x + delta*(B.x-A.x), y: A.y + delta*(B.y - A.y))
            let controlPoint2 = CGPoint(x: B.x - delta*(B.x-A.x), y: B.y - delta*(B.y - A.y))
            let curvedSegment = CurvedSegment(controlPoint1: controlPoint1, controlPoint2: controlPoint2)
            result.append(curvedSegment)
        }
        
        // Calculate good control points
        for i in 1..<points.count-1 {
            /// A temporary control point
            let M = result[i-1].controlPoint2
            
            /// A temporary control point
            let N = result[i].controlPoint1
            
            /// central point
            let A = points[i]
            
            /// Reflection of M over the point A
            let MM = CGPoint(x: 2 * A.x - M.x, y: 2 * A.y - M.y)
            
            /// Reflection of N over the point A
            let NN = CGPoint(x: 2 * A.x - N.x, y: 2 * A.y - N.y)
            
            result[i].controlPoint1 = CGPoint(x: (MM.x + N.x)/2, y: (MM.y + N.y)/2)
            result[i-1].controlPoint2 = CGPoint(x: (NN.x + M.x)/2, y: (NN.y + M.y)/2)
        }
        
        return result
    }
    
    /**
     Create a curved bezier path that connects all points in the dataset
     */
    func createCurvedPath(_ dataPoints: [CGPoint]) -> UIBezierPath? {
        let path = UIBezierPath()
        path.move(to: dataPoints[0])
        
        var curveSegments: [CurvedSegment] = []
        curveSegments = controlPointsFrom(points: dataPoints)
        
        for i in 1..<dataPoints.count {
            path.addCurve(to: dataPoints[i], controlPoint1: curveSegments[i-1].controlPoint1, controlPoint2: curveSegments[i-1].controlPoint2)
        }
        return path
    }
}

func createLineDrawing(points: [CGPoint], colors: [CGColor]) {
        self.curveBezierPath = createCurvedPath(points)
        
        let gradientLayer: CAGradientLayer = createGradientLayerWithColors(colors: colors)
        gradientLayer.frame = layer.bounds

        let shapeMask = CAShapeLayer()
        shapeMask.path = curveBezierPath?.cgPath
        shapeMask.strokeColor = UIColor.white.cgColor
        shapeMask.fillColor = UIColor.clear.cgColor
        shapeMask.lineWidth = somelineWidth

        gradientLayer.mask = shapeMask
    }

这段代码的结果不是我想要实现的,因为线条的颜色会垂直移动,并且不会像上面的示例图那样跟随线条的路径。还有其他方法可以实现这一目标吗?我想继续使用

UIBezierPath
来实现线条边缘的平滑(因为
UIBezierPath
addCurve
方法)。

TLDR;无论如何,是否可以在不使用

CAShapeLayer
作为形状图层的背景(也将形状图层作为该渐变图层的蒙版)的情况下为
CAGradientLayer
设置多种颜色?

ios swift core-graphics
1个回答
0
投票

您可以使用其背后的想法来完成您自己的工作:

let path1 = UIBezierPath()
path1.move(to: CGPoint(x: 10, y: 10))
path1.addLine(to: CGPoint(x: 50, y: 10))

let path2 = UIBezierPath()
path2.move(to: CGPoint(x: 50, y: 10))
path2.addLine(to: CGPoint(x: 90, y: 10))

let shapeLayer1 = CAShapeLayer()
shapeLayer1.path = path1.cgPath
shapeLayer1.strokeColor = UIColor.red.cgColor
shapeLayer1.lineWidth = 3

let shapeLayer2 = CAShapeLayer()
shapeLayer2.path = path2.cgPath
shapeLayer2.strokeColor = UIColor.blue.cgColor
shapeLayer2.lineWidth = 3

view.layer.addSublayer(shapeLayer1)
view.layer.addSublayer(shapeLayer2)

此代码绘制两条线段,一红一蓝。您可以根据需要添加更多段和颜色。我希望这对你有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.