Search code examples
swiftcashapelayercagradientlayer

swift how to make gradient layer start at different position


I am coding an area graph, can't upload actual images so I draw an illustration. enter image description here

So I am using two layers, one layer to draw the area, another layer to draw the gradient.

Here is the code for that:

 let area = CGMutablePath()
    let zero = CGFloat(scaleValueOnYAxis(min!.y))

    area.move(to: CGPoint(x: CGFloat(xValues[0]), y: zero))
    for i in 0..<xValues.count {
        area.addLine(to: CGPoint(x: CGFloat(xValues[i]), y: CGFloat(yValues[i])))
    }
    area.addLine(to: CGPoint(x: CGFloat(xValues.last!), y: zero))
    let areaLayer = CAShapeLayer()
    areaLayer.frame = self.bounds
    areaLayer.path = area
    areaLayer.strokeColor = nil
    areaLayer.lineWidth = 0
    layers.append(areaLayer)
    self.layer.addSublayer(areaLayer)

    //draw the gradient layer
    let gradient = CAGradientLayer()
    let startColor = SomeColor.cgColor
    let endColor = SomeOtherColor.cgColor
    let gradientAngle = 0
    let angle = CGPoint.convert(angle: gradientAngle)

    gradient.frame = self.bounds
    gradient.colors = [startColor.cgColor, endColor.cgColor]

    if let _gradientAngle = angle {
        let (startPoint, endPoint) = CGPoint.getStartAndEndPoint(angle: _gradientAngle)
        gradient.startPoint = startPoint
        gradient.endPoint = endPoint
    }
    gradient.mask = areaLayer
    layers.append(gradient)
    self.layer.addSublayer(gradient)

The problem I am having is that the gradient actually starts at the top of the bound, like this: enter image description here

But I want it only to start at the hight data point. But if I change the frame of the gradient layer to move it down, the gradient actually shift down like this: enter image description here

Any help on this please??


Solution

  • You you do not want the gradient frame to be the same size as the shape layer; you want to to be the same size as the bounding box for the path. Fortunately cgPath has a boundingBox method for this.