Swift繪制雷達(dá)圖(蛛網(wǎng)圖、五方圖)

前言

由于項(xiàng)目需求中用到了帶有漸變色的能力雷達(dá)圖,而我們常用的一些三方控件并不能滿足我的項(xiàng)目需求。特此記錄一下自己的實(shí)現(xiàn)此功能的過程。主要使用UIBezierPath路徑相關(guān)、CAShapeLayer繪制相關(guān)、CAGradientLayer漸變色相關(guān),通過對(duì)上述三個(gè)類的組合來實(shí)現(xiàn)此功能。先上一下效果圖

雷達(dá)圖.png

最終的實(shí)現(xiàn)效果會(huì)有一點(diǎn)出入,主要是背景顏色文字顏色可能會(huì)有點(diǎn)不同。如有需要大家可以自行修改一下顏色就可以了

繪制前需要知道的一些東西

  • 如何繪制正多邊形
    繪制多邊形主要是獲取到對(duì)應(yīng)的點(diǎn)的坐標(biāo),下面是獲取點(diǎn)坐標(biāo)的方法
/*
//.pi 、 M_PI  、 Double.pi   這三個(gè)值是一樣的  只不過在OC和swift中的寫法有點(diǎn)不同


***繪制順序是逆時(shí)針順序***獲取橫坐標(biāo)***
index: 第幾個(gè)點(diǎn)的坐標(biāo)
ridus: 正多邊形的半徑值
count: 正幾邊形  如果傳入5的話就代表是5邊形
centerX:圓心的X坐標(biāo)
*/
    private func pointX(index : Int , ridus : Double , count : Int , centerX : Double) -> Double{
        return centerX - cos(.pi / 180 * (90.0 - 360.0 / count * Double(index))) * ridus
    }
    
/*
***繪制順序是逆時(shí)針順序***獲取縱坐標(biāo)***
index: 第幾個(gè)點(diǎn)的坐標(biāo)
ridus: 正多邊形的半徑值
count: 正幾邊形  如果傳入5的話就代表是5邊形
centerY:圓心的Y坐標(biāo)
*/
    private func pointY(index : Int , ridus : Double , count : Int , centerY : Double) -> Double{
        return centerY - sin(.pi / 180 * (90.0 - 360.0 / count * Double(index))) * ridus
    }
  • 如何繪制一個(gè)帶邊線的不規(guī)則漸變五邊形(即本文章中最終實(shí)現(xiàn)的內(nèi)容視圖的樣式)
  1. 邊線的實(shí)現(xiàn)方法
    在開發(fā)過程中我們肯定或多或少的都用過CAShapeLayer進(jìn)行一些繪制相關(guān)的操作,其中有一個(gè)設(shè)置畫筆顏色的方法strokeColor而這個(gè)屬性只能設(shè)置單顏色,所以在繪制漸變線條的時(shí)候這個(gè)方法是無法實(shí)現(xiàn)的,這時(shí)候就要用到CAGradientLayer這個(gè)與漸變有關(guān)的類來實(shí)現(xiàn)了。
    下面來具體說一下實(shí)現(xiàn)思路:
    第一步:設(shè)置CAGradientLayer的漸變色和對(duì)應(yīng)的frame
    第二步:設(shè)置CAShapeLayerfillColorstrokeColor
    第三步:將設(shè)置好的CAShapeLayer添加到CAGradientLayermask屬性上面
    第四步:將設(shè)置好的CAGradientLayer添加到viewlayer上面
    具體的關(guān)于fillColorstrokeColor
    如果設(shè)置fillColorclear則會(huì)只顯示線條部分的漸變色。這個(gè)就是實(shí)現(xiàn)線條漸變的核心的地方
  2. 內(nèi)容層漸變的實(shí)現(xiàn)方法
    關(guān)于內(nèi)部層漸變的實(shí)現(xiàn)其實(shí)和邊線的實(shí)現(xiàn)差不多。主要的區(qū)別還是在于fillColorstrokeColor的設(shè)置上做一些不同的設(shè)置就可以了

