iOS 3D效果雷达图

iOS Radar Chart with 3D Effect

我想在我的应用程序中复制此图表。

我试图在网上搜索,但只找到 pods,具体是 Charts.

我尝试对其进行自定义,但无法通过为每个 "triangle" 分配不同的颜色阴影来赋予它 3d 效果。

我怎样才能复制它? Uibezierpath 还是别的?

玩得开心。

class GraphView: UIView {

let cirleSegnaposto:CGFloat = 20.0
let labelSize:Double = 50
let spacingGraphLabel:Double = 0
let widthOfZero:Double = 30

let labels = ["Label 1", "Label 2", "Label 3", "Label 4", "Label 5"]
let firstColors:[UIColor] = [.darkGray, .black, .darkGray, .lightGray, .white]
let secondColors:[UIColor] = [.orange, .brown, .orange, .yellow, .red]

var values: [Int]? = nil
var secondValues: [Int]? = nil

override func draw(_ rect: CGRect) {
    for i in 0 ..< 4 {
        let cirleLayer = CAShapeLayer()

        let delta = Double(15 * i) + labelSize
        let path = UIBezierPath(ovalIn: CGRect(x: delta,
                                               y: delta,
                                               width: Double(rect.width) - delta * 2,
                                               height: Double(rect.width) - delta * 2))

        cirleLayer.path = path.cgPath
        cirleLayer.lineWidth = 1
        cirleLayer.strokeColor = UIColor.lightGray.cgColor
        cirleLayer.fillColor = UIColor.clear.cgColor

        self.layer.addSublayer(cirleLayer)
    }

    let radius:Double = Double(rect.width/2) - (labelSize - spacingGraphLabel)
    let labelRadius:Double = Double(rect.width/2) + (spacingGraphLabel)

    let origin = CGPoint(x: rect.width/2, y: rect.height/2)

    for i in 0..<5 {
        let cirleLayer = CAShapeLayer()

        let angle:Double = Double(i)/5.0 * (2 * .pi)

        let centerX = Double(origin.x) + radius * cos(angle)
        let centerY = Double(origin.y) - radius * sin(angle)

        let path = UIBezierPath(ovalIn: CGRect(x: CGFloat(centerX) - cirleSegnaposto/2,
                                               y: CGFloat(centerY) - cirleSegnaposto/2,
                                               width: cirleSegnaposto,
                                               height: cirleSegnaposto))

        cirleLayer.path = path.cgPath
        cirleLayer.fillColor = UIColor.lightGray.cgColor
        cirleLayer.lineWidth = 0.5
        cirleLayer.strokeColor = UIColor.black.cgColor

        self.layer.addSublayer(cirleLayer)

        let label = UILabel(frame: .zero)
        label.font = UIFont.systemFont(ofSize: 12)
        label.text = labels[i]
        label.frame.size = CGSize(width: labelSize, height: labelSize/2)

        let labelCenterX = Double(origin.x) + labelRadius * cos(angle)
        let labelCenterY = Double(origin.y) - labelRadius * sin(angle)

        label.center = CGPoint(x: labelCenterX, y: labelCenterY)
        label.transform = label.transform.rotated(by: .pi/2)

        self.addSubview(label)
    }

    if let values = secondValues {
        drawGraph(values: values, center: origin, maxValue: radius, colors: secondColors.map({[=10=].cgColor}))
    }

    if let values = values {
        drawGraph(values: values, center: origin, maxValue: radius, colors: firstColors.map({[=10=].cgColor}))
    }
}

func drawGraph(values: [Int], center: CGPoint, maxValue: Double, colors: [CGColor]) {
    var points = [CGPoint]()
    for i in 0 ..< values.count {
        let radius = Double(values[i])/10.0 * (maxValue - widthOfZero) + widthOfZero

        let angle:Double = Double(i)/5.0 * (2 * .pi)

        let x = Double(center.x) + radius * cos(angle)
        let y = Double(center.y) - radius * sin(angle)

        let point = CGPoint(x: x, y: y)
        points.append(point)
    }

    for (i, point) in points.enumerated() {
        let secondPoint = point == points.last ? points[0] : points[i+1]

        let path = UIBezierPath()
        path.move(to: center)
        path.addLine(to: point)
        path.addLine(to: secondPoint)
        path.close()

        let layer = CAShapeLayer()
        layer.path = path.cgPath
        layer.fillColor = colors[i]
        layer.lineWidth = 1
        layer.lineJoin = .round
        layer.strokeColor = UIColor.black.cgColor

        self.layer.addSublayer(layer)
    }
}

}