diff --git a/linechart/linechart/LineChart.swift b/linechart/linechart/LineChart.swift old mode 100644 new mode 100755 index fe9ed1a..9ce8b41 --- a/linechart/linechart/LineChart.swift +++ b/linechart/linechart/LineChart.swift @@ -17,13 +17,19 @@ func - (left: Array, right: Array) -> Array { } - // delegate method @objc protocol LineChartDelegate { func didSelectDataPoint(x: CGFloat, yValues: Array) + optional func plotLabelForX(index: Int) -> String + optional func plotLabelForY(index: Int) -> String } +enum Axis { + case x + case y +} +typealias PlotLabelForAxis = (axis: Axis, index: Int) -> (text: String, degreesRotated: CGFloat) // LineChart class class LineChart: UIControl { @@ -34,11 +40,15 @@ class LineChart: UIControl { var dotsVisible = true var labelsXVisible = false var labelsYVisible = false + var xLabelPercentOffsetFromCenter: CGFloat = 0 + var yLabelPercentOffsetFromCenter: CGFloat = 0 + var areaUnderLinesVisible = false var numberOfGridLinesX: CGFloat = 10 var numberOfGridLinesY: CGFloat = 10 var animationEnabled = true var animationDuration: CFTimeInterval = 1 + var plotLabelForAxis: PlotLabelForAxis? var dotsBackgroundColor = UIColor.whiteColor() @@ -176,8 +186,6 @@ class LineChart: UIControl { return UIColor(red: red, green: green, blue: blue, alpha: 1) } - - /** * Lighten color. */ @@ -254,8 +262,6 @@ class LineChart: UIControl { return roundedDividend } - - /** * Highlight data points at index. */ @@ -345,11 +351,10 @@ class LineChart: UIControl { maximum = newMaximum } } + return CGFloat(maximum) } - - /** * Scale to fit drawing width. */ @@ -479,8 +484,6 @@ class LineChart: UIControl { } - - /** * Draw x grid. */ @@ -496,7 +499,6 @@ class LineChart: UIControl { } - /** * Draw y grid. */ @@ -510,11 +512,11 @@ class LineChart: UIControl { CGContextMoveToPoint(context, axisInset, self.bounds.height - (CGFloat(index) * height) - axisInset) CGContextAddLineToPoint(context, self.bounds.width - axisInset, self.bounds.height - (CGFloat(index) * height) - axisInset) } + CGContextStrokePath(context) } - /** * Draw grid. */ @@ -523,8 +525,6 @@ class LineChart: UIControl { drawYGrid() } - - /** * Draw x labels. */ @@ -535,12 +535,59 @@ class LineChart: UIControl { var label = UILabel(frame: CGRect(x: scaledValue + (axisInset/2), y: self.bounds.height-axisInset, width: axisInset, height: axisInset)) label.font = UIFont.systemFontOfSize(10) label.textAlignment = NSTextAlignment.Center - label.text = String(index) + label.lineBreakMode = NSLineBreakMode.ByWordWrapping + label.numberOfLines = 0 + let labelTextAndSizeToFit = labelTextForAxis(Axis.x, index: index) + label.text = labelTextAndSizeToFit.0//String(index) + + applyDimensionsToLabel( + + label, + labelTextAndScale: labelTextAndSizeToFit, + offset: xLabelPercentOffsetFromCenter, + axis: Axis.x + ) + + self.addSubview(label) } } + func degreesToRad(deg: CGFloat) -> CGFloat { + + return deg / (180 * CGFloat(M_PI)) + + } + func radToDeg(rad: CGFloat) -> CGFloat { + + return (rad * (180 / CGFloat(M_PI)) ) + } + + func applyDimensionsToLabel(label: UILabel, labelTextAndScale: (String, Bool, CGFloat), offset: CGFloat, axis: Axis) { + + if labelTextAndScale.1 == true { + + let labelSize = label.text?.sizeWithAttributes([NSFontAttributeName: label.font]) as CGSize? + let width = labelSize?.width + let height = labelSize?.height + let x = axis == .x ? label.frame.origin.x - (width! * offset) : label.frame.origin.x + let y = axis == .y ? label.frame.origin.y - (height! * offset) : label.frame.origin.y + + label.frame = CGRectMake( + + x, + y, + width!, + height! + ) + + let rads = degreesToRad(labelTextAndScale.2) + let tr: CGAffineTransform = CGAffineTransformMakeRotation(rads) + + label.transform = tr + } + } /** * Draw y labels. @@ -555,13 +602,64 @@ class LineChart: UIControl { var label = UILabel(frame: CGRect(x: 0, y: yValue, width: axisInset, height: axisInset)) label.font = UIFont.systemFontOfSize(10) label.textAlignment = NSTextAlignment.Center - label.text = String(index) + label.numberOfLines = 0 + label.lineBreakMode = NSLineBreakMode.ByWordWrapping + let labelTextAndSizeToFit = labelTextForAxis(Axis.y, index: index) + label.text = labelTextAndSizeToFit.0 //String(index) + + applyDimensionsToLabel( + + label, + labelTextAndScale: labelTextAndSizeToFit, + offset: yLabelPercentOffsetFromCenter, + axis: Axis.y + + ) + self.addSubview(label) } } - - - + + func labelTextForAxis(axis: Axis, index: Int) -> (String, Bool, CGFloat) { + + var text = String(index) + var sizeToFit = false + var rotationDegrees: CGFloat = 0 + + if let plotLabelForAxis = plotLabelForAxis as PlotLabelForAxis? { + + let plotLabelForAxis = plotLabelForAxis(axis: axis, index: index) + text = plotLabelForAxis.0 + rotationDegrees = plotLabelForAxis.1 + + sizeToFit = true + + } else { + + if let delegate = delegate as LineChartDelegate? { + + switch axis { + + case .x: + + if let xPlot = delegate.plotLabelForX!(index) as String? { + text = xPlot + sizeToFit = true + } + + case .y: + + if let yPlot = delegate.plotLabelForY!(index) as String? { + text = yPlot + sizeToFit = true + } + } + } + } + + return (text, sizeToFit, rotationDegrees) + } + /** * Add line chart */ diff --git a/linechart/linechart/MainViewController.swift b/linechart/linechart/MainViewController.swift old mode 100644 new mode 100755 index 3effaaa..3032010 --- a/linechart/linechart/MainViewController.swift +++ b/linechart/linechart/MainViewController.swift @@ -3,8 +3,6 @@ import UIKit import QuartzCore class MainViewController: UIViewController, LineChartDelegate { - - var label = UILabel() var lineChart: LineChart? @@ -40,8 +38,6 @@ class MainViewController: UIViewController, LineChartDelegate { } - - override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } @@ -55,7 +51,14 @@ class MainViewController: UIViewController, LineChartDelegate { label.text = "x: \(x) y: \(yValues)" } + func plotLabelForX(index: Int) -> String { + return String(index) + } + func plotLabelForY(index: Int) -> String { + return String(index) + } + /** * Redraw chart on device rotation.