繪制最里面的小五邊形

  1. 繪制路徑
    private func setCenterCobWeb(){
        //設(shè)置五邊形的五個(gè)頂點(diǎn)的位置
        let path = UIBezierPath.init()
        for index in 0...4 {
            let point = CGPoint.init(
                x: pointX(index : index , ridus : 10 , count : 5 , centerY : self.center.x),//此處我的圓心點(diǎn)是View的正中心
                y: pointY(index : index , ridus : 10 , count : 5 , centerY : self.center.x)
            )
            if index == 0 {
                path.move(to: point)
                continue
            }
            path.addLine(to: point)
        }
        
        //設(shè)置畫筆的相關(guān)屬性
        let centerCobWebLayer = CAShapeLayer.init()
        centerCobWebLayer.path = path.cgPath
        centerCobWebLayer.lineWidth = 0//因?yàn)槲业膬?nèi)側(cè)的五邊形是帶有填充色的且線的顏色和填充色一樣所以此處設(shè)置0
        //如果這個(gè)位置邊線和填充色不一樣的話則需要這樣設(shè)置
        /*
          centerCobWebLayer.fillColor = strokeColor.cgColor//自己替換顏色
          centerCobWebLayer.strokeColor = strokeColor.cgColor//自己替換顏色
        */
        centerCobWebLayer.fillColor = strokeColor.cgColor//此處修改成自己的填充色
        //添加到layer上去
        self.layer.addSublayer(centerCobWebLayer)
        
    }
     //獲取X坐標(biāo)
     private func pointX(index : Int , ridus : Double , count : Int , centerX : Double) -> Double{
        return centerX - cos(.pi / 180 * (90.0 - 360.0 / count * Double(index))) * ridus
    }
    //獲取Y坐標(biāo)
    private func pointY(index : Int , ridus : Double , count : Int , centerY : Double) -> Double{
        return centerY - sin(.pi / 180 * (90.0 - 360.0 / count * Double(index))) * ridus
    }

繪制最里面的小五邊形對(duì)應(yīng)的五條虛線的邊

    //此方法可以直接在繪制小五邊形的時(shí)候在獲取坐標(biāo)點(diǎn)的for循環(huán)里面直接調(diào)用就可以了
    private func setLinelayer(index : Int){
        let lineLayer = CAShapeLayer.init()
        lineLayer.bounds = self.bounds
        //此處一定要設(shè)置,不然的話繪制的位置會(huì)出現(xiàn)變化
        lineLayer.position = CGPoint.init(x: centerX, y: centerX)  //定到你的圓心點(diǎn)的位置就可以了
        lineLayer.fillColor = UIColor.clear.cgColor
        lineLayer.strokeColor = strokeColor.cgColor
        lineLayer.lineWidth = 1
        lineLayer.lineDashPattern = [5,10]//虛線相關(guān)的屬性  【虛線長度,虛線間隔】
        //開始點(diǎn)的坐標(biāo)-> 虛線離著最里面的小五邊形有一點(diǎn)點(diǎn)的距離。小五邊形的半徑是10  此處設(shè)置15,
        //如果不需要也可以設(shè)置成和小五邊形一樣的半徑
        let startPoint = CGPoint.init(
            x: pointX(index : index , ridus : 15 , count : 5 , centerY : self.center.x),
            y: pointY(index : index , ridus : 15 , count : 5 , centerY : self.center.x)
        )
        //結(jié)束點(diǎn)的坐標(biāo)->最外層的大的五邊形的坐標(biāo)
        let endPoint = CGPoint.init(
            x: pointX(index : index , ridus : 大五邊形的半徑 - 大五邊形的線的寬度 * 2 , count : 5 , centerY : self.center.x),
            y: pointY(index : index , ridus : 大五邊形的半徑 - 大五邊形的線的寬度 * 2 , count : 5 , centerY : self.center.x)
            //說明一下:大五邊形的線的寬度 * 2  這個(gè)是因?yàn)椴粶p去這個(gè)寬度的話
            //最終繪制出來的虛線和大五邊形的邊出現(xiàn)重疊的情況。如果沒有這個(gè)要求的話可以直接去掉這個(gè)
        )
        
        let path = CGMutablePath.init()
        path.move(to: startPoint)
        path.addLine(to: endPoint)
        lineLayer.path = path
        self.layer.addSublayer(lineLayer)
    }

