2017-06-07 32 views
1

一個很簡單的圖,我的問題是製作與uibezierpath

我想創建一個具有一定值的簡單的線圖。這是在mainviewcontroller內的視圖中完成的。我創建了一個名爲chart的UIview。我從API中檢索數據時將數據傳遞給圖表。我想出瞭如何繪製軸,但我現在卡住了。我無法找到任何關於如何設置間隔標籤和使點出現動態谷歌的任何東西。

  • 繪製xasis及其標籤。
  • 在圖中畫點。

我salution

  • 我想出如何做的所有事情我問。

的代碼我現在有:

class ChartView: UIView { 

//some variables 
var times: [String] = [] 
var AmountOfRain: [Double] = [] 
let pathy = UIBezierPath() 
let pathx = UIBezierPath() 
var beginwitharray = Array<CGFloat>() 

// Only override draw() if you perform custom drawing. 
// An empty implementation adversely affects performance during animation. 
override func draw(_ rect: CGRect) { 
    // Drawing code 

    //draw the y line 
    pathy.move(to: CGPoint(x: 30, y: 10)) 
    pathy.addLine(to: CGPoint(x: 30, y: 10)) 
    pathy.addLine(to: CGPoint(x: 30, y: frame.size.height - 30)) 
    UIColor.black.setStroke() 
    pathy.lineWidth = 1.0 
    pathy.stroke() 

    //draw the x line 
    pathx.move(to: CGPoint(x: 30, y: frame.size.height - 30)) 
    pathx.addLine(to: CGPoint(x: 30, y: frame.size.height - 30)) 
    pathx.addLine(to: CGPoint(x: frame.size.width - 30, y: frame.size.height - 30)) 
    UIColor.black.setStroke() 
    pathx.lineWidth = 1.0 
    pathx.stroke() 

    //when the data arrives form the SUPER slow duienradar API refresh it with the data 
    if beginwitharray != []{ 
     //remove the label retriving data 
     let label = viewWithTag(1) 
     DispatchQueue.main.sync { 
      label?.removeFromSuperview() 
     } 
     //create the dots in the graph 
     var point = CGPoint() 
     //simple way to do 2 loop in 1 loop. 
     var intforbeginarray = 0 
     let stoke = UIBezierPath() 
     //get the first 6 itmes out of the rain array cuz of space issues 
     let first6aumountarray = AmountOfRain[0...5] 
     stoke.move(to: CGPoint(x: 30, y: self.frame.size.height - 30)) 

     //loop trough the data in the amounts array 
     for amount in first6aumountarray{ 
      //determen the hight of the dot 
      let InitialHeight = (CGFloat(amount) * (self.frame.size.height - 30))/6 
      let pointHeight = (frame.size.height - 30) - InitialHeight 

       //make the point so we can draw it using UIbezierpath() 
       point = CGPoint(x: beginwitharray[intforbeginarray] + 20, y: pointHeight) 
       intforbeginarray += 1 

       //create the dot 
       let dot = UIBezierPath() 
       dot.addArc(withCenter: point, radius: CGFloat(5), startAngle: CGFloat(0), endAngle: CGFloat(360), clockwise: true) 
       UIColor.black.setFill() 
       dot.lineWidth = 30 
       dot.fill() 

       //create the line between dots will give a warning on the last one cuz the last one doenst go anyway 
       stoke.addLine(to: point) 
       stoke.move(to: point) 
       stoke.lineWidth = 1 
       UIColor.black.setStroke() 
     } 
     //make the strokes 
     stoke.stroke() 
    } 
} 
func getvalues(RainData: [Double], TimesData:[String]){ 

    //assing the data to the subview 
    self.AmountOfRain = RainData 
    self.times = TimesData 

    //xaxis values 
    let maxint = [0, 1, 2, 3, 4, 5, 6] 

    //calculate the hight spacing to fit the graph 
    let heightperstep = ((self.frame.size.height - 5)/6)-5 
    var beginheight = self.frame.size.height - 35 

    //calculate the width spacing to fit the graph 
    let widthperstep = ((self.frame.size.width - 5)/6)-5 
    var beginwith = CGFloat(30) 

    //extra check to see if we have data at all. 
    if times != []{ 
     //get the first 6 items out of the times array for use in our graph 
     let first6 = times[0...5] 
     //draw the label on the main queue 
     DispatchQueue.main.sync { 
      //draw the xaxis labels accroding to the spacing 
      for number in maxint{ 
       let label = UILabel(frame: CGRect(x: 5, y: beginheight, width: 25, height: 15)) 
       label.text = "\(number)" 
       self.addSubview(label) 
       beginheight = beginheight - heightperstep 
      } 
      //draw the yaxis labels according to the spacing 
      for time in first6{ 
       let label = UILabel(frame: CGRect(x: beginwith, y: self.frame.size.height - 20, width: 55, height: 15)) 
       label.text = time 
       self.addSubview(label) 
       beginwitharray.append(beginwith) 
       beginwith = beginwith + widthperstep 
      } 
     } 
    } 
    //redrawthe graph with new data. 
    setNeedsDisplay() 
}} 

任何幫助,將不勝感激。我也不能使用lib或pod,因爲這是一個學校項目,我需要創建一個簡單的圖形。

編輯:

完成了我的代碼,這段代碼運行

我也第一次是畫在x ASIS和y軸的時候清理了一個錯誤。在此之後,我考慮了有關數據的合理值。這個結果不可能真的高於6.因爲我可以在空間中放置大約6個標籤,所以我的步驟容易下降1,直到達到0爲止。我所做的計算是針對特定的幀高度。之後我想到了這一切以及y-asxis的填充。這是一個搞清楚如何在正確的地方找到點的問題。由於我已經擁有了beginwitharray中的數據,我只需要計算高度。然後它簡單地循環數據並繪製每個點。然後,我只需使用uibezierpath連接點。

我希望我的煩惱能夠爲他們節省很多時間,當他們讀到我是如何做到的。

回答

1

這可能會有所幫助:Draw Graph curves with UIBezierPath

你需要做的本質究竟是什麼每個數據集,你有你需要知道的值y軸的範圍,並根據這些範圍分配給每個值CGFloat的值(在你的情況下,英寸雨量需要與某個CGFloat值相關)。假設你有你的套裝amountOfRain = [0.1, 1.3, 1.5, 0.9, 0.1, 0],所以你的範圍是var rangeY = amountOfRain.max() - amountOfRain.min()。現在讓我們通過將英寸雨量轉換爲與您繪製的軸線相對應的CGFloat值來確定您的第一個數據點0.1應該在您的圖表上的哪個位置出現,此方程式僅爲基本代數:let y1 = (amountOfRain[0]/rangeY)*((frame.size.height-30) - 10) + 10現在,它看起來像您的雨樣是定期的,所以現在你可以在CGPoint上添加一個點或者一些對應於(x1,y1)的點。如果您對所有數據點都進行了此操作,則會創建一個圖表,其最大值位於圖形的頂部,最小值位於底部。祝你好運!

+0

非常感謝您的幫助,但它並不是完整的awnser。生病更新我的問題更多的人 – Cees