2016-08-09 17 views
2

ライブラリ私は以下を使用しています。charts
私は年の特定の日に値を持つ折れ線グラフを持っています。私はx軸上にラベルとして毎日描画したくない(300日以上の範囲があるかもしれない)ので、私は月だけを描くことを考えている。今、私のxValsは次のようになります:[nil、nil、nil、 "07/2016"、nil nil nil(..)]。残念ながら、ラベルは表示されません。
希望する動作を達成する他の方法はありますか?

コード(x軸値):
iosで選択した軸ラベルをレンダリングする方法

while date.compare(to) != NSComparisonResult.OrderedDescending { // iterate over all days in range 
     let components = currentCalendar.components([.Day, .Month , .Year], fromDate: date) 
     if components.day != 1 { 
      vals.append(nil) 
     } else { // first day of the month 
      vals.append(String(components.month) + "/" + String(components.year)) 
     } 

     let incrementComponents = NSDateComponents() 
     incrementComponents.day = 1 
     date = currentCalendar.dateByAddingComponents(incrementComponents, toDate: date, options: [])! 
} 

とエントリ:

for point in base!.points { 
     if let index = chartValuesFormatter?.indexFromDate(point.date) { 
      entries.append(ChartDataEntry(value: point.value, xIndex: index)) 
     } 
} 

一般的には、私はすべての値それらのいくつかが表示され、エントリが正しくレンダリングさを指定すると、動作します。私の唯一の問題は、月の期間の始めに月ラベルのみを表示することです。

+0

だけで、すべての値の月を入れて、libに – Tj3n

+0

を示すために、値のapprotiate数を選択します。しかし、時にはそれが何度も同じ月よりが表示されます。私は毎月1日に月ラベルを表示する必要があります(または月が多すぎる場合はライブラリを最適化する必要があります)。 –

+0

データの作成方法についていくつかのコードを貼り付けてください。 – Jassi

答えて

0

私は解決策を見つけました。それは(このような基本的な問題のために)すべきであるほど単純ではありませんが、非常にカスタマイズ可能です。 LineChartView (via BarLineChartViewBase)のプロパティはxAxisRendererです。 ChartXAxisRendererをサブクラス化することができます。これはデフォルトのもので、drawLabels機能をオーバーライドします。私の場合は、元のコードをコピーし、計算の背後にあるロジックを変更して、どのラベルをどこに描画するかを決めました。

編集:オーバーラップロジックを備えた私のカスタムレンダラー。恐らくは複雑すぎるかもしれませんが、これまでのところうまくいきます。

class ChartXAxisDateRenderer: ChartXAxisRenderer { 
internal static let FDEG2RAD = CGFloat(M_PI/180.0) 

/// draws the x-labels on the specified y-position 
override func drawLabels(context context: CGContext, pos: CGFloat, anchor: CGPoint) { 

    guard let xAxis = xAxis else { return } 

    let paraStyle = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle 
    paraStyle.alignment = .Center 

    let labelAttrs = [NSFontAttributeName: xAxis.labelFont, 
         NSForegroundColorAttributeName: xAxis.labelTextColor, 
         NSParagraphStyleAttributeName: paraStyle] 
    let labelRotationAngleRadians = xAxis.labelRotationAngle * ChartXAxisDateRenderer.FDEG2RAD 

    let valueToPixelMatrix = transformer.valueToPixelMatrix 

    let minLabelsMargin: CGFloat = 4.0 

    var position = CGPoint(x: 0.0, y: 0.0) 

    var labelMaxSize = CGSize() 

    if (xAxis.isWordWrapEnabled) { 
     labelMaxSize.width = xAxis.wordWrapWidthPercent * valueToPixelMatrix.a 
    } 

    var positions = [CGPoint]() 
    var widths = [CGFloat]() 
    var labels = [String]() 
    var originalIndices = [Int]() 

    for i in 0...xAxis.values.count-1 { 
     let label = xAxis.values[i] 
     if (label == nil || label == "") 
     { 
      continue 
     } 

     originalIndices.append(i) 
     labels.append(label!) 

     position.x = CGFloat(i) 
     position.y = 0.0 
     position = CGPointApplyAffineTransform(position, valueToPixelMatrix) 
     positions.append(position) 

     let labelns = label! as NSString 
     let width = labelns.boundingRectWithSize(labelMaxSize, options: .UsesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width 
     widths.append(width) 
    } 

    let newIndices = findBestPositions(positions, widths: widths, margin: minLabelsMargin) 

    for index in newIndices { 
     let label = labels[index] 
     let position = positions[index] 
     let i = originalIndices[index] 

     if (viewPortHandler.isInBoundsX(position.x)) { 
      drawLabel(context: context, label: label, xIndex: i, x: position.x, y: pos, attributes: labelAttrs, constrainedToSize: labelMaxSize, anchor: anchor, angleRadians: labelRotationAngleRadians) 
     } 
    } 
} 

// Best position indices - minimum "n" without overlapping 
private func findBestPositions(positions: [CGPoint], widths: [CGFloat], margin: CGFloat) -> [Int] { 
    var n = 1 
    var overlap = true 

    // finding "n" 
    while n < widths.count && overlap { 
     overlap = doesOverlap(n, positions: positions, widths: widths, margin: margin) 
     if overlap { 
      n += 1 
     } 
    } 

    var newPositions = [Int]() 
    var i = 0 
    // create result indices 
    while i < positions.count { 
     newPositions.append(i) 
     i += n 
    } 

    return newPositions 
} 

// returns whether drawing only n-th labels will casue overlapping 
private func doesOverlap(n: Int, positions: [CGPoint], widths: [CGFloat], margin: CGFloat) -> Bool { 
    var i = 0 
    var newPositions = [CGPoint]() 
    var newWidths = [CGFloat]() 

    // getting only n-th records 
    while i < positions.count { 
     newPositions.append(positions[i]) 
     newWidths.append(widths[i]) 
     i += n 
    } 

    // overlap with next label checking 
    for j in 0...newPositions.count - 2 { 
     if newPositions[j].x + newWidths[j] + margin > newPositions[j+1].x { 
      return true 
     } 
    } 

    return false 
} 

}

+0

ご迷惑をおかけして申し訳ありませんが、同じ問題があります。カスタムコードを投稿できますか?ありがとう! – user3745888

+0

@ user3745888が投稿されました。ほとんどのコードは重複していますが、残りはかなり明確になるはずです。私はそれが欠陥があり、複雑すぎると思う(まだ十分にテストされていない)。お気軽にコメントを残してください。 –

関連する問題