繪制大五邊形

    private func setCobwebLineLayer(){
        let path = UIBezierPath.init()
        var endPoint = CGPoint.init(x: 0, y: 0)
        for index in 0...4 {//繪制幾邊形就到幾
            let point = CGPoint.init(
                
                x: pointX(index : index , ridus : 大五邊形半徑 , count : 5 , centerY : self.center.x),
                y: pointY(index : index , ridus : 大五邊形半徑 , count : 5 , centerY : self.center.x)
            )
            if index == 0 {
                path.move(to: point)
                endPoint = point
                continue
            }
            path.addLine(to: point)
        }
        //也可以最終不添加這個(gè)endPoind 直接調(diào)用 path.close()
        //如果直接使用path.close() 呢在設(shè)置線條的圓角的話就會(huì)出現(xiàn)問題,
        //如果線條的交點(diǎn)不需要圓角可以直接使用path.close()
        path.addLine(to: endPoint)
        
        let cobWebLayer = CAShapeLayer.init()
        cobWebLayer.path = path.cgPath
        cobWebLayer.lineWidth = CGFloat(cobwebLineWidth)//畫筆的寬度 自行修改
        cobWebLayer.lineCap = .round//線條圓角相關(guān)
        cobWebLayer.lineJoin = .round//線條圓角相關(guān)
        cobWebLayer.strokeColor = strokeColor.cgColor//自行修改畫筆顏色
        cobWebLayer.fillColor = Color.clear.cgColor//填充色要設(shè)置成透明的
        self.layer.addSublayer(cobWebLayer)
    }

繪制數(shù)據(jù)的填充層和線條

一定是要先繪制填充層
**關(guān)于代碼中pointXArraypointYArray的說明:

  1. 在設(shè)置gradientLayerframe的時(shí)候設(shè)置多大呢么漸變的內(nèi)容層就是多大。所以正常的漸變應(yīng)該是內(nèi)容層呢一部分進(jìn)行漸變就可以了。如果設(shè)置的frame是當(dāng)前view的大小呢么內(nèi)容層的漸變只能是一部分。所以此處用兩個(gè)數(shù)組保存x坐標(biāo)y坐標(biāo)用來回去最大值和最小值
  2. 設(shè)置了gradientLayerframe以后現(xiàn)在的數(shù)據(jù)層的坐標(biāo)的計(jì)算就類似于在一個(gè)View上添加一個(gè)ImagView的坐標(biāo)和你現(xiàn)在把這個(gè)ImageView添加到了一個(gè)新的View上面然后把新的View添加到當(dāng)前的view上面此時(shí)ImageView的坐標(biāo)性質(zhì)差不多。只要保證還是現(xiàn)實(shí)在原來的位置就可以了
    private func setValueLayer(){
        self.valueArray = [0.5,0.4,0.9,0.7,0.2]//五條邊對(duì)應(yīng)的占比
        let path = UIBezierPath.init()
        var pointXArray = [CGFloat]()
        var pointYArray = [CGFloat]()
        for (index , value) in self.valueArray!.enumerated() {
            let point = CGPoint.init(
                x: pointX(index : index , ridus : 15 + (ridus - 15) * value , count : 5 , centerY : self.center.x),
                y: pointY(index : index , ridus : 15 + (ridus - 15) * value , count : 5 , centerY : self.center.x)
            )
            pointXArray.append(point.x)
            pointYArray.append(point.y)
        }
        for (index , value) in pointXArray.enumerated() {
            if index == 0 {
                path.move(to: CGPoint.init(x: value - pointXArray.min()!, y: pointYArray[index] - pointYArray.min()!))
            }else{
                path.addLine(to: CGPoint.init(x: value - pointXArray.min()!, y: pointYArray[index] - pointYArray.min()!))
            }
        }
        let shapeLayer = CAShapeLayer.init()
        shapeLayer.path = path.cgPath
        shapeLayer.strokeColor = UIColor.white.cgColor
        shapeLayer.fillColor = UIColor.white.cgColor
        shapeLayer.lineWidth = 0//此處做填充層 所以沒有線 畫筆寬度為0就可以了
        
        let gradientLayer = CAGradientLayer.init()
        gradientLayer.frame = CGRect(x: pointXArray.min()!, y: pointYArray.min()!, width: pointXArray.max()! - pointXArray.min()!, height: pointYArray.max()! - pointYArray.min()!)
        gradientLayer.startPoint = CGPoint.init(x: 0.5, y: 0)
        gradientLayer.endPoint = CGPoint.init(x: 0.5, y: 1)
        let gradientLayerColors = infoFillColors
        gradientLayer.colors = gradientLayerColors
        gradientLayer.mask = shapeLayer
        self.layer.addSublayer(gradientLayer)
    }

繪制漸變的線條

private func setValueLineLayer(){
        let path = UIBezierPath.init()
        var pointXArray = [CGFloat]()
        var pointYArray = [CGFloat]()
        for (index , value) in self.valueArray!.enumerated() {
            let point = CGPoint.init(
                 x: pointX(index : index , ridus : 15 + (ridus - 15) * value , count : 5 , centerY : self.center.x),
                y: pointY(index : index , ridus : 15 + (ridus - 15) * value , count : 5 , centerY : self.center.x)
            )
            pointXArray.append(point.x)
            pointYArray.append(point.y)
        }
        
        for (index , value) in pointXArray.enumerated() {
            if index == 0 {
                path.move(to: CGPoint.init(x: value - pointXArray.min()!, y: pointYArray[index] - pointYArray.min()!))
            }else{
                path.addLine(to: CGPoint.init(x: value - pointXArray.min()!, y: pointYArray[index] - pointYArray.min()!))
            }
        }
        
        path.close()
        let lineChartLayer = CAShapeLayer.init()
        lineChartLayer.path = path.cgPath
        lineChartLayer.strokeColor = UIColor.white.cgColor
        lineChartLayer.fillColor = UIColor.clear.cgColor//設(shè)置填充色為clear 則只會(huì)顯示線條部分的漸變色
        lineChartLayer.lineWidth = 2//此處一定要設(shè)置線條的寬度
        let gradientLayer =  CAGradientLayer.init()
        gradientLayer.frame = CGRect(x: pointXArray.min()!, y: pointYArray.min()!, width:pointXArray.max()! - pointXArray.min()!, height: pointYArray.max()! - pointYArray.min()!)
        gradientLayer.colors = infoLineColors
        gradientLayer.startPoint = CGPoint.init(x:0.5, y:0);
        gradientLayer.endPoint = CGPoint.init(x:0.5,y: 1);
        gradientLayer.mask = lineChartLayer
        self.layer.addSublayer(gradientLayer)
    }

大的五邊形的文字信息

關(guān)于大五邊形文字信息的設(shè)置這里就不上代碼了。簡單的說一下實(shí)現(xiàn)方法就可以了:

  • 在我們繪制大五邊形的點(diǎn)的時(shí)候會(huì)獲取到五個(gè)點(diǎn),然后根據(jù)五個(gè)點(diǎn)的信息我們就可以拿到labelframe的一些關(guān)鍵信息了。
  • 根據(jù)獲取到的五個(gè)點(diǎn)正常的創(chuàng)建Label然后添加到view上面就可以了

項(xiàng)目中我寫的完整的代碼

import UIKit

class CobwebChartView: UIView {
    
    var centerX : Double = 0
    var centerY : Double = 0
    var ridus : Double = 0
    let cobwebLineWidth : Double = 2
    let strokeColor = UIColor.init(red: 30 / 255.0, green: 174 / 255.0, blue: 197 / 255.0, alpha: 1)
    let infoFillColors = [UIColor.init(red: 248 / 255.0, green: 24 / 255.0, blue: 101 / 255.0, alpha: 0.16).cgColor,
                          UIColor.init(red: 157 / 255.0, green:109 / 255.0, blue: 211 / 255.0, alpha: 0.16).cgColor]
    //let infoFillColors = [UIColor.red.cgColor,UIColor.blue.cgColor]
    let infoLineColors = [UIColor.init(red: 248 / 255.0, green: 24 / 255.0, blue: 101 / 255.0, alpha: 1).cgColor,
                          UIColor.init(red: 157 / 255.0, green:109 / 255.0, blue: 211 / 255.0, alpha: 1).cgColor]
    
    var valueArray : [Double]?{
        didSet{
            self.setCenterCobWeb()
            self.setCobwebLineLayer()
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = Color.viewBgColor
        self.centerX = Double(self.height / 2.0)
        self.centerY = Double(self.height / 2.0)
        self.ridus = centerX - 50
        self.setCenterCobWeb()
        self.setCobwebLineLayer()
        self.setValueLayer()
        self.setValueLineLayer()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

extension CobwebChartView{
    //MARK:設(shè)置最內(nèi)側(cè)的正五邊形
    private func setCenterCobWeb(){
        let path = UIBezierPath.init()
        for index in 0...4 {
            let point = CGPoint.init(
                x: pointX(index: index, ridus: 10),
                y: pointY(index: index, ridus: 10)
            )
            setLinelayer(index: index)
            if index == 0 {
                path.move(to: point)
                continue
            }
            path.addLine(to: point)
        }
        
        let centerCobWebLayer = CAShapeLayer.init()
        centerCobWebLayer.path = path.cgPath
        centerCobWebLayer.lineWidth = 0
        centerCobWebLayer.fillColor = strokeColor.cgColor
        self.layer.addSublayer(centerCobWebLayer)
        
    }
    
    private func setLinelayer(index : Int){
        let lineLayer = CAShapeLayer.init()
        lineLayer.bounds = self.bounds
        lineLayer.position = CGPoint.init(x: centerX, y: centerX)
        lineLayer.fillColor = UIColor.clear.cgColor
        lineLayer.strokeColor = strokeColor.cgColor
        lineLayer.lineWidth = 1
        lineLayer.lineDashPattern = [5,10]
        let startPoint = CGPoint.init(
            x: pointX(index: index, ridus: 15),
            y: pointY(index: index, ridus: 15)
        )
        
        let endPoint = CGPoint.init(
            x: pointX(index: index, ridus: ridus - cobwebLineWidth * 2),
            y: pointY(index: index, ridus: ridus - cobwebLineWidth * 2)
        )
        
        let path = CGMutablePath.init()
        path.move(to: startPoint)
        path.addLine(to: endPoint)
        lineLayer.path = path
        self.layer.addSublayer(lineLayer)
    }
    
    private func setCobwebLineLayer(){
        let path = UIBezierPath.init()
        var endPoint = CGPoint.init(x: 0, y: 0)
        let titleArray = ["力量","恢復(fù)","耐力","柔韌性","平衡"]
        for index in 0...4 {
            let point = CGPoint.init(
                x: pointX(index: index, ridus: ridus),
                y: pointY(index: index, ridus: ridus)
            )
            
            if index == 0 {
                path.move(to: point)
                endPoint = point
                setTitleLabel(position: .top, point: point, title: titleArray[index])
                continue
            }
            if index == 1 {
                setTitleLabel(position: .left, point: point, title: titleArray[index])
            }
            
            if index == 2 || index == 3 {
                setTitleLabel(position: .bottom, point: point, title: titleArray[index])
            }
            if index == 4 {
                setTitleLabel(position: .right, point: point, title: titleArray[index])
            }
            path.addLine(to: point)
        }
        path.addLine(to: endPoint)
        
        let cobWebLayer = CAShapeLayer.init()
        cobWebLayer.path = path.cgPath
        cobWebLayer.lineWidth = CGFloat(cobwebLineWidth)
        cobWebLayer.lineCap = .round
        cobWebLayer.lineJoin = .round
        cobWebLayer.strokeColor = strokeColor.cgColor
        cobWebLayer.fillColor = Color.clear.cgColor
        self.layer.addSublayer(cobWebLayer)
    }
    
    private func setValueLayer(){
        self.valueArray = [0.5,0.4,0.9,0.7,0.2]
        let path = UIBezierPath.init()
        var pointXArray = [CGFloat]()
        var pointYArray = [CGFloat]()
        for (index , value) in self.valueArray!.enumerated() {
            let point = CGPoint.init(
                x: pointX(index: index, ridus: 15 + (ridus - 15) * value),
                y: pointY(index: index, ridus: 15 + (ridus - 15) * value)
            )
            pointXArray.append(point.x)
            pointYArray.append(point.y)
        }
        for (index , value) in pointXArray.enumerated() {
            if index == 0 {
                path.move(to: CGPoint.init(x: value - pointXArray.min()!, y: pointYArray[index] - pointYArray.min()!))
            }else{
                path.addLine(to: CGPoint.init(x: value - pointXArray.min()!, y: pointYArray[index] - pointYArray.min()!))
            }
        }
        let shapeLayer = CAShapeLayer.init()
        shapeLayer.path = path.cgPath
        shapeLayer.strokeColor = UIColor.white.cgColor
        shapeLayer.fillColor = UIColor.white.cgColor
        shapeLayer.lineWidth = 0
        
        let gradientLayer = CAGradientLayer.init()
        gradientLayer.frame = CGRect(x: pointXArray.min()!, y: pointYArray.min()!, width: pointXArray.max()! - pointXArray.min()!, height: pointYArray.max()! - pointYArray.min()!)
        gradientLayer.startPoint = CGPoint.init(x: 0.5, y: 0)
        gradientLayer.endPoint = CGPoint.init(x: 0.5, y: 1)
        let gradientLayerColors = infoFillColors
        gradientLayer.colors = gradientLayerColors
        gradientLayer.mask = shapeLayer
        self.layer.addSublayer(gradientLayer)
        
        
        
    }
    
    private func setValueLineLayer(){
        let path = UIBezierPath.init()
        var pointXArray = [CGFloat]()
        var pointYArray = [CGFloat]()
        for (index , value) in self.valueArray!.enumerated() {
            let point = CGPoint.init(
                x: pointX(index: index, ridus: 15 + (ridus - 15) * value),
                y: pointY(index: index, ridus: 15 + (ridus - 15) * value)
            )
            pointXArray.append(point.x)
            pointYArray.append(point.y)
        }
        
        for (index , value) in pointXArray.enumerated() {
            if index == 0 {
                path.move(to: CGPoint.init(x: value - pointXArray.min()!, y: pointYArray[index] - pointYArray.min()!))
            }else{
                path.addLine(to: CGPoint.init(x: value - pointXArray.min()!, y: pointYArray[index] - pointYArray.min()!))
            }
        }
        
        path.close()
        let lineChartLayer = CAShapeLayer.init()
        lineChartLayer.path = path.cgPath
        lineChartLayer.strokeColor = UIColor.white.cgColor
        lineChartLayer.fillColor = UIColor.clear.cgColor
        lineChartLayer.lineWidth = 2
        let gradientLayer =  CAGradientLayer.init()
        gradientLayer.frame = CGRect(x: pointXArray.min()!, y: pointYArray.min()!, width:pointXArray.max()! - pointXArray.min()!, height: pointYArray.max()! - pointYArray.min()!)
        gradientLayer.colors = infoLineColors
        gradientLayer.startPoint = CGPoint.init(x:0.5, y:0);
        gradientLayer.endPoint = CGPoint.init(x:0.5,y: 1);
        gradientLayer.mask = lineChartLayer
        self.layer.addSublayer(gradientLayer)
    }
    
    private func setTitleLabel(position : LabelPosition , point : CGPoint , title : String){
        let titleLabel = UILabel.init()
        titleLabel.text = title
        titleLabel.font = UIFont.systemFont(ofSize: 14)
        titleLabel.sizeToFit()
        if position == .left {
            titleLabel.frame = CGRect(x: point.x - 10 - titleLabel.frame.size.width, y: point.y - titleLabel.frame.size.height / 2.0, width: titleLabel.frame.size.width, height: titleLabel.frame.size.height)
        }
        if position == .top {
            titleLabel.frame = CGRect(x: point.x - titleLabel.frame.size.width / 2.0, y: point.y - titleLabel.frame.size.height - 10, width: titleLabel.frame.size.width, height: titleLabel.frame.size.height)
        }
        
        if position == .right {
            titleLabel.frame = CGRect(x: point.x + 10, y: point.y - titleLabel.frame.size.height / 2.0, width: titleLabel.frame.size.width, height: titleLabel.frame.size.height)
        }
        if position == .bottom {
            titleLabel.frame = CGRect(x: point.x - titleLabel.frame.size.width / 2.0, y: point.y + 10, width: titleLabel.frame.size.width, height: titleLabel.frame.size.height)
        }
        self.addSubview(titleLabel)
    }
    
    enum LabelPosition {
        case left
        case right
        case top
        case bottom
    }
}

extension CobwebChartView{
    private func pointX(index : Int , ridus : Double) -> Double{
        return centerX - cos(.pi / 180 * (90.0 - 360.0 / 5 * Double(index))) * ridus
    }
    
    private func pointY(index : Int , ridus : Double) -> Double{
        return centerY - sin(.pi / 180 * (90.0 - 360.0 / 5 * Double(index))) * ridus
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容