From 5a4168357ceb3e9796e946741540e04296764162 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 8 Apr 2016 17:30:10 +0300 Subject: [PATCH 1/6] Added horizontal cubic (not exaggerating vertical control points) --- .../Standard/LineChartDataSet.swift | 41 +++++-- .../Data/Interfaces/ILineChartDataSet.swift | 19 +++- .../Classes/Renderers/LineChartRenderer.swift | 104 ++++++++++++++++-- .../Classes/Data/RealmLineDataSet.swift | 41 +++++-- 4 files changed, 172 insertions(+), 33 deletions(-) diff --git a/Charts/Classes/Data/Implementations/Standard/LineChartDataSet.swift b/Charts/Classes/Data/Implementations/Standard/LineChartDataSet.swift index babdafc289..3795908ada 100644 --- a/Charts/Classes/Data/Implementations/Standard/LineChartDataSet.swift +++ b/Charts/Classes/Data/Implementations/Standard/LineChartDataSet.swift @@ -39,6 +39,8 @@ public class LineChartDataSet: LineRadarChartDataSet, ILineChartDataSet // MARK: - Styling functions and accessors + public var mode: LineChartMode = LineChartMode.Linear + private var _cubicIntensity = CGFloat(0.2) /// Intensity for cubic lines (min = 0.05, max = 1) @@ -64,16 +66,36 @@ public class LineChartDataSet: LineRadarChartDataSet, ILineChartDataSet } } - /// If true, cubic lines are drawn instead of linear - public var drawCubicEnabled = false + @available(*, deprecated=1.0, message="Use `mode` instead.") + public var drawCubicEnabled: Bool + { + get + { + return mode == .CubicBezier + } + set + { + mode = newValue ? LineChartMode.CubicBezier : LineChartMode.Linear + } + } - /// - returns: true if drawing cubic lines is enabled, false if not. + @available(*, deprecated=1.0, message="Use `mode` instead.") public var isDrawCubicEnabled: Bool { return drawCubicEnabled } - /// If true, stepped lines are drawn instead of linear - public var drawSteppedEnabled = false - - /// - returns: true if drawing stepped lines is enabled, false if not. + @available(*, deprecated=1.0, message="Use `mode` instead.") + public var drawSteppedEnabled: Bool + { + get + { + return mode == .Stepped + } + set + { + mode = newValue ? LineChartMode.Stepped : LineChartMode.Linear + } + } + + @available(*, deprecated=1.0, message="Use `mode` instead.") public var isDrawSteppedEnabled: Bool { return drawSteppedEnabled } /// The radius of the drawn circles. @@ -167,9 +189,10 @@ public class LineChartDataSet: LineRadarChartDataSet, ILineChartDataSet copy.cubicIntensity = cubicIntensity copy.lineDashPhase = lineDashPhase copy.lineDashLengths = lineDashLengths + copy.lineCapType = lineCapType copy.drawCirclesEnabled = drawCirclesEnabled - copy.drawCubicEnabled = drawCubicEnabled - copy.drawSteppedEnabled = drawSteppedEnabled + copy.drawCircleHoleEnabled = drawCircleHoleEnabled + copy.mode = mode return copy } } diff --git a/Charts/Classes/Data/Interfaces/ILineChartDataSet.swift b/Charts/Classes/Data/Interfaces/ILineChartDataSet.swift index 4a413a760a..38da71b51d 100644 --- a/Charts/Classes/Data/Interfaces/ILineChartDataSet.swift +++ b/Charts/Classes/Data/Interfaces/ILineChartDataSet.swift @@ -14,6 +14,15 @@ import Foundation import CoreGraphics +@objc +public enum LineChartMode: Int +{ + case Linear + case Stepped + case CubicBezier + case HorizontalBezier +} + @objc public protocol ILineChartDataSet: ILineRadarChartDataSet { @@ -21,21 +30,23 @@ public protocol ILineChartDataSet: ILineRadarChartDataSet // MARK: - Styling functions and accessors + var mode: LineChartMode { get set } + /// Intensity for cubic lines (min = 0.05, max = 1) /// /// **default**: 0.2 var cubicIntensity: CGFloat { get set } - /// If true, cubic lines are drawn instead of linear + @available(*, deprecated=1.0, message="Use `mode` instead.") var drawCubicEnabled: Bool { get set } - /// - returns: true if drawing cubic lines is enabled, false if not. + @available(*, deprecated=1.0, message="Use `mode` instead.") var isDrawCubicEnabled: Bool { get } - /// If true, stepped lines are drawn instead of linear + @available(*, deprecated=1.0, message="Use `mode` instead.") var drawSteppedEnabled: Bool { get set } - /// - returns: true if drawing stepped lines is enabled, false if not. + @available(*, deprecated=1.0, message="Use `mode` instead.") var isDrawSteppedEnabled: Bool { get } /// The radius of the drawn circles. diff --git a/Charts/Classes/Renderers/LineChartRenderer.swift b/Charts/Classes/Renderers/LineChartRenderer.swift index 65486f5af3..eec251f35c 100644 --- a/Charts/Classes/Renderers/LineChartRenderer.swift +++ b/Charts/Classes/Renderers/LineChartRenderer.swift @@ -72,19 +72,23 @@ public class LineChartRenderer: LineRadarChartRenderer } // if drawing cubic lines is enabled - if (dataSet.isDrawCubicEnabled) + switch dataSet.mode { - drawCubic(context: context, dataSet: dataSet) - } - else - { // draw normal (straight) lines + case .Linear: fallthrough + case .Stepped: drawLinear(context: context, dataSet: dataSet) + + case .CubicBezier: + drawCubicBezier(context: context, dataSet: dataSet) + + case .HorizontalBezier: + drawHorizontalBezier(context: context, dataSet: dataSet) } CGContextRestoreGState(context) } - public func drawCubic(context context: CGContext, dataSet: ILineChartDataSet) + public func drawCubicBezier(context context: CGContext, dataSet: ILineChartDataSet) { guard let trans = dataProvider?.getTransformer(dataSet.axisDependency), @@ -168,9 +172,87 @@ public class LineChartRenderer: LineRadarChartRenderer curDy = CGFloat(next.value - prev.value) * intensity // the last cubic - CGPathAddCurveToPoint(cubicPath, &valueToPixelMatrix, CGFloat(prev.xIndex) + prevDx, (CGFloat(prev.value) + prevDy) * phaseY, - CGFloat(cur.xIndex) - curDx, - (CGFloat(cur.value) - curDy) * phaseY, CGFloat(cur.xIndex), CGFloat(cur.value) * phaseY) + CGPathAddCurveToPoint(cubicPath, &valueToPixelMatrix, + CGFloat(prev.xIndex) + prevDx, + (CGFloat(prev.value) + prevDy) * phaseY, + CGFloat(cur.xIndex) - curDx, + (CGFloat(cur.value) - curDy) * phaseY, + CGFloat(cur.xIndex), + CGFloat(cur.value) * phaseY) + } + } + + CGContextSaveGState(context) + + if (dataSet.isDrawFilledEnabled) + { + // Copy this path because we make changes to it + let fillPath = CGPathCreateMutableCopy(cubicPath) + + drawCubicFill(context: context, dataSet: dataSet, spline: fillPath!, matrix: valueToPixelMatrix, from: minx, to: size) + } + + CGContextBeginPath(context) + CGContextAddPath(context, cubicPath) + CGContextSetStrokeColorWithColor(context, drawingColor.CGColor) + CGContextStrokePath(context) + + CGContextRestoreGState(context) + } + + public func drawHorizontalBezier(context context: CGContext, dataSet: ILineChartDataSet) + { + guard let + trans = dataProvider?.getTransformer(dataSet.axisDependency), + animator = animator + else { return } + + let entryCount = dataSet.entryCount + + guard let + entryFrom = dataSet.entryForXIndex(self.minX < 0 ? self.minX : 0, rounding: .Down), + entryTo = dataSet.entryForXIndex(self.maxX, rounding: .Up) + else { return } + + let diff = (entryFrom == entryTo) ? 1 : 0 + let minx = max(dataSet.entryIndex(entry: entryFrom) - diff - 1, 0) + let maxx = min(max(minx + 2, dataSet.entryIndex(entry: entryTo) + 1), entryCount) + + let phaseX = animator.phaseX + let phaseY = animator.phaseY + + // get the color that is specified for this position from the DataSet + let drawingColor = dataSet.colors.first! + + // the path for the cubic-spline + let cubicPath = CGPathCreateMutable() + + var valueToPixelMatrix = trans.valueToPixelMatrix + + let size = Int(ceil(CGFloat(maxx - minx) * phaseX + CGFloat(minx))) + + if (size - minx >= 2) + { + var prev: ChartDataEntry! = dataSet.entryForIndex(minx) + var cur: ChartDataEntry! = prev + + if cur == nil { return } + + // let the spline start + CGPathMoveToPoint(cubicPath, &valueToPixelMatrix, CGFloat(cur.xIndex), CGFloat(cur.value) * phaseY) + + for j in minx + 1 ..< min(size, entryCount) + { + prev = cur + cur = dataSet.entryForIndex(j) + + let cpx = CGFloat(prev.xIndex) + CGFloat(cur.xIndex - prev.xIndex) / 2.0 + + CGPathAddCurveToPoint(cubicPath, + &valueToPixelMatrix, + cpx, CGFloat(prev.value) * phaseY, + cpx, CGFloat(cur.value) * phaseY, + CGFloat(cur.xIndex), CGFloat(cur.value) * phaseY) } } @@ -240,7 +322,7 @@ public class LineChartRenderer: LineRadarChartRenderer let valueToPixelMatrix = trans.valueToPixelMatrix let entryCount = dataSet.entryCount - let isDrawSteppedEnabled = dataSet.isDrawSteppedEnabled + let isDrawSteppedEnabled = dataSet.mode == .Stepped let pointsPerEntryPair = isDrawSteppedEnabled ? 4 : 2 let phaseX = animator.phaseX @@ -425,7 +507,7 @@ public class LineChartRenderer: LineRadarChartRenderer { let phaseX = animator?.phaseX ?? 1.0 let phaseY = animator?.phaseY ?? 1.0 - let isDrawSteppedEnabled = dataSet.isDrawSteppedEnabled + let isDrawSteppedEnabled = dataSet.mode == .Stepped var matrix = matrix var e: ChartDataEntry! diff --git a/ChartsRealm/Classes/Data/RealmLineDataSet.swift b/ChartsRealm/Classes/Data/RealmLineDataSet.swift index f0be0688d8..d366ce1a86 100644 --- a/ChartsRealm/Classes/Data/RealmLineDataSet.swift +++ b/ChartsRealm/Classes/Data/RealmLineDataSet.swift @@ -29,6 +29,8 @@ public class RealmLineDataSet: RealmLineRadarDataSet, ILineChartDataSet // MARK: - Styling functions and accessors + public var mode: LineChartMode = LineChartMode.Linear + private var _cubicIntensity = CGFloat(0.2) /// Intensity for cubic lines (min = 0.05, max = 1) @@ -54,16 +56,36 @@ public class RealmLineDataSet: RealmLineRadarDataSet, ILineChartDataSet } } - /// If true, cubic lines are drawn instead of linear - public var drawCubicEnabled = false + @available(*, deprecated=1.0, message="Use `mode` instead.") + public var drawCubicEnabled: Bool + { + get + { + return mode == .CubicBezier + } + set + { + mode = newValue ? LineChartMode.CubicBezier : LineChartMode.Linear + } + } - /// - returns: true if drawing cubic lines is enabled, false if not. + @available(*, deprecated=1.0, message="Use `mode` instead.") public var isDrawCubicEnabled: Bool { return drawCubicEnabled } - /// If true, stepped lines are drawn instead of linear - public var drawSteppedEnabled = false - - /// - returns: true if drawing stepped lines is enabled, false if not. + @available(*, deprecated=1.0, message="Use `mode` instead.") + public var drawSteppedEnabled: Bool + { + get + { + return mode == .Stepped + } + set + { + mode = newValue ? LineChartMode.Stepped : LineChartMode.Linear + } + } + + @available(*, deprecated=1.0, message="Use `mode` instead.") public var isDrawSteppedEnabled: Bool { return drawSteppedEnabled } /// The radius of the drawn circles. @@ -157,9 +179,10 @@ public class RealmLineDataSet: RealmLineRadarDataSet, ILineChartDataSet copy.cubicIntensity = cubicIntensity copy.lineDashPhase = lineDashPhase copy.lineDashLengths = lineDashLengths + copy.lineCapType = lineCapType copy.drawCirclesEnabled = drawCirclesEnabled - copy.drawCubicEnabled = drawCubicEnabled - copy.drawSteppedEnabled = drawSteppedEnabled + copy.drawCircleHoleEnabled = drawCircleHoleEnabled + copy.mode = mode return copy } From a70624386cb8ea28488153f1ea66b793a2f47fca Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 8 Apr 2016 17:30:33 +0300 Subject: [PATCH 2/6] Added horizontal bezier to the demo --- .../Demos/CubicLineChartViewController.m | 23 +++++++++++++++++++ .../Classes/Demos/LineChart1ViewController.m | 12 ++++++++++ .../Classes/Demos/LineChart2ViewController.m | 12 ++++++++++ 3 files changed, 47 insertions(+) diff --git a/ChartsDemo/Classes/Demos/CubicLineChartViewController.m b/ChartsDemo/Classes/Demos/CubicLineChartViewController.m index ce5cd847a7..3a90aaecd0 100644 --- a/ChartsDemo/Classes/Demos/CubicLineChartViewController.m +++ b/ChartsDemo/Classes/Demos/CubicLineChartViewController.m @@ -51,6 +51,8 @@ - (void)viewDidLoad @{@"key": @"toggleFilled", @"label": @"Toggle Filled"}, @{@"key": @"toggleCircles", @"label": @"Toggle Circles"}, @{@"key": @"toggleCubic", @"label": @"Toggle Cubic"}, + @{@"key": @"toggleHorizontalCubic", @"label": @"Toggle Horizontal Cubic"}, + @{@"key": @"toggleStepped", @"label": @"Toggle Stepped"}, @{@"key": @"toggleHighlight", @"label": @"Toggle Highlight"}, @{@"key": @"animateX", @"label": @"Animate X"}, @{@"key": @"animateY", @"label": @"Animate Y"}, @@ -185,6 +187,27 @@ - (void)optionTapped:(NSString *)key return; } + if ([key isEqualToString:@"toggleStepped"]) + { + for (id set in _chartView.data.dataSets) + { + set.drawSteppedEnabled = !set.isDrawSteppedEnabled; + } + + [_chartView setNeedsDisplay]; + } + + if ([key isEqualToString:@"toggleHorizontalCubic"]) + { + for (id set in _chartView.data.dataSets) + { + set.mode = set.mode == LineChartModeCubicBezier ? LineChartModeHorizontalBezier : LineChartModeCubicBezier; + } + + [_chartView setNeedsDisplay]; + return; + } + [super handleOption:key forChartView:_chartView]; } diff --git a/ChartsDemo/Classes/Demos/LineChart1ViewController.m b/ChartsDemo/Classes/Demos/LineChart1ViewController.m index a89de40196..b5a9cb6626 100644 --- a/ChartsDemo/Classes/Demos/LineChart1ViewController.m +++ b/ChartsDemo/Classes/Demos/LineChart1ViewController.m @@ -37,6 +37,7 @@ - (void)viewDidLoad @{@"key": @"toggleFilled", @"label": @"Toggle Filled"}, @{@"key": @"toggleCircles", @"label": @"Toggle Circles"}, @{@"key": @"toggleCubic", @"label": @"Toggle Cubic"}, + @{@"key": @"toggleHorizontalCubic", @"label": @"Toggle Horizontal Cubic"}, @{@"key": @"toggleStepped", @"label": @"Toggle Stepped"}, @{@"key": @"toggleHighlight", @"label": @"Toggle Highlight"}, @{@"key": @"animateX", @"label": @"Animate X"}, @@ -220,6 +221,17 @@ - (void)optionTapped:(NSString *)key [_chartView setNeedsDisplay]; } + if ([key isEqualToString:@"toggleHorizontalCubic"]) + { + for (id set in _chartView.data.dataSets) + { + set.mode = set.mode == LineChartModeCubicBezier ? LineChartModeHorizontalBezier : LineChartModeCubicBezier; + } + + [_chartView setNeedsDisplay]; + return; + } + [super handleOption:key forChartView:_chartView]; } diff --git a/ChartsDemo/Classes/Demos/LineChart2ViewController.m b/ChartsDemo/Classes/Demos/LineChart2ViewController.m index 9085ca9b32..b7f96e306c 100644 --- a/ChartsDemo/Classes/Demos/LineChart2ViewController.m +++ b/ChartsDemo/Classes/Demos/LineChart2ViewController.m @@ -37,6 +37,7 @@ - (void)viewDidLoad @{@"key": @"toggleFilled", @"label": @"Toggle Filled"}, @{@"key": @"toggleCircles", @"label": @"Toggle Circles"}, @{@"key": @"toggleCubic", @"label": @"Toggle Cubic"}, + @{@"key": @"toggleHorizontalCubic", @"label": @"Toggle Horizontal Cubic"}, @{@"key": @"toggleStepped", @"label": @"Toggle Stepped"}, @{@"key": @"toggleHighlight", @"label": @"Toggle Highlight"}, @{@"key": @"animateX", @"label": @"Animate X"}, @@ -216,6 +217,17 @@ - (void)optionTapped:(NSString *)key [_chartView setNeedsDisplay]; } + if ([key isEqualToString:@"toggleHorizontalCubic"]) + { + for (id set in _chartView.data.dataSets) + { + set.mode = set.mode == LineChartModeCubicBezier ? LineChartModeHorizontalBezier : LineChartModeCubicBezier; + } + + [_chartView setNeedsDisplay]; + return; + } + [super handleOption:key forChartView:_chartView]; } From 0069c410492ac23248c854fadfb9b1ffb8419361 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 8 Apr 2016 17:53:30 +0300 Subject: [PATCH 3/6] Make yVals settable --- .../Implementations/Standard/ChartDataSet.swift | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Charts/Classes/Data/Implementations/Standard/ChartDataSet.swift b/Charts/Classes/Data/Implementations/Standard/ChartDataSet.swift index 4fd28aa2a7..ec199fc00c 100644 --- a/Charts/Classes/Data/Implementations/Standard/ChartDataSet.swift +++ b/Charts/Classes/Data/Implementations/Standard/ChartDataSet.swift @@ -64,7 +64,19 @@ public class ChartDataSet: ChartBaseDataSet /// the last end value used for calcMinMax internal var _lastEnd: Int = 0 - public var yVals: [ChartDataEntry] { return _yVals } + /// the array of y-values that this DataSet represents. + public var yVals: [ChartDataEntry] + { + get + { + return _yVals + } + set + { + _yVals = newValue + notifyDataSetChanged() + } + } /// Use this method to tell the data set that the underlying data has changed public override func notifyDataSetChanged() From 299eaf06b26deda9cc16ba6e7054e0e1c3c80bc7 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 8 Apr 2016 17:30:49 +0300 Subject: [PATCH 4/6] Made these line demos reuse the dataset and keep styling --- .../Demos/CubicLineChartViewController.m | 48 +++++++----- .../Classes/Demos/LineChart1ViewController.m | 72 +++++++++-------- .../Classes/Demos/LineChart2ViewController.m | 77 +++++++++++-------- 3 files changed, 115 insertions(+), 82 deletions(-) diff --git a/ChartsDemo/Classes/Demos/CubicLineChartViewController.m b/ChartsDemo/Classes/Demos/CubicLineChartViewController.m index 3a90aaecd0..a802a5f8e6 100644 --- a/ChartsDemo/Classes/Demos/CubicLineChartViewController.m +++ b/ChartsDemo/Classes/Demos/CubicLineChartViewController.m @@ -131,25 +131,35 @@ - (void)setDataCount:(int)count range:(double)range [yVals1 addObject:[[ChartDataEntry alloc] initWithValue:val xIndex:i]]; } - LineChartDataSet *set1 = [[LineChartDataSet alloc] initWithYVals:yVals1 label:@"DataSet 1"]; - set1.drawCubicEnabled = YES; - set1.cubicIntensity = 0.2; - set1.drawCirclesEnabled = NO; - set1.lineWidth = 1.8; - set1.circleRadius = 4.0; - [set1 setCircleColor:UIColor.whiteColor]; - set1.highlightColor = [UIColor colorWithRed:244/255.f green:117/255.f blue:117/255.f alpha:1.f]; - [set1 setColor:UIColor.whiteColor]; - set1.fillColor = UIColor.whiteColor; - set1.fillAlpha = 1.f; - set1.drawHorizontalHighlightIndicatorEnabled = NO; - set1.fillFormatter = [[CubicLineSampleFillFormatter alloc] init]; - - LineChartData *data = [[LineChartData alloc] initWithXVals:xVals dataSet:set1]; - [data setValueFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:9.f]]; - [data setDrawValues:NO]; - - _chartView.data = data; + LineChartDataSet *set1 = nil; + if (_chartView.data.dataSetCount > 0) + { + set1 = (LineChartDataSet *)_chartView.data.dataSets[0]; + set1.yVals = yVals1; + [_chartView notifyDataSetChanged]; + } + else + { + set1 = [[LineChartDataSet alloc] initWithYVals:yVals1 label:@"DataSet 1"]; + set1.drawCubicEnabled = YES; + set1.cubicIntensity = 0.2; + set1.drawCirclesEnabled = NO; + set1.lineWidth = 1.8; + set1.circleRadius = 4.0; + [set1 setCircleColor:UIColor.whiteColor]; + set1.highlightColor = [UIColor colorWithRed:244/255.f green:117/255.f blue:117/255.f alpha:1.f]; + [set1 setColor:UIColor.whiteColor]; + set1.fillColor = UIColor.whiteColor; + set1.fillAlpha = 1.f; + set1.drawHorizontalHighlightIndicatorEnabled = NO; + set1.fillFormatter = [[CubicLineSampleFillFormatter alloc] init]; + + LineChartData *data = [[LineChartData alloc] initWithXVals:xVals dataSet:set1]; + [data setValueFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:9.f]]; + [data setDrawValues:NO]; + + _chartView.data = data; + } } - (void)optionTapped:(NSString *)key diff --git a/ChartsDemo/Classes/Demos/LineChart1ViewController.m b/ChartsDemo/Classes/Demos/LineChart1ViewController.m index b5a9cb6626..3f49281710 100644 --- a/ChartsDemo/Classes/Demos/LineChart1ViewController.m +++ b/ChartsDemo/Classes/Demos/LineChart1ViewController.m @@ -143,37 +143,47 @@ - (void)setDataCount:(int)count range:(double)range [yVals addObject:[[ChartDataEntry alloc] initWithValue:val xIndex:i]]; } - LineChartDataSet *set1 = [[LineChartDataSet alloc] initWithYVals:yVals label:@"DataSet 1"]; - - set1.lineDashLengths = @[@5.f, @2.5f]; - set1.highlightLineDashLengths = @[@5.f, @2.5f]; - [set1 setColor:UIColor.blackColor]; - [set1 setCircleColor:UIColor.blackColor]; - set1.lineWidth = 1.0; - set1.circleRadius = 3.0; - set1.drawCircleHoleEnabled = NO; - set1.valueFont = [UIFont systemFontOfSize:9.f]; - //set1.fillAlpha = 65/255.0; - //set1.fillColor = UIColor.blackColor; - - NSArray *gradientColors = @[ - (id)[ChartColorTemplates colorFromString:@"#00ff0000"].CGColor, - (id)[ChartColorTemplates colorFromString:@"#ffff0000"].CGColor - ]; - CGGradientRef gradient = CGGradientCreateWithColors(nil, (CFArrayRef)gradientColors, nil); - - set1.fillAlpha = 1.f; - set1.fill = [ChartFill fillWithLinearGradient:gradient angle:90.f]; - set1.drawFilledEnabled = YES; - - CGGradientRelease(gradient); - - NSMutableArray *dataSets = [[NSMutableArray alloc] init]; - [dataSets addObject:set1]; - - LineChartData *data = [[LineChartData alloc] initWithXVals:xVals dataSets:dataSets]; - - _chartView.data = data; + LineChartDataSet *set1 = nil; + if (_chartView.data.dataSetCount > 0) + { + set1 = (LineChartDataSet *)_chartView.data.dataSets[0]; + set1.yVals = yVals; + [_chartView notifyDataSetChanged]; + } + else + { + set1 = [[LineChartDataSet alloc] initWithYVals:yVals label:@"DataSet 1"]; + + set1.lineDashLengths = @[@5.f, @2.5f]; + set1.highlightLineDashLengths = @[@5.f, @2.5f]; + [set1 setColor:UIColor.blackColor]; + [set1 setCircleColor:UIColor.blackColor]; + set1.lineWidth = 1.0; + set1.circleRadius = 3.0; + set1.drawCircleHoleEnabled = NO; + set1.valueFont = [UIFont systemFontOfSize:9.f]; + //set1.fillAlpha = 65/255.0; + //set1.fillColor = UIColor.blackColor; + + NSArray *gradientColors = @[ + (id)[ChartColorTemplates colorFromString:@"#00ff0000"].CGColor, + (id)[ChartColorTemplates colorFromString:@"#ffff0000"].CGColor + ]; + CGGradientRef gradient = CGGradientCreateWithColors(nil, (CFArrayRef)gradientColors, nil); + + set1.fillAlpha = 1.f; + set1.fill = [ChartFill fillWithLinearGradient:gradient angle:90.f]; + set1.drawFilledEnabled = YES; + + CGGradientRelease(gradient); + + NSMutableArray *dataSets = [[NSMutableArray alloc] init]; + [dataSets addObject:set1]; + + LineChartData *data = [[LineChartData alloc] initWithXVals:xVals dataSets:dataSets]; + + _chartView.data = data; + } } - (void)optionTapped:(NSString *)key diff --git a/ChartsDemo/Classes/Demos/LineChart2ViewController.m b/ChartsDemo/Classes/Demos/LineChart2ViewController.m index b7f96e306c..02d16b5582 100644 --- a/ChartsDemo/Classes/Demos/LineChart2ViewController.m +++ b/ChartsDemo/Classes/Demos/LineChart2ViewController.m @@ -121,26 +121,15 @@ - (void)setDataCount:(int)count range:(double)range [xVals addObject:[@(i) stringValue]]; } - NSMutableArray *yVals = [[NSMutableArray alloc] init]; + NSMutableArray *yVals1 = [[NSMutableArray alloc] init]; for (int i = 0; i < count; i++) { double mult = range / 2.0; double val = (double) (arc4random_uniform(mult)) + 50; - [yVals addObject:[[ChartDataEntry alloc] initWithValue:val xIndex:i]]; + [yVals1 addObject:[[ChartDataEntry alloc] initWithValue:val xIndex:i]]; } - LineChartDataSet *set1 = [[LineChartDataSet alloc] initWithYVals:yVals label:@"DataSet 1"]; - set1.axisDependency = AxisDependencyLeft; - [set1 setColor:[UIColor colorWithRed:51/255.f green:181/255.f blue:229/255.f alpha:1.f]]; - [set1 setCircleColor:UIColor.whiteColor]; - set1.lineWidth = 2.0; - set1.circleRadius = 3.0; - set1.fillAlpha = 65/255.0; - set1.fillColor = [UIColor colorWithRed:51/255.f green:181/255.f blue:229/255.f alpha:1.f]; - set1.highlightColor = [UIColor colorWithRed:244/255.f green:117/255.f blue:117/255.f alpha:1.f]; - set1.drawCircleHoleEnabled = NO; - NSMutableArray *yVals2 = [[NSMutableArray alloc] init]; for (int i = 0; i < count; i++) @@ -150,26 +139,50 @@ - (void)setDataCount:(int)count range:(double)range [yVals2 addObject:[[ChartDataEntry alloc] initWithValue:val xIndex:i]]; } - LineChartDataSet *set2 = [[LineChartDataSet alloc] initWithYVals:yVals2 label:@"DataSet 2"]; - set2.axisDependency = AxisDependencyRight; - [set2 setColor:UIColor.redColor]; - [set2 setCircleColor:UIColor.whiteColor]; - set2.lineWidth = 2.0; - set2.circleRadius = 3.0; - set2.fillAlpha = 65/255.0; - set2.fillColor = UIColor.redColor; - set2.highlightColor = [UIColor colorWithRed:244/255.f green:117/255.f blue:117/255.f alpha:1.f]; - set2.drawCircleHoleEnabled = NO; - - NSMutableArray *dataSets = [[NSMutableArray alloc] init]; - [dataSets addObject:set2]; - [dataSets addObject:set1]; - - LineChartData *data = [[LineChartData alloc] initWithXVals:xVals dataSets:dataSets]; - [data setValueTextColor:UIColor.whiteColor]; - [data setValueFont:[UIFont systemFontOfSize:9.f]]; + LineChartDataSet *set1 = nil, *set2 = nil; - _chartView.data = data; + if (_chartView.data.dataSetCount > 0) + { + set1 = (LineChartDataSet *)_chartView.data.dataSets[0]; + set2 = (LineChartDataSet *)_chartView.data.dataSets[1]; + set1.yVals = yVals1; + set2.yVals = yVals2; + [_chartView notifyDataSetChanged]; + } + else + { + set1 = [[LineChartDataSet alloc] initWithYVals:yVals1 label:@"DataSet 1"]; + set1.axisDependency = AxisDependencyLeft; + [set1 setColor:[UIColor colorWithRed:51/255.f green:181/255.f blue:229/255.f alpha:1.f]]; + [set1 setCircleColor:UIColor.whiteColor]; + set1.lineWidth = 2.0; + set1.circleRadius = 3.0; + set1.fillAlpha = 65/255.0; + set1.fillColor = [UIColor colorWithRed:51/255.f green:181/255.f blue:229/255.f alpha:1.f]; + set1.highlightColor = [UIColor colorWithRed:244/255.f green:117/255.f blue:117/255.f alpha:1.f]; + set1.drawCircleHoleEnabled = NO; + + set2 = [[LineChartDataSet alloc] initWithYVals:yVals2 label:@"DataSet 2"]; + set2.axisDependency = AxisDependencyRight; + [set2 setColor:UIColor.redColor]; + [set2 setCircleColor:UIColor.whiteColor]; + set2.lineWidth = 2.0; + set2.circleRadius = 3.0; + set2.fillAlpha = 65/255.0; + set2.fillColor = UIColor.redColor; + set2.highlightColor = [UIColor colorWithRed:244/255.f green:117/255.f blue:117/255.f alpha:1.f]; + set2.drawCircleHoleEnabled = NO; + + NSMutableArray *dataSets = [[NSMutableArray alloc] init]; + [dataSets addObject:set2]; + [dataSets addObject:set1]; + + LineChartData *data = [[LineChartData alloc] initWithXVals:xVals dataSets:dataSets]; + [data setValueTextColor:UIColor.whiteColor]; + [data setValueFont:[UIFont systemFontOfSize:9.f]]; + + _chartView.data = data; + } } - (void)optionTapped:(NSString *)key From 3883db7d9913bd5bcaeddd7f9e517409646bac3e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 8 Apr 2016 17:55:21 +0300 Subject: [PATCH 5/6] Docs --- .../Data/Implementations/Standard/LineChartDataSet.swift | 3 +++ Charts/Classes/Data/Interfaces/ILineChartDataSet.swift | 3 +++ ChartsRealm/Classes/Data/RealmLineDataSet.swift | 3 +++ 3 files changed, 9 insertions(+) diff --git a/Charts/Classes/Data/Implementations/Standard/LineChartDataSet.swift b/Charts/Classes/Data/Implementations/Standard/LineChartDataSet.swift index 3795908ada..5270d57241 100644 --- a/Charts/Classes/Data/Implementations/Standard/LineChartDataSet.swift +++ b/Charts/Classes/Data/Implementations/Standard/LineChartDataSet.swift @@ -39,6 +39,9 @@ public class LineChartDataSet: LineRadarChartDataSet, ILineChartDataSet // MARK: - Styling functions and accessors + /// The drawing mode for this line dataset + /// + /// **default**: Linear public var mode: LineChartMode = LineChartMode.Linear private var _cubicIntensity = CGFloat(0.2) diff --git a/Charts/Classes/Data/Interfaces/ILineChartDataSet.swift b/Charts/Classes/Data/Interfaces/ILineChartDataSet.swift index 38da71b51d..3f33357e8f 100644 --- a/Charts/Classes/Data/Interfaces/ILineChartDataSet.swift +++ b/Charts/Classes/Data/Interfaces/ILineChartDataSet.swift @@ -30,6 +30,9 @@ public protocol ILineChartDataSet: ILineRadarChartDataSet // MARK: - Styling functions and accessors + /// The drawing mode for this line dataset + /// + /// **default**: Linear var mode: LineChartMode { get set } /// Intensity for cubic lines (min = 0.05, max = 1) diff --git a/ChartsRealm/Classes/Data/RealmLineDataSet.swift b/ChartsRealm/Classes/Data/RealmLineDataSet.swift index d366ce1a86..94d01fbb9a 100644 --- a/ChartsRealm/Classes/Data/RealmLineDataSet.swift +++ b/ChartsRealm/Classes/Data/RealmLineDataSet.swift @@ -29,6 +29,9 @@ public class RealmLineDataSet: RealmLineRadarDataSet, ILineChartDataSet // MARK: - Styling functions and accessors + /// The drawing mode for this line dataset + /// + /// **default**: Linear public var mode: LineChartMode = LineChartMode.Linear private var _cubicIntensity = CGFloat(0.2) From 7b5462ee6b1401234f446831d966be9fd4842a14 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 9 Apr 2016 22:07:58 +0300 Subject: [PATCH 6/6] DRYed some code here... --- .../Classes/Renderers/LineChartRenderer.swift | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/Charts/Classes/Renderers/LineChartRenderer.swift b/Charts/Classes/Renderers/LineChartRenderer.swift index eec251f35c..106f45c7c6 100644 --- a/Charts/Classes/Renderers/LineChartRenderer.swift +++ b/Charts/Classes/Renderers/LineChartRenderer.swift @@ -138,12 +138,12 @@ public class LineChartRenderer: LineRadarChartRenderer // let the spline start CGPathMoveToPoint(cubicPath, &valueToPixelMatrix, CGFloat(cur.xIndex), CGFloat(cur.value) * phaseY) - for j in minx + 1 ..< min(size, entryCount - 1) + for j in minx + 1 ..< min(size, entryCount) { prevPrev = prev prev = cur cur = next - next = dataSet.entryForIndex(j + 1) + next = entryCount > j + 1 ? dataSet.entryForIndex(j + 1) : cur if next == nil { break } @@ -152,26 +152,6 @@ public class LineChartRenderer: LineRadarChartRenderer curDx = CGFloat(next.xIndex - prev.xIndex) * intensity curDy = CGFloat(next.value - prev.value) * intensity - CGPathAddCurveToPoint(cubicPath, &valueToPixelMatrix, CGFloat(prev.xIndex) + prevDx, (CGFloat(prev.value) + prevDy) * phaseY, - CGFloat(cur.xIndex) - curDx, - (CGFloat(cur.value) - curDy) * phaseY, CGFloat(cur.xIndex), CGFloat(cur.value) * phaseY) - } - - if (size > entryCount - 1) - { - prevPrev = dataSet.entryForIndex(entryCount - (entryCount >= 3 ? 3 : 2)) - prev = dataSet.entryForIndex(entryCount - 2) - cur = dataSet.entryForIndex(entryCount - 1) - next = cur - - if prevPrev == nil || prev == nil || cur == nil { return } - - prevDx = CGFloat(cur.xIndex - prevPrev.xIndex) * intensity - prevDy = CGFloat(cur.value - prevPrev.value) * intensity - curDx = CGFloat(next.xIndex - prev.xIndex) * intensity - curDy = CGFloat(next.value - prev.value) * intensity - - // the last cubic CGPathAddCurveToPoint(cubicPath, &valueToPixelMatrix, CGFloat(prev.xIndex) + prevDx, (CGFloat(prev.value) + prevDy) * phaseY,