Compare commits

...

33 Commits

Author SHA1 Message Date
terryworona e7c84aa4de Fixed #192 2015-12-16 20:53:31 -08:00
terryworona b7f7324d96 updated pod spec and change log 2015-12-04 17:38:38 -08:00
terryworona 78b2aa1964 Fixed up gradient bars 2015-12-04 15:22:59 -08:00
terryworona d9ab659422 Updated readme 2015-12-04 15:14:26 -08:00
terryworona 71df60f9a3 added bar chart gradient support 2015-12-04 14:30:47 -08:00
terryworona 728b9420a9 Fixed crasher 2015-12-04 13:04:12 -08:00
terryworona fe42e4f61d PR cleanup 2015-12-04 13:02:16 -08:00
terryworona 45cf0d66ba Merge with master 2015-12-03 17:48:25 -08:00
Terry Worona 5aecb0ba92 Fixed readme typo 2015-11-22 19:13:52 -08:00
Terry Worona 6f14f4099f Updated pod spec and change log 2015-11-22 19:01:36 -08:00
Terry Worona 9fa369ce8d Updated pod spec 2015-11-22 18:59:49 -08:00
Terry Worona 9828034f6b Fixed #94 2015-11-22 18:52:54 -08:00
Terry Worona 58f57fcef2 new version 2015-11-22 13:31:25 -08:00
Terry Worona 78390657d7 Added iPhone 6 support for demo app 2015-11-22 13:17:58 -08:00
Terry Worona 87a5de93af Updated readme 2015-11-22 13:09:50 -08:00
Terry Worona edfca9b780 Moving customization readme 2015-11-22 12:50:02 -08:00
Terry Worona 14c7aa7c98 Updated change log 2015-11-22 12:47:05 -08:00
terryworona b928cd1849 Fixed #159 for real this time 2015-11-20 18:13:19 -08:00
terryworona 2d6c6e291d More cleanup 2015-11-20 17:57:22 -08:00
terryworona 5addeeae83 Spacing 2015-11-20 16:58:30 -08:00
terryworona ec14cc002e Reverted #153 (won't enhance) 2015-11-20 16:47:32 -08:00
terryworona e3174efa9e Fixed #159 2015-11-20 16:08:56 -08:00
terryworona 4a1380668e Enhancement #153 2015-11-20 15:10:52 -08:00
terryworona 3752b7d598 Hide vertical selection when touches begin. 2015-11-19 09:51:26 -08:00
terryworona e1d10ffb7e Updated readme for 185 2015-11-18 17:28:07 -08:00
terryworona f2e5641d58 Fixed #185 2015-11-18 17:23:04 -08:00
terryworona b0c68377a3 Fixed #146 2015-11-18 15:32:01 -08:00
terryworona d3cb39b566 Updated project for iOS 9 support 2015-11-18 14:35:32 -08:00
terryworona 99f727c0d6 updated changelog and pod spec 2015-09-18 11:44:35 -07:00
terryworona b6bc9c29ca readme and comment 2015-09-18 11:41:05 -07:00
terryworona 124eabe98c Merge pull request #188 from andrewloyola/line-chart-touch-ignore
Delegate call to ignore touches on selected lines
2015-09-18 11:30:20 -07:00
Andrew Loyola 1f0f3351c3 Delegate call do ignore touches on selected lines
If you want to display more lines than are touchable, you can use this to ignore certain line indices
2015-09-18 11:20:50 -04:00
Ben Norris 69ce275d1a Adds support for gradients to line charts 2015-06-17 13:55:19 -06:00
17 changed files with 873 additions and 267 deletions
+49 -2
View File
@@ -1,8 +1,54 @@
# Change Log
## [Unreleased](https://github.com/Jawbone/JBChartView/tree/HEAD)
## [v2.9.0](https://github.com/Jawbone/JBChartView/tree/v2.9.0) (2015-12-04)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.19...v2.9.0)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.14...HEAD)
## [v2.8.19](https://github.com/Jawbone/JBChartView/tree/v2.8.19) (2015-11-23)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.18...v2.8.19)
**Fixed bugs:**
- Straight lines [\#94](https://github.com/Jawbone/JBChartView/issues/94)
## [v2.8.18](https://github.com/Jawbone/JBChartView/tree/v2.8.18) (2015-11-22)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.17...v2.8.18)
**Implemented enhancements:**
- Vertical values should be supplied by the DataSource delegate for LineCharts [\#180](https://github.com/Jawbone/JBChartView/issues/180)
- JBLineChartDotsView reloadData performance issues [\#179](https://github.com/Jawbone/JBChartView/issues/179)
## [v2.8.17](https://github.com/Jawbone/JBChartView/tree/v2.8.17) (2015-11-21)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.16...v2.8.17)
**Implemented enhancements:**
- Disabling/Enabling certain functionality: line chart selection and x-axis values [\#185](https://github.com/Jawbone/JBChartView/issues/185)
- Add ability to set selection permanently. [\#153](https://github.com/Jawbone/JBChartView/issues/153)
- The line fill color doesn't match the bottom of the drawn line [\#146](https://github.com/Jawbone/JBChartView/issues/146)
**Fixed bugs:**
- Bug when quickly tapping a line chart in two different places [\#159](https://github.com/Jawbone/JBChartView/issues/159)
**Closed issues:**
- Show dot only on vertical line selection [\#190](https://github.com/Jawbone/JBChartView/issues/190)
- Needs to support negative values [\#189](https://github.com/Jawbone/JBChartView/issues/189)
## [v2.8.16](https://github.com/Jawbone/JBChartView/tree/v2.8.16) (2015-09-18)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.15...v2.8.16)
**Closed issues:**
- Partially filled bar [\#186](https://github.com/Jawbone/JBChartView/issues/186)
**Merged pull requests:**
- Delegate call to ignore touches on selected lines [\#188](https://github.com/Jawbone/JBChartView/pull/188) ([andrewloyola](https://github.com/andrewloyola))
## [v2.8.15](https://github.com/Jawbone/JBChartView/tree/v2.8.15) (2015-08-12)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.14...v2.8.15)
**Implemented enhancements:**
@@ -26,6 +72,7 @@
**Merged pull requests:**
- Return the available height instead of 0 [\#183](https://github.com/Jawbone/JBChartView/pull/183) ([0xPr0xy](https://github.com/0xPr0xy))
- Adds support for gradients to line charts [\#175](https://github.com/Jawbone/JBChartView/pull/175) ([benjaminsnorris](https://github.com/benjaminsnorris))
## [v2.8.14](https://github.com/Jawbone/JBChartView/tree/v2.8.14) (2015-04-30)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.13...v2.8.14)
+14 -1
View File
@@ -80,7 +80,7 @@
* If you already implement barChartView:barViewAtIndex: delegate - this method has no effect.
* If a custom UIView isn't supplied, a flat bar will be made automatically (default color black).
*
* Default: if none specified - calls barChartView:barViewAtIndex:.
* Default: black color.
*
* @param barChartView The bar chart object requesting this information.
* @param index The 0-based index of a given bar (left to right, x-axis).
@@ -89,6 +89,19 @@
*/
- (UIColor *)barChartView:(JBBarChartView *)barChartView colorForBarViewAtIndex:(NSUInteger)index;
/**
* If you already implement barChartView:barViewAtIndex: delegate - this method has no effect.
* If a custom UIView isn't supplied and barChartView:colorForBarViewAtIndex: isn't implemented, then
* a gradient layer may be supplied to be used across all bars within the chart.
*
* Default: black color.
*
* @param barChartView The bar chart object requesting this information.
*
* @return The gradient layer to be used as a mask over all bars within the chart.
*/
- (CAGradientLayer *)barGradientForBarChartView:(JBBarChartView *)barChartView;
/**
* The selection color to be overlayed on a bar during touch events.
* The color is automatically faded to transparent (vertically). The property showsVerticalSelection
+174 -51
View File
@@ -25,7 +25,27 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
@end
@interface JBBarChartView ()
@protocol JBGradientBarViewDelegate;
@interface JBGradientBarView: UIView
@property (nonatomic, strong) CAGradientLayer *gradientLayer;
@property (nonatomic, weak) id<JBGradientBarViewDelegate> delegate;
// Initialization
- (void)construct;
@end
@protocol JBGradientBarViewDelegate <NSObject>
@optional
- (CGRect)chartViewBoundsForGradientBarView:(JBGradientBarView *)gradientBarView;
@end
@interface JBBarChartView () <JBGradientBarViewDelegate>
@property (nonatomic, strong) NSDictionary *chartDataDictionary; // key = column, value = height
@property (nonatomic, strong) NSArray *barViews;
@@ -178,36 +198,49 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
NSMutableArray *mutableCachedBarViewHeights = [NSMutableArray array];
for (NSNumber *key in [[self.chartDataDictionary allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
UIView *barView = nil; // since all bars are visible at once, no need to cache this view
if ([self.dataSource respondsToSelector:@selector(barChartView:barViewAtIndex:)])
{
barView = [self.dataSource barChartView:self barViewAtIndex:index];
NSAssert(barView != nil, @"JBBarChartView // datasource function - (UIView *)barChartView:(JBBarChartView *)barChartView barViewAtIndex:(NSUInteger)index must return a non-nil UIView subclass");
}
else
{
barView = [[UIView alloc] init];
UIColor *backgroundColor = nil;
if ([self.delegate respondsToSelector:@selector(barChartView:colorForBarViewAtIndex:)])
{
backgroundColor = [self.delegate barChartView:self colorForBarViewAtIndex:index];
NSAssert(backgroundColor != nil, @"JBBarChartView // delegate function - (UIColor *)barChartView:(JBBarChartView *)barChartView colorForBarViewAtIndex:(NSUInteger)index must return a non-nil UIColor");
}
else
{
backgroundColor = kJBBarChartViewDefaultBarColor;
}
barView.backgroundColor = backgroundColor;
}
UIView *barView = nil;
{
// Custom bar
if ([self.dataSource respondsToSelector:@selector(barChartView:barViewAtIndex:)])
{
UIView *customBarView = [self.dataSource barChartView:self barViewAtIndex:index];
if (customBarView != nil)
{
barView = customBarView;
}
}
// Color bar
if ([self.delegate respondsToSelector:@selector(barChartView:colorForBarViewAtIndex:)] && barView == nil)
{
UIColor *backgroundColor = [self.delegate barChartView:self colorForBarViewAtIndex:index];
if (backgroundColor != nil)
{
barView = [[UIView alloc] init];
barView.backgroundColor = backgroundColor;
}
}
// Gradient
if ([self.delegate respondsToSelector:@selector(barGradientForBarChartView:)] && barView == nil)
{
CAGradientLayer *gradientLayer = [self.delegate barGradientForBarChartView:self];
if (gradientLayer != nil)
{
barView = [[JBGradientBarView alloc] init];
((JBGradientBarView *)barView).delegate = self;
((JBGradientBarView *)barView).gradientLayer = gradientLayer;
}
}
// Default
if (barView == nil)
{
barView = [[UIView alloc] init];
barView.backgroundColor = kJBBarChartViewDefaultBarColor;
}
}
barView.tag = index;
CGFloat height = [self normalizedHeightForRawHeight:[self.chartDataDictionary objectForKey:key]];
barView.frame = CGRectMake(xOffset, self.bounds.size.height - height - self.footerView.frame.size.height, [self barWidth], height);
[mutableBarViews addObject:barView];
[mutableCachedBarViewHeights addObject:[NSNumber numberWithFloat:height]];
// Add new bar
if (self.footerView)
@@ -218,7 +251,12 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
{
[self addSubview:barView];
}
CGFloat height = [self normalizedHeightForRawHeight:[self.chartDataDictionary objectForKey:key]];
barView.frame = CGRectMake(xOffset, self.bounds.size.height - height - self.footerView.frame.size.height, [self barWidth], height);
[mutableBarViews addObject:barView];
[mutableCachedBarViewHeights addObject:[NSNumber numberWithFloat:height]];
xOffset += ([self barWidth] + self.barPadding);
index++;
}
@@ -394,27 +432,39 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
{
if (animated)
{
NSUInteger index = 0;
dispatch_block_t animationCompletionBlock = ^{
if (callbackCopy)
{
callbackCopy();
}
};
NSUInteger animationDelayIndex = 0;
for (UIView *barView in self.barViews)
{
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:(kJBBarChartViewStateAnimationDuration * 0.5) * index options:UIViewAnimationOptionBeginFromCurrentState animations:^{
updateBarView(barView, YES);
} completion:^(BOOL finished) {
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
updateBarView(barView, NO);
} completion:^(BOOL lastBarFinished) {
if ((NSUInteger)barView.tag == [self.barViews count] - 1)
{
if (callbackCopy)
{
callbackCopy();
}
}
}];
}];
index++;
}
}
BOOL lastIndex = ((NSUInteger)barView.tag == [self.barViews count] - 1);
if ([[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue] > [self minimumValue])
{
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:(kJBBarChartViewStateAnimationDuration * 0.5) * animationDelayIndex options:UIViewAnimationOptionBeginFromCurrentState animations:^{
updateBarView(barView, YES);
} completion:^(BOOL finished) {
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
updateBarView(barView, NO);
} completion:^(BOOL lastBarFinished) {
if (lastIndex)
{
animationCompletionBlock();
}
}];
}];
animationDelayIndex++;
}
else if (lastIndex)
{
animationCompletionBlock();
}
}
}
else
{
for (UIView *barView in self.barViews)
@@ -561,7 +611,7 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
{
return;
}
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
UIView *barView = [self barViewForForPoint:touchPoint];
@@ -624,6 +674,7 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self setVerticalSelectionViewVisible:NO animated:NO];
[self touchesBeganOrMovedWithTouches:touches];
}
@@ -642,4 +693,76 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
[self touchesEndedOrCancelledWithTouches:touches];
}
#pragma mark - JBGradientBarViewDelegate
- (CGRect)chartViewBoundsForGradientBarView:(JBGradientBarView *)gradientBarView
{
return self.bounds;
}
@end
@implementation JBGradientBarView
#pragma mark - Alloc/Init
- (instancetype)init
{
self = [super init];
if (self)
{
[self construct];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self construct];
}
return self;
}
#pragma mark - Setters
- (void)setGradientLayer:(CAGradientLayer *)gradientLayer
{
if (_gradientLayer != nil)
{
[_gradientLayer removeFromSuperlayer];
_gradientLayer = nil;
}
_gradientLayer = gradientLayer;
_gradientLayer.masksToBounds = YES;
[self.layer insertSublayer:_gradientLayer atIndex:0];
}
#pragma mark - Construction
- (void)construct
{
self.clipsToBounds = YES;
}
#pragma mark - Setters
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
if ([self.delegate respondsToSelector:@selector(chartViewBoundsForGradientBarView:)])
{
_gradientLayer.frame = [self.delegate chartViewBoundsForGradientBarView:self]; // gradient is as large as the chart
_gradientLayer.frame = CGRectOffset(_gradientLayer.frame, -CGRectGetMinX(frame), 0);
}
else
{
_gradientLayer.frame = self.bounds;
}
}
@end
+103 -2
View File
@@ -24,6 +24,20 @@ typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
JBLineChartViewLineStyleDashed
};
/**
* Current support for two line color styles: solid (default) and gradient.
*/
typedef NS_ENUM(NSInteger, JBLineChartViewLineColorStyle){
/**
* Solid line and fill color.
*/
JBLineChartViewLineColorStyleSolid,
/**
* Gradient line and fill color.
*/
JBLineChartViewLineColorStyleGradient
};
@protocol JBLineChartViewDataSource <JBChartViewDataSource>
@required
@@ -75,6 +89,20 @@ typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
*/
- (BOOL)lineChartView:(JBLineChartView *)lineChartView smoothLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the opacity value to be used for dimming the line & fill during selection events.
* This value is applied to the line or fill's opacity anytime it's not selected (but another line is).
* This applies to both solid and gradient line styles.
*
* Default: 0.2.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return A value between 0.0 and 1.0 (will be clamped accordingly).
*/
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns a (custom) UIView instance representing a dot (x,y point) within the chart.
* For this value to apply, showsDotsForLineAtLineIndex: must return YES for the line at lineIndex.
@@ -132,8 +160,8 @@ typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
* Occurs whenever there is a touch gesture on the chart (chart must be expanded).
* The horizontal index is the closest index to the touch point & is clamped to it's max/min value if it moves outside of the view's bounds.
* The lineIndex remains constant until the line is deselected and will be highlighted using the (optional) selectionColorForLineAtLineIndex: protocol.
* Futhermore, all other lines that aren't selected will be dimmed to 20%% opacity throughout the duration of the touch/move. Any dotted line that isn't the
* primary selection will have it's dots dimmed to hidden (to avoid transparency issues).
* Futhermore, all other lines that aren't selected will be dimmed to 20% opacity (default) throughout the duration of the touch/move.
* Any dotted line that isn't the primary selection will have it's dots dimmed to hidden (to avoid transparency issues).
*
* @param lineChartView A line chart object informing the delegate about the new selection.
* @param lineIndex An index number identifying the closest line in the chart to the current touch
@@ -150,6 +178,16 @@ typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
*/
- (void)didDeselectLineInLineChartView:(JBLineChartView *)lineChartView;
/**
* Returns whether or not a line at a particular index responds to selection events.
*
* Default: YES
*
* @param lineChartView A line chart object informing the delegate about the new selection.
* @param lineIndex An index number identifying the closest line in the chart to the current touch
*/
- (BOOL)lineChartView:(JBLineChartView *)lineChartView shouldIgnoreSelectionAtIndex:(NSUInteger)lineIndex;
/**
* Returns the color of particular line at lineIndex within the chart.
*
@@ -162,6 +200,18 @@ typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the gradient layer to be used for a particular line at lineIndex within the chart.
*
* Default: black to light gray.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The gradient layer to be used as a mask for the line in the chart.
*/
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView gradientForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the fill color of particular line at lineIndex within the chart.
*
@@ -174,6 +224,18 @@ typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView fillColorForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the gradient layer to be used for a fill of a particular line at lineIndex within the chart.
*
* Default: white to light gray.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The fill color to show under a line in the chart.
*/
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the color of a particular dot in a line at lineIndex within the chart.
* For this value to apply, showsDotsForLineAtLineIndex: must return YES for the line at lineIndex.
@@ -254,6 +316,19 @@ typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the gradient layer to be overlayed on a line during touch events.
* Alpha of gradient is controlled by the color returned from lineChartView:selectionColorForLineAtLineIndex:
*
* Default: matches lineChartView:gradientForLineAtLineIndex:.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The gradient layer to be used as a mask for the line in the chart.
*/
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView selectionGradientForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the selection fill color to be overlayed under a line within the chart during touch events.
* The property showsLineSelection must be YES for the color to apply.
@@ -267,6 +342,19 @@ typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionFillColorForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the gradient layer to be used for the selection fill to be overlayed under a line during touch events.
* Alpha of gradient is controlled by the color returned from lineChartView:selectionFillColorForLineAtLineIndex:
*
* Default: matches lineChartView:fillGradientForLineAtLineIndex.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The fill color to show under a line in the chart.
*/
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView selectionFillGradientForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the selection color to be overlayed on a line within the chart during touch events.
* The property showsLineSelection must be YES for the color to apply.
@@ -294,6 +382,19 @@ typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
*/
- (JBLineChartViewLineStyle)lineChartView:(JBLineChartView *)lineChartView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the line color style of a particular line at lineIndex within the chart.
* See JBLineChartViewLineColorStyle for line color style descriptions.
*
* Default: JBLineChartViewLineColorStyleSolid.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The line style to be used to draw a line in the chart.
*/
- (JBLineChartViewLineColorStyle)lineChartView:(JBLineChartView *)lineChartView lineColorStyleForLineAtLineIndex:(NSUInteger)lineIndex;
@end
@interface JBLineChartView : JBChartView
+221 -47
View File
@@ -23,8 +23,8 @@ CGFloat static const kJBLineChartLinesViewStrokeWidth = 5.0;
CGFloat static const kJBLineChartLinesViewMiterLimit = -5.0;
CGFloat static const kJBLineChartLinesViewDefaultLinePhase = 1.0f;
CGFloat static const kJBLineChartLinesViewDefaultDimmedOpacity = 0.20f;
NSInteger static const kJBLineChartLinesViewUnselectedLineIndex = -1;
CGFloat static const kJBLineChartLinesViewSmoothThresholdSlope = 0.01f;
NSInteger static const kJBLineChartLinesViewUnselectedLineIndex = -1;
NSInteger static const kJBLineChartLinesViewSmoothThresholdVertical = 1;
// Numerics (JBLineChartDotsView)
@@ -35,10 +35,12 @@ NSInteger static const kJBLineChartDotsViewUnselectedLineIndex = -1;
CGFloat static const kJBLineSelectionViewWidth = 20.0f;
// Numerics (JBLineChartView)
CGFloat static const kJBBarChartViewUndefinedCachedHeight = -1.0f;
CGFloat static const kJBLineChartViewUndefinedCachedHeight = -1.0f;
CGFloat static const kJBLineChartViewStateAnimationDuration = 0.25f;
CGFloat static const kJBLineChartViewStateAnimationDelay = 0.05f;
CGFloat static const kJBLineChartViewStateBounceOffset = 15.0f;
CGFloat static const kJBLineChartViewDefaultStartPoint = 0.0;
CGFloat static const kJBLineChartViewDefaultEndPoint = 1.0;
NSInteger static const kJBLineChartUnselectedLineIndex = -1;
// Collections (JBLineChartLineView)
@@ -51,6 +53,15 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
static UIColor *kJBLineChartViewDefaultLineSelectionFillColor = nil;
static UIColor *kJBLineChartViewDefaultDotColor = nil;
static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
static UIColor *kJBLineChartViewDefaultGradientStartColor = nil;
static UIColor *kJBLineChartViewDefaultGradientEndColor = nil;
static UIColor *kJBLineChartViewDefaultGradientFillStartColor = nil;
static UIColor *kJBLineChartViewDefaultGradientFillEndColor = nil;
static UIColor *kJBLineChartViewDefaultGradientSelectionStartColor = nil;
static UIColor *kJBLineChartViewDefaultGradientSelectionEndColor = nil;
static UIColor *kJBLineChartViewDefaultGradientSelectionFillStartColor = nil;
static UIColor *kJBLineChartViewDefaultGradientSelectionFillEndColor = nil;
@interface JBChartView (Private)
@@ -63,6 +74,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
@property (nonatomic, assign) NSUInteger tag;
@property (nonatomic, assign) JBLineChartViewLineStyle lineStyle;
@property (nonatomic, assign) JBLineChartViewLineColorStyle lineColorStyle;
@end
@@ -107,12 +119,17 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
- (NSArray *)chartDataForLineChartLinesView:(JBLineChartLinesView*)lineChartLinesView;
- (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView colorForLineAtLineIndex:(NSUInteger)lineIndex;
- (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView selectedColorForLineAtLineIndex:(NSUInteger)lineIndex;
- (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView gradientForLineAtLineIndex:(NSUInteger)lineIndex;
- (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView selectionGradientForLineAtLineIndex:(NSUInteger)lineIndex;
- (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView fillColorForLineAtLineIndex:(NSUInteger)lineIndex;
- (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView selectedFillColorForLineAtLineIndex:(NSUInteger)lineIndex;
- (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex;
- (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView selectionFillGradientForLineAtLineIndex:(NSUInteger)lineIndex;
- (CGFloat)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView widthForLineAtLineIndex:(NSUInteger)lineIndex;
- (CGFloat)paddingForLineChartLinesView:(JBLineChartLinesView *)lineChartLinesView;
- (JBLineChartViewLineStyle)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex;
- (JBLineChartViewLineColorStyle)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView lineColorStyleForLineAtLineIndex:(NSUInteger)lineIndex;
- (BOOL)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView smoothLineAtLineIndex:(NSUInteger)lineIndex;
- (CGFloat)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex;
@end
@@ -141,7 +158,6 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
- (CGFloat)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView dotRadiusForLineAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
- (UIView *)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView dotViewAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
- (BOOL)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView shouldHideDotViewOnSelectionAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
- (CGFloat)paddingForLineChartDotsView:(JBLineChartDotsView *)lineChartDotsView;
- (BOOL)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex;
@end
@@ -202,6 +218,14 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
kJBLineChartViewDefaultLineSelectionFillColor = [UIColor clearColor];
kJBLineChartViewDefaultDotColor = [UIColor blackColor];
kJBLineChartViewDefaultDotSelectionColor = [UIColor whiteColor];
kJBLineChartViewDefaultGradientStartColor = [UIColor blackColor];
kJBLineChartViewDefaultGradientEndColor = [UIColor lightGrayColor];
kJBLineChartViewDefaultGradientFillStartColor = [UIColor whiteColor];
kJBLineChartViewDefaultGradientFillEndColor = [UIColor lightGrayColor];
kJBLineChartViewDefaultGradientSelectionStartColor = [UIColor whiteColor];
kJBLineChartViewDefaultGradientSelectionEndColor = [UIColor darkGrayColor];
kJBLineChartViewDefaultGradientSelectionFillStartColor = [UIColor clearColor];
kJBLineChartViewDefaultGradientSelectionFillEndColor = [UIColor clearColor];
}
}
@@ -239,8 +263,8 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
{
_showsVerticalSelection = YES;
_showsLineSelection = YES;
_cachedMinHeight = kJBBarChartViewUndefinedCachedHeight;
_cachedMaxHeight = kJBBarChartViewUndefinedCachedHeight;
_cachedMinHeight = kJBLineChartViewUndefinedCachedHeight;
_cachedMaxHeight = kJBLineChartViewUndefinedCachedHeight;
}
#pragma mark - Data
@@ -248,8 +272,8 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
- (void)reloadData
{
// Reset cached max height
self.cachedMinHeight = kJBBarChartViewUndefinedCachedHeight;
self.cachedMaxHeight = kJBBarChartViewUndefinedCachedHeight;
self.cachedMinHeight = kJBLineChartViewUndefinedCachedHeight;
self.cachedMaxHeight = kJBLineChartViewUndefinedCachedHeight;
// Padding
CGFloat chartPadding = [self padding];
@@ -290,7 +314,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
rawHeight = 0; //set to 0 so we can calculate the x position
}
CGFloat normalizedHeight = [self normalizedHeightForRawHeight:rawHeight];
CGFloat normalizedHeight = [self padding] + [self normalizedHeightForRawHeight:rawHeight];
yOffset = mainViewRect.size.height - normalizedHeight;
chartPoint.position = CGPointMake(xOffset, yOffset);
@@ -432,13 +456,15 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
{
CGFloat minHeight = [self minimumValue];
CGFloat maxHeight = [self maximumValue];
CGFloat availableHeightWithPadding = [self availableHeight] - ([self padding] * 2);
if ((maxHeight - minHeight) <= 0)
{
return [self availableHeight];
return availableHeightWithPadding;
}
return ((rawHeight - minHeight) / (maxHeight - minHeight)) * [self availableHeight];
return ((rawHeight - minHeight) / (maxHeight - minHeight)) * availableHeightWithPadding;
}
- (CGFloat)availableHeight
@@ -543,7 +569,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
maxLineWidth = currentMaxLineWidth;
}
}
return ceil(maxLineWidth * 0.5);
return (maxLineWidth * 0.5);
}
- (NSUInteger)dataCount
@@ -588,6 +614,30 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
return kJBLineChartViewDefaultLineSelectionColor;
}
- (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView gradientForLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.delegate respondsToSelector:@selector(lineChartView:gradientForLineAtLineIndex:)])
{
return [self.delegate lineChartView:self gradientForLineAtLineIndex:lineIndex];
}
// Default gradient
CAGradientLayer *gradient = [CAGradientLayer new];
gradient.startPoint = CGPointMake(kJBLineChartViewDefaultStartPoint, kJBLineChartViewDefaultStartPoint);
gradient.endPoint = CGPointMake(kJBLineChartViewDefaultEndPoint, kJBLineChartViewDefaultEndPoint);
gradient.colors = @[(id)kJBLineChartViewDefaultGradientStartColor.CGColor, (id)kJBLineChartViewDefaultGradientEndColor.CGColor];
return gradient;
}
- (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView selectionGradientForLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.delegate respondsToSelector:@selector(lineChartView:selectionGradientForLineAtLineIndex:)])
{
return [self.delegate lineChartView:self selectionGradientForLineAtLineIndex:lineIndex];
}
return [self.delegate lineChartView:self gradientForLineAtLineIndex:lineIndex];
}
- (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView fillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.delegate respondsToSelector:@selector(lineChartView:fillColorForLineAtLineIndex:)])
@@ -606,6 +656,30 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
return kJBLineChartViewDefaultLineSelectionFillColor;
}
- (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.delegate respondsToSelector:@selector(lineChartView:fillGradientForLineAtLineIndex:)])
{
return [self.delegate lineChartView:self fillGradientForLineAtLineIndex:lineIndex];
}
// Default gradient
CAGradientLayer *gradient = [CAGradientLayer new];
gradient.startPoint = CGPointMake(kJBLineChartViewDefaultStartPoint, kJBLineChartViewDefaultStartPoint);
gradient.endPoint = CGPointMake(kJBLineChartViewDefaultEndPoint, kJBLineChartViewDefaultEndPoint);
gradient.colors = @[(id)kJBLineChartViewDefaultGradientFillStartColor.CGColor, (id)kJBLineChartViewDefaultGradientFillEndColor.CGColor];
return gradient;
}
- (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView selectionFillGradientForLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.delegate respondsToSelector:@selector(lineChartView:selectionFillGradientForLineAtLineIndex:)])
{
return [self.delegate lineChartView:self selectionFillGradientForLineAtLineIndex:lineIndex];
}
return [self.delegate lineChartView:self fillGradientForLineAtLineIndex:lineIndex];
}
- (CGFloat)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView widthForLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.delegate respondsToSelector:@selector(lineChartView:widthForLineAtLineIndex:)])
@@ -615,11 +689,6 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
return kJBLineChartLinesViewStrokeWidth;
}
- (CGFloat)paddingForLineChartLinesView:(JBLineChartLinesView *)lineChartLinesView
{
return [self padding];
}
- (JBLineChartViewLineStyle)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.delegate respondsToSelector:@selector(lineChartView:lineStyleForLineAtLineIndex:)])
@@ -629,6 +698,15 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
return JBLineChartViewLineStyleSolid;
}
- (JBLineChartViewLineColorStyle)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView lineColorStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.delegate respondsToSelector:@selector(lineChartView:lineColorStyleForLineAtLineIndex:)])
{
return [self.delegate lineChartView:self lineColorStyleForLineAtLineIndex:lineIndex];
}
return JBLineChartViewLineColorStyleSolid;
}
- (BOOL)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView smoothLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.dataSource respondsToSelector:@selector(lineChartView:smoothLineAtLineIndex:)])
@@ -638,6 +716,15 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
return NO;
}
- (CGFloat)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex
{
if ([self.dataSource respondsToSelector:@selector(lineChartView:dimmedSelectionOpacityAtLineIndex:)])
{
return [self.dataSource lineChartView:self dimmedSelectionOpacityAtLineIndex:lineIndex];
}
return kJBLineChartLinesViewDefaultDimmedOpacity;
}
#pragma mark - JBLineChartDotsViewDelegate
- (NSArray *)chartDataForLineChartDotsView:(JBLineChartDotsView*)lineChartDotsView
@@ -699,11 +786,6 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
return NO;
}
- (CGFloat)paddingForLineChartDotsView:(JBLineChartDotsView *)lineChartDotsView
{
return [self padding];
}
- (BOOL)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex
{
if ([self.dataSource respondsToSelector:@selector(lineChartView:showsDotsForLineAtLineIndex:)])
@@ -808,7 +890,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
- (CGFloat)cachedMinHeight
{
if (_cachedMinHeight == kJBBarChartViewUndefinedCachedHeight)
if (_cachedMinHeight == kJBLineChartViewUndefinedCachedHeight)
{
CGFloat minHeight = FLT_MAX;
NSAssert([self.dataSource respondsToSelector:@selector(numberOfLinesInLineChartView:)], @"JBLineChartView // dataSource must implement - (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView");
@@ -835,7 +917,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
- (CGFloat)cachedMaxHeight
{
if (_cachedMaxHeight == kJBBarChartViewUndefinedCachedHeight)
if (_cachedMaxHeight == kJBLineChartViewUndefinedCachedHeight)
{
CGFloat maxHeight = 0;
NSAssert([self.dataSource respondsToSelector:@selector(numberOfLinesInLineChartView:)], @"JBLineChartView // dataSource must implement - (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView");
@@ -952,6 +1034,15 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
for (NSUInteger lineIndex=0; lineIndex<numberOfLines; lineIndex++)
{
NSAssert([self.dataSource respondsToSelector:@selector(lineChartView:numberOfVerticalValuesAtLineIndex:)], @"JBLineChartView // dataSource must implement - (NSUInteger)lineChartView:(JBLineChartView *)lineChartView numberOfVerticalValuesAtLineIndex:(NSUInteger)lineIndex");
if ([self.delegate respondsToSelector:@selector(lineChartView:shouldIgnoreSelectionAtIndex:)])
{
if([self.delegate lineChartView:self shouldIgnoreSelectionAtIndex:lineIndex])
{
continue;
}
}
if ([self.dataSource lineChartView:self numberOfVerticalValuesAtLineIndex:lineIndex] > rightHorizontalIndex)
{
NSArray *lineData = [self.chartData objectAtIndex:lineIndex];
@@ -990,7 +1081,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
{
return; // no touch for no data or collapsed
}
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [self clampPoint:[touch locationInView:self.linesView] toBounds:self.linesView.bounds padding:[self padding]];
@@ -1019,8 +1110,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
self.verticalSelectionView.bgColor = verticalSelectionColor;
}
CGFloat xOffset = fmin(self.bounds.size.width - self.verticalSelectionView.frame.size.width, fmax(0, touchPoint.x - (ceil(self.verticalSelectionView.frame.size.width * 0.5))));
CGFloat xOffset = fmin(self.bounds.size.width - self.verticalSelectionView.frame.size.width, fmax(0, touchPoint.x - (self.verticalSelectionView.frame.size.width * 0.5)));
CGFloat yOffset = self.headerView.frame.size.height + self.headerPadding;
if ([self.dataSource respondsToSelector:@selector(shouldExtendSelectionViewIntoHeaderPaddingForChartView:)])
@@ -1067,6 +1157,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
[self.linesView setSelectedLineIndex:[self lineIndexForPoint:touchPoint] animated:YES];
[self.dotsView setSelectedLineIndex:[self lineIndexForPoint:touchPoint] animated:YES];
}
[self setVerticalSelectionViewVisible:NO animated:NO];
[self touchesBeganOrMovedWithTouches:touches];
}
@@ -1200,9 +1291,6 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
NSAssert([self.delegate respondsToSelector:@selector(chartDataForLineChartLinesView:)], @"JBLineChartLinesView // delegate must implement - (NSArray *)chartDataForLineChartLinesView:(JBLineChartLinesView *)lineChartLinesView");
NSArray *chartData = [self.delegate chartDataForLineChartLinesView:self];
NSAssert([self.delegate respondsToSelector:@selector(paddingForLineChartLinesView:)], @"JBLineChartLinesView // delegate must implement - (CGFloat)paddingForLineChartLinesView:(JBLineChartLinesView *)lineChartLinesView");
CGFloat padding = [self.delegate paddingForLineChartLinesView:self];
NSUInteger lineIndex = 0;
for (NSArray *lineData in chartData)
@@ -1224,7 +1312,10 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
BOOL visiblePointFound = NO;
NSArray *sortedLineData = [lineData sortedArrayUsingSelector:@selector(compare:)];
CGFloat firstXPosition = 0.0f;
CGFloat lastXPosition = 0.0f;
CGFloat firstYPosition = 0.0f;
CGFloat lastXPosition = 0.0f;
CGFloat lastYPosition = 0.0f;
for (NSUInteger index = 0; index < [sortedLineData count]; index++)
{
JBLineChartPoint *lineChartPoint = [sortedLineData objectAtIndex:index];
@@ -1234,8 +1325,9 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
if (!visiblePointFound)
{
[path moveToPoint:CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - padding, fmax(padding, lineChartPoint.position.y)))];
[path moveToPoint:CGPointMake(lineChartPoint.position.x, lineChartPoint.position.y)];
firstXPosition = lineChartPoint.position.x;
firstYPosition = lineChartPoint.position.y;
visiblePointFound = YES;
}
else
@@ -1261,14 +1353,15 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
CGPoint controlPoint1 = CGPointMake(controlPointX, previousLineChartPoint.position.y);
CGPoint controlPoint2 = CGPointMake(controlPointX, lineChartPoint.position.y);
[path addCurveToPoint:CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - padding, fmax(padding, lineChartPoint.position.y))) controlPoint1:controlPoint1 controlPoint2:controlPoint2];
[path addCurveToPoint:CGPointMake(lineChartPoint.position.x, lineChartPoint.position.y) controlPoint1:controlPoint1 controlPoint2:controlPoint2];
}
else
{
[path addLineToPoint:CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - padding, fmax(padding, lineChartPoint.position.y)))];
[path addLineToPoint:CGPointMake(lineChartPoint.position.x, lineChartPoint.position.y)];
}
lastXPosition = lineChartPoint.position.x;
lastYPosition = lineChartPoint.position.y;
previousSlope = currentSlope;
}
previousLineChartPoint = lineChartPoint;
@@ -1298,6 +1391,9 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:fillColorForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView fillColorForLineAtLineIndex:(NSUInteger)lineIndex");
shapeFillLayer.fillColor = [self.delegate lineChartLinesView:self fillColorForLineAtLineIndex:lineIndex].CGColor;
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:lineColorStyleForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (JBLineChartViewLineColorStyle)lineChartLineView:(JBLineChartLinesView *)lineChartLinesView lineColorStyleForLineAtLineIndex:(NSUInteger)lineIndex");
shapeLayer.lineColorStyle = [self.delegate lineChartLinesView:self lineColorStyleForLineAtLineIndex:lineIndex];
if (smoothLine == YES)
{
shapeLayer.lineCap = kCALineCapRound;
@@ -1323,15 +1419,35 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
if(visiblePointFound)
{
[fillPath addLineToPoint:CGPointMake(lastXPosition, self.bounds.size.height - padding)];
[fillPath addLineToPoint:CGPointMake(firstXPosition, self.bounds.size.height - padding)];
[fillPath addLineToPoint:CGPointMake(lastXPosition, lastYPosition)];
[fillPath addLineToPoint:CGPointMake(lastXPosition, self.bounds.size.height)];
[fillPath addLineToPoint:CGPointMake(firstXPosition, self.bounds.size.height)];
[fillPath addLineToPoint:CGPointMake(firstXPosition, firstYPosition)];
}
shapeFillLayer.path = fillPath.CGPath;
shapeFillLayer.frame = self.bounds;
[self.layer addSublayer:shapeFillLayer];
[self.layer addSublayer:shapeLayer];
if (shapeLayer.lineColorStyle == JBLineChartViewLineColorStyleGradient)
{
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:fillGradientForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex");
CAGradientLayer *fillGradient = [self.delegate lineChartLinesView:self fillGradientForLineAtLineIndex:lineIndex];
fillGradient.frame = shapeFillLayer.frame;
fillGradient.mask = shapeFillLayer;
[self.layer addSublayer:fillGradient];
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:gradientForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView gradientForLineAtLineIndex:(NSUInteger)lineIndex");
CAGradientLayer *lineGradient = [self.delegate lineChartLinesView:self gradientForLineAtLineIndex:lineIndex];
lineGradient.frame = shapeLayer.frame;
lineGradient.mask = shapeLayer;
[self.layer addSublayer:lineGradient];
}
else // shapeLayer.lineColorStyle == JBLineChartViewLineColorStyleSolid (default)
{
[self.layer addSublayer:shapeFillLayer];
[self.layer addSublayer:shapeLayer];
}
lineIndex++;
}
@@ -1356,6 +1472,9 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
__weak JBLineChartLinesView* weakSelf = self;
dispatch_block_t adjustLines = ^{
NSMutableArray *layersToReplace = [NSMutableArray array];
NSString * const oldLayerKey = @"oldLayer";
NSString * const newLayerKey = @"newLayer";
for (CALayer *layer in [weakSelf.layer sublayers])
{
if ([layer isKindOfClass:[JBLineLayer class]])
@@ -1370,7 +1489,9 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
{
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:colorForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView colorForLineAtLineIndex:(NSUInteger)lineIndex");
((JBLineLayer *)layer).strokeColor = [self.delegate lineChartLinesView:self colorForLineAtLineIndex:((JBLineLayer *)layer).tag].CGColor;
((JBLineLayer *)layer).opacity = (weakSelf.selectedLineIndex == kJBLineChartLinesViewUnselectedLineIndex) ? 1.0f : kJBLineChartLinesViewDefaultDimmedOpacity;
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:dimmedSelectionOpacityAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CGFloat)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex");
((JBLineLayer *)layer).opacity = (weakSelf.selectedLineIndex == kJBLineChartLinesViewUnselectedLineIndex) ? 1.0f : [self.delegate lineChartLinesView:self dimmedSelectionOpacityAtLineIndex:((JBLineLayer *)layer).tag];
}
}
else if ([layer isKindOfClass:[JBFillLayer class]])
@@ -1385,9 +1506,65 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
{
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:fillColorForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView fillColorForLineAtLineIndex:(NSUInteger)lineIndex");
((JBFillLayer *)layer).fillColor = [self.delegate lineChartLinesView:self fillColorForLineAtLineIndex:((JBLineLayer *)layer).tag].CGColor;
((JBFillLayer *)layer).opacity = (weakSelf.selectedLineIndex == kJBLineChartLinesViewUnselectedLineIndex) ? 1.0f : kJBLineChartLinesViewDefaultDimmedOpacity;
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:dimmedSelectionOpacityAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CGFloat)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex");
((JBFillLayer *)layer).opacity = (weakSelf.selectedLineIndex == kJBLineChartLinesViewUnselectedLineIndex) ? 1.0f : [self.delegate lineChartLinesView:self dimmedSelectionOpacityAtLineIndex:((JBLineLayer *)layer).tag];
}
}
else if ([layer isKindOfClass:[CAGradientLayer class]])
{
if ([layer.mask isKindOfClass:[JBLineLayer class]])
{
JBLineLayer *lineLayer = (JBLineLayer *)layer.mask;
if (lineLayer.tag == weakSelf.selectedLineIndex)
{
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:selectionGradientForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView selectionGradientForLineAtLineIndex:(NSUInteger)lineIndex");
CAGradientLayer *selectedGradient = [self.delegate lineChartLinesView:self selectionGradientForLineAtLineIndex:lineLayer.tag];
selectedGradient.frame = layer.frame;
selectedGradient.mask = layer.mask;
selectedGradient.opacity = 1.0f;
[layersToReplace addObject:@{oldLayerKey: layer, newLayerKey: selectedGradient}];
}
else
{
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:gradientForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView gradientForLineAtLineIndex:(NSUInteger)lineIndex");
CAGradientLayer *unselectedGradient = [self.delegate lineChartLinesView:self gradientForLineAtLineIndex:lineLayer.tag];
unselectedGradient.frame = layer.frame;
unselectedGradient.mask = layer.mask;
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:dimmedSelectionOpacityAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CGFloat)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex");
((JBLineLayer *)layer).opacity = (weakSelf.selectedLineIndex == kJBLineChartLinesViewUnselectedLineIndex) ? 1.0f : [self.delegate lineChartLinesView:self dimmedSelectionOpacityAtLineIndex:lineLayer.tag];
[layersToReplace addObject:@{oldLayerKey: layer, newLayerKey: unselectedGradient}];
}
}
else if ([layer.mask isKindOfClass:[JBFillLayer class]])
{
JBFillLayer *fillLayer = (JBFillLayer *)layer.mask;
if (fillLayer.tag == weakSelf.selectedLineIndex)
{
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:selectionFillGradientForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView selectionFillGradientForLineAtLineIndex:(NSUInteger)lineIndex");
CAGradientLayer *selectedFillGradient = [self.delegate lineChartLinesView:self selectionFillGradientForLineAtLineIndex:fillLayer.tag];
selectedFillGradient.frame = layer.frame;
selectedFillGradient.mask = layer.mask;
selectedFillGradient.opacity = 1.0f;
[layersToReplace addObject:@{oldLayerKey: layer, newLayerKey: selectedFillGradient}];
}
else
{
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:fillGradientForLineAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CAGradientLayer *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex");
CAGradientLayer *unselectedFillGradient = [self.delegate lineChartLinesView:self fillGradientForLineAtLineIndex:fillLayer.tag];
unselectedFillGradient.frame = layer.frame;
unselectedFillGradient.mask = layer.mask;
NSAssert([self.delegate respondsToSelector:@selector(lineChartLinesView:dimmedSelectionOpacityAtLineIndex:)], @"JBLineChartLinesView // delegate must implement - (CGFloat)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex");
unselectedFillGradient.opacity = (weakSelf.selectedLineIndex == kJBLineChartLinesViewUnselectedLineIndex) ? 1.0f : [self.delegate lineChartLinesView:self dimmedSelectionOpacityAtLineIndex:fillLayer.tag];
[layersToReplace addObject:@{oldLayerKey: layer, newLayerKey: unselectedFillGradient}];
}
}
}
}
for (NSDictionary *layerPair in layersToReplace)
{
[weakSelf.layer replaceSublayer:layerPair[oldLayerKey] with:layerPair[newLayerKey]];
}
};
@@ -1482,10 +1659,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
NSAssert([self.delegate respondsToSelector:@selector(chartDataForLineChartDotsView:)], @"JBLineChartDotsView // delegate must implement - (NSArray *)chartDataForLineChartDotsView:(JBLineChartDotsView *)lineChartDotsView");
NSArray *chartData = [self.delegate chartDataForLineChartDotsView:self];
NSAssert([self.delegate respondsToSelector:@selector(paddingForLineChartDotsView:)], @"JBLineChartDotsView // delegate must implement - (CGFloat)paddingForLineChartDotsView:(JBLineChartDotsView *)lineChartDotsView");
CGFloat padding = [self.delegate paddingForLineChartDotsView:self];
NSUInteger lineIndex = 0;
NSMutableDictionary *mutableDotViewsDict = [NSMutableDictionary dictionary];
for (NSArray *lineData in chartData)
@@ -1519,7 +1693,7 @@ static UIColor *kJBLineChartViewDefaultDotSelectionColor = nil;
currentDotView.backgroundColor = [self.delegate lineChartDotsView:self colorForDotAtHorizontalIndex:horizontalIndex atLineIndex:lineIndex];
}
currentDotView.center = CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - padding, fmax(padding, lineChartPoint.position.y)));
currentDotView.center = CGPointMake(lineChartPoint.position.x, lineChartPoint.position.y);
[mutableDotViews addObject:currentDotView];
[self addSubview:currentDotView];
+196
View File
@@ -0,0 +1,196 @@
## Customization
Both the line and bar charts support a robust set of customization options.
The background of a bar or line chart can be set just like any other view:
self.barChartView.backgroundColor = ...; // UIColor
self.lineChartView.backgroundColor = ...; // UIColor
Any <i>JBChartView</i> subclass supports the use of headers and footers (similiar to that of <i>UITableView</i>):
self.barChartView.footerView = ...; // UIView
self.lineChartView.headerView = ...; // UIView
Lastly, any JBChartView subclass can be collapsed or expanded programmatically via the <i>state</i> property. If you chose to animate state changes, a callback helper can be used to notify you when the animation has completed:
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback;
#### JBBarChartView
A bar chart can be inverted such that it's orientation is top->down (including the selection view) by setting the following property:
@property (nonatomic, assign, getter=isInverted) BOOL inverted;
By default, a chart's bars will be black and flat. They can be customized by supplying a UIView subclass through the <i>optional</i> protocol:
- (UIView *)barChartView:(JBBarChartView *)barChartView barViewAtIndex:(NSUInteger)index
{
return ...; // color of line in chart
}
If you don't require a custom UIView, simply supply a color for the bar instead:
- (UIColor *)barChartView:(JBBarChartView *)barChartView colorForBarViewAtIndex:(NSUInteger)index;
If a solid color isn't your cup of tea, you can expose a gradient to be applied across the entire chart:
- (CAGradientLayer *)barGradientForBarChartView:(JBBarChartView *)barChartView;
Furthermore, the color of the selection bar (on touch events) can be customized via the <i>optional</i> protocol:
- (UIColor *)barSelectionColorForBarChartView:(JBBarChartView *)barChartView
{
return ...; // color of selection view
}
<b>Note</b>: The delegate will request a custom UIView, followed by a color and lastly a gradient. If nothing is supplied, a plain black bar will be used.
Lastly, a bar chart's selection events are delegated back via:
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSUInteger)index touchPoint:(CGPoint)touchPoint
{
// Update view
}
- (void)didDeselectBarChartView:(JBBarChartView *)barChartView
{
// Update view
}
The <b>touchPoint</b> is especially important as it allows you to add custom elements to your chart during selection events. Refer to the demo project (<b>JBarChartViewController</b>) to see how a tooltip can be used to display additional information during selection events.
#### JBLineChartView
The color, width and style of each line in the chart can be customized via the <i>optional</i> protocol:
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of line in chart
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView fillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of area under line in chart
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView widthForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // width of line in chart
}
- (JBLineChartViewLineStyle)lineChartView:(JBLineChartView *)lineChartView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // style of line in chart
}
Additionally, the line style of a line can be customzized via the <i>optional</i> protocol. If a gradient is used, the color for the line and fill of the line will control the alpha value of the gradient.
- (JBLineChartViewLineColorStyle)lineChartView:(JBLineChartView *)lineChartView lineColorStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // line style of line in chart
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView gradientForLineAtLineIndex:(NSUInteger)lineIndex {
return ...; // gradient for line in chart
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex {
return ...; // gradient for area under line in chart
}
Defining a gradient to use is simple and flexible. For example, this would be a horizontal gradient from blue to green:
CAGradientLayer *gradient = [CAGradientLayer new];
gradient.startPoint = CGPointMake(0.0, 0.0);
gradient.endPoint = CGPointMake(1.0, 0.0);
gradient.colors = @[(id)[UIColor blueColor].CGColor, (id)[UIColor greenColor].CGColor];
Furthermore, the color and width of the selection view along with the color of the selected line can be customized via the <i>optional</i> protocols:
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView verticalSelectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of selection view
}
- (CGFloat)verticalSelectionWidthForLineChartView:(JBLineChartView *)lineChartView
{
return ...; // width of selection view
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of selected line
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionFillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of area under selected line
}
When using a gradient for the line or fill, a different gradient can provided for selection. If the selection gradient is not provided, it will default to the line and fill gradient provided for the line.
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView selectionGradientForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // gradient for selected line
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView selectionFillGradientForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // gradient for area under selected line
}
By default, each line will not show dots for each point. To enable this on a per-line basis:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex;
To the radius of each dot (default is 6x the line width, or 3x the diameter), implement:
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dotRadiusForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
To customize the color of each dot during selection and non-selection events (default is white and black respectively), implement:
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
Alternatively, you can supply your own UIView instead of using the default impelmentation:
- (UIView *)lineChartView:(JBLineChartView *)lineChartView dotViewAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
Custom dot views are automatically shown when selected unless the following is implemented:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView shouldHideDotViewOnSelectionAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
As well, by default, each line will have squared off end caps and connection points. To enable rounded connections and end caps:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView smoothLineAtLineIndex:(NSUInteger)lineIndex;
Furthermore, a line chart's selection events are delegated back via:
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectLineAtIndex:(NSUInteger)lineIndex horizontalIndex:(NSUInteger)horizontalIndex touchPoint:(CGPoint)touchPoint
{
// Update view
}
- (void)didDeselectLineInLineChartView:(JBLineChartView *)lineChartView
{
// Update view
}
Upon selection, all other lines (+ fills) will be dimmed to 20% opacity (default). To change this value, implement:
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex
{
// Return new opacity (0.0 to hide completely, and 1.0 to have no effect)
}
If you don't want a line to be selectable:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView shouldIgnoreSelectionAtIndex:(NSUInteger)lineIndex
{
return NO; // Check line index
}
The <b>touchPoint</b> is especially important as it allows you to add custom elements to your chart during selection events. Refer to the demo project (<b>JBLineChartViewController</b>) to see how a tooltip can be used to display additional information during selection events.
+2 -2
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "JBChartView"
s.version = "2.8.15"
s.version = "2.9.0"
s.summary = "Jawbone's iOS-based charting library for both line and bar graphs."
s.homepage = "https://github.com/Jawbone/JBChartView"
@@ -10,7 +10,7 @@ Pod::Spec.new do |s|
s.author = { "Terry Worona" => "tworona@jawbone.com" }
s.source = {
:git => "https://github.com/Jawbone/JBChartView.git",
:tag => "v2.8.15"
:tag => "v2.9.0"
}
s.platform = :ios, '6.0'
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
566C73A61C026858000EC785 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 566C73A51C026858000EC785 /* Default-568h@2x.png */; };
94BDFC3419F933B2007492F6 /* JBLineChartMissingPointsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94BDFC3319F933B2007492F6 /* JBLineChartMissingPointsViewController.m */; };
9B0725211829822A0052109B /* JBChartListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0725201829822A0052109B /* JBChartListViewController.m */; };
9B2E530518218CF20079B9D2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B2E530418218CF20079B9D2 /* Foundation.framework */; };
@@ -46,6 +47,7 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
566C73A51C026858000EC785 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
94BDFC3219F933B2007492F6 /* JBLineChartMissingPointsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBLineChartMissingPointsViewController.h; sourceTree = "<group>"; };
94BDFC3319F933B2007492F6 /* JBLineChartMissingPointsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBLineChartMissingPointsViewController.m; sourceTree = "<group>"; };
9B07251F1829822A0052109B /* JBChartListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBChartListViewController.h; sourceTree = "<group>"; };
@@ -233,6 +235,7 @@
9B603D44182C7002000A76D0 /* Images */ = {
isa = PBXGroup;
children = (
566C73A51C026858000EC785 /* Default-568h@2x.png */,
9B7967ED198317540003A2B0 /* icon-area-chart.png */,
9B7967EE198317540003A2B0 /* icon-area-chart@2x.png */,
9B698F07182D720E003C135F /* icon-arrow.png */,
@@ -352,7 +355,7 @@
9B2E52F918218CF20079B9D2 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0510;
LastUpgradeCheck = 0710;
ORGANIZATIONNAME = Jawbone;
};
buildConfigurationList = 9B2E52FC18218CF20079B9D2 /* Build configuration list for PBXProject "JBChartViewDemo" */;
@@ -387,6 +390,7 @@
9B7967EF198317540003A2B0 /* icon-area-chart.png in Resources */,
9B603D47182C7002000A76D0 /* icon-jawbone-logo.png in Resources */,
9B603D48182C7002000A76D0 /* icon-jawbone-logo@2x.png in Resources */,
566C73A61C026858000EC785 /* Default-568h@2x.png in Resources */,
9B7967F0198317540003A2B0 /* icon-area-chart@2x.png in Resources */,
9B698F19182D7DAE003C135F /* icon-line-chart@2x.png in Resources */,
9B698F0A182D720E003C135F /* icon-arrow@2x.png in Resources */,
@@ -456,6 +460,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -519,6 +524,7 @@
GCC_PREFIX_HEADER = "JBChartViewDemo/JBChartViewDemo-Prefix.pch";
INFOPLIST_FILE = "JBChartViewDemo/JBChartViewDemo-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.jawbone.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -533,6 +539,7 @@
GCC_PREFIX_HEADER = "JBChartViewDemo/JBChartViewDemo-Prefix.pch";
INFOPLIST_FILE = "JBChartViewDemo/JBChartViewDemo-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.jawbone.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -29,8 +29,14 @@
#define kJBColorLineChartHeaderSeparatorColor UIColorFromHex(0x8eb6b7)
#define kJBColorLineChartDefaultSolidLineColor [UIColor colorWithWhite:1.0 alpha:0.5]
#define kJBColorLineChartDefaultSolidSelectedLineColor [UIColor colorWithWhite:1.0 alpha:1.0]
#define kJBColorLineChartDefaultDashedLineColor [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0]
#define kJBColorLineChartDefaultDashedLineColor [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0]
#define kJBColorLineChartDefaultDashedSelectedLineColor [UIColor colorWithWhite:1.0 alpha:1.0]
#define kJBColorLineChartDefaultSolidFillColor [UIColor clearColor]
#define kJBColorLineChartDefaultDashedFillColor [UIColor colorWithWhite:1.0 alpha:0.3]
#define kJBColorLineChartDefaultGradientStartColor UIColorFromHex(0x0000FF)
#define kJBColorLineChartDefaultGradientEndColor UIColorFromHex(0x00FF00)
#define kJBColorLineChartDefaultFillGradientStartColor UIColorFromHex(0xFFFFFF)
#define kJBColorLineChartDefaultFillGradientEndColor UIColorFromHex(0xbe0000)
#define mark - Area Chart
@@ -12,7 +12,7 @@
#import "JBChartTooltipTipView.h"
// Numerics
CGFloat const kJBBaseChartViewControllerAnimationDuration = 0.25f;
CGFloat const kJBBaseChartViewControllerAnimationDuration = 0.1f;
@interface JBBaseChartViewController ()
@@ -55,10 +55,11 @@ CGFloat const kJBBaseChartViewControllerAnimationDuration = 0.25f;
[self.view bringSubviewToFront:self.tooltipTipView];
dispatch_block_t adjustTooltipPosition = ^{
CGPoint originalTouchPoint = [self.view convertPoint:touchPoint fromView:chartView];
CGPoint convertedTouchPoint = originalTouchPoint; // modified
JBChartView *chartView = [self chartView];
if (chartView)
if (chartView && !CGPointEqualToPoint(touchPoint, CGPointZero))
{
CGFloat minChartX = (chartView.frame.origin.x + ceil(self.tooltipView.frame.size.width * 0.5));
if (convertedTouchPoint.x < minChartX)
@@ -70,6 +71,7 @@ CGFloat const kJBBaseChartViewControllerAnimationDuration = 0.25f;
{
convertedTouchPoint.x = maxChartX;
}
self.tooltipView.frame = CGRectMake(convertedTouchPoint.x - ceil(self.tooltipView.frame.size.width * 0.5), CGRectGetMaxY(chartView.headerView.frame), self.tooltipView.frame.size.width, self.tooltipView.frame.size.height);
CGFloat minTipX = (chartView.frame.origin.x + self.tooltipTipView.frame.size.width);
@@ -83,33 +85,34 @@ CGFloat const kJBBaseChartViewControllerAnimationDuration = 0.25f;
originalTouchPoint.x = maxTipX;
}
self.tooltipTipView.frame = CGRectMake(originalTouchPoint.x - ceil(self.tooltipTipView.frame.size.width * 0.5), CGRectGetMaxY(self.tooltipView.frame), self.tooltipTipView.frame.size.width, self.tooltipTipView.frame.size.height);
}
}
};
dispatch_block_t adjustTooltipVisibility = ^{
self.tooltipView.alpha = _tooltipVisible ? 1.0 : 0.0;
self.tooltipTipView.alpha = _tooltipVisible ? 1.0 : 0.0;
};
if (tooltipVisible)
{
adjustTooltipPosition();
}
if (animated)
{
[UIView animateWithDuration:kJBBaseChartViewControllerAnimationDuration animations:^{
adjustTooltipVisibility();
} completion:^(BOOL finished) {
if (!tooltipVisible)
{
adjustTooltipPosition();
}
}];
if (tooltipVisible)
{
adjustTooltipPosition();
}
[UIView animateWithDuration:kJBBaseChartViewControllerAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
adjustTooltipVisibility();
} completion:^(BOOL finished) {
if (!tooltipVisible)
{
adjustTooltipPosition();
}
}];
}
else
{
adjustTooltipVisibility();
adjustTooltipPosition();
adjustTooltipVisibility();
}
}
@@ -33,7 +33,7 @@
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
@@ -29,6 +29,8 @@ CGFloat const kJBAreaChartViewControllerChartHeaderHeight = 75.0f;
CGFloat const kJBAreaChartViewControllerChartHeaderPadding = 20.0f;
CGFloat const kJBAreaChartViewControllerChartFooterHeight = 20.0f;
CGFloat const kJBAreaChartViewControllerChartLineWidth = 2.0f;
CGFloat const kJBAreaChartViewControllerChartSunLineDimmedOpacity = 1.0f;
CGFloat const kJBAreaChartViewControllerChartMoonLineDimmedOpacity = 0.0f;
NSInteger const kJBAreaChartViewControllerMaxNumChartPoints = 12;
// Strings
@@ -198,6 +200,18 @@ NSString * const kJBAreaChartViewControllerNavButtonViewKey = @"view";
return YES;
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex
{
if (lineIndex == JBLineChartLineMoon)
{
return kJBAreaChartViewControllerChartMoonLineDimmedOpacity;
}
else
{
return kJBAreaChartViewControllerChartSunLineDimmedOpacity;
}
}
#pragma mark - JBLineChartViewDelegate
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView verticalValueForHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
@@ -240,6 +240,43 @@ NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidLineColor: kJBColorLineChartDefaultDashedLineColor;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView fillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidFillColor : kJBColorLineChartDefaultDashedFillColor;
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView gradientForLineAtLineIndex:(NSUInteger)lineIndex
{
if (lineIndex == JBLineChartLineSolid)
{
return nil;
}
else
{
CAGradientLayer *gradient = [CAGradientLayer new];
gradient.startPoint = CGPointMake(0.0, 0.0);
gradient.endPoint = CGPointMake(1.0, 0.0);
gradient.colors = @[(id)kJBColorLineChartDefaultGradientStartColor.CGColor, (id)kJBColorLineChartDefaultGradientEndColor.CGColor];
return gradient;
}
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex
{
if (lineIndex == JBLineChartLineSolid)
{
return nil;
}
else
{
CAGradientLayer *gradient = [CAGradientLayer new];
gradient.startPoint = CGPointMake(0.0, 0.0);
gradient.endPoint = CGPointMake(1.0, 0.0);
gradient.colors = @[(id)kJBColorLineChartDefaultFillGradientStartColor.CGColor, (id)kJBColorLineChartDefaultFillGradientEndColor.CGColor];
return gradient;
}
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidLineColor: kJBColorLineChartDefaultDashedLineColor;
@@ -275,6 +312,11 @@ NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
return (lineIndex == JBLineChartLineSolid) ? JBLineChartViewLineStyleSolid : JBLineChartViewLineStyleDashed;
}
- (JBLineChartViewLineColorStyle)lineChartView:(JBLineChartView *)lineChartView lineColorStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? JBLineChartViewLineColorStyleSolid : JBLineChartViewLineColorStyleGradient;
}
#pragma mark - Buttons
- (void)chartToggleButtonPressed:(id)sender
@@ -5,16 +5,31 @@
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
@@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.jawbone.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

+5 -140
View File
@@ -43,7 +43,7 @@ Simply add the following line to your <code>Podfile</code>:
### The Old School Way
The simpliest way to use JBChartView with your application is to drag and drop the <i>/Classes</i> folder into you're Xcode 5 project. It's also recommended you rename the <i>/Classes</i> folder to something more descriptive (ie. "<i>Jawbone - JBChartView</i>").
The simplest way to use JBChartView with your application is to drag and drop the <i>/Classes</i> folder into you're Xcode 5 project. It's also recommended you rename the <i>/Classes</i> folder to something more descriptive (ie. "<i>Jawbone - JBChartView</i>").
<center>
<img src="https://raw.github.com/Jawbone/JBChartView/master/Screenshots/installation.png">
@@ -153,145 +153,7 @@ Lastly, ensure you have set the *frame* of your lineChartView & call *reloadData
## Customization
Both the line and bar charts support a robust set of customization options.
The background of a bar or line chart can be set just like any other view:
self.barChartView.backgroundColor = ...; // UIColor
self.lineChartView.backgroundColor = ...; // UIColor
Any <i>JBChartView</i> subclass supports the use of headers and footers (similiar to that of <i>UITableView</i>):
self.barChartView.footerView = ...; // UIView
self.lineChartView.headerView = ...; // UIView
Lastly, any JBChartView subclass can be collapsed or expanded programmatically via the <i>state</i> property. If you chose to animate state changes, a callback helper can be used to notify you when the animation has completed:
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback;
#### JBBarChartView
A bar chart can be inverted such that it's orientation is top->down (including the selection view) by setting the following property:
@property (nonatomic, assign, getter=isInverted) BOOL inverted;
By default, a chart's bars will be black and flat. They can be customized by supplying a UIView subclass through the <i>optional</i> protocol:
- (UIView *)barChartView:(JBBarChartView *)barChartView barViewAtIndex:(NSUInteger)index
{
return ...; // color of line in chart
}
If you don't require a custom UIView, simply supply a color for the bar instead:
- (UIColor *)barChartView:(JBBarChartView *)barChartView colorForBarViewAtIndex:(NSUInteger)index;
Furthermore, the color of the selection bar (on touch events) can be customized via the <i>optional</i> protocol:
- (UIColor *)barSelectionColorForBarChartView:(JBBarChartView *)barChartView
{
return ...; // color of selection view
}
Lastly, a bar chart's selection events are delegated back via:
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSUInteger)index touchPoint:(CGPoint)touchPoint
{
// Update view
}
- (void)didDeselectBarChartView:(JBBarChartView *)barChartView
{
// Update view
}
The <b>touchPoint</b> is especially important as it allows you to add custom elements to your chart during selection events. Refer to the demo project (<b>JBarChartViewController</b>) to see how a tooltip can be used to display additional information during selection events.
#### JBLineChartView
The color, width and style of each line in the chart can be customized via the <i>optional</i> protocol:
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of line in chart
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView fillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of area under line in chart
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView widthForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // width of line in chart
}
- (JBLineChartViewLineStyle)lineChartView:(JBLineChartView *)lineChartView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // style of line in chart
}
Furthermore, the color and width of the selection view along with the color of the selected line can be customized via the <i>optional</i> protocols:
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView verticalSelectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of selection view
}
- (CGFloat)verticalSelectionWidthForLineChartView:(JBLineChartView *)lineChartView
{
return ...; // width of selection view
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of selected line
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionFillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of area under selected line
}
By default, each line will not show dots for each point. To enable this on a per-line basis:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex;
To the radius of each dot (default is 6x the line width, or 3x the diameter), implement:
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dotRadiusForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
To customize the color of each dot during selection and non-selection events (default is white and black respectively), implement:
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
Alternatively, you can supply your own UIView instead of using the default impelmentation:
- (UIView *)lineChartView:(JBLineChartView *)lineChartView dotViewAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
Custom dot views are automatically shown when selected unless the following is implemented:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView shouldHideDotViewOnSelectionAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
As well, by default, each line will have squared off end caps and connection points. To enable rounded connections and end caps:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView smoothLineAtLineIndex:(NSUInteger)lineIndex;
Lastly, a line chart's selection events are delegated back via:
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectLineAtIndex:(NSUInteger)lineIndex horizontalIndex:(NSUInteger)horizontalIndex touchPoint:(CGPoint)touchPoint
{
// Update view
}
- (void)didDeselectLineInLineChartView:(JBLineChartView *)lineChartView
{
// Update view
}
The <b>touchPoint</b> is especially important as it allows you to add custom elements to your chart during selection events. Refer to the demo project (<b>JBLineChartViewController</b>) to see how a tooltip can be used to display additional information during selection events.
Both the line and bar charts support a robust set of customization options. Read more about them <a href="Customization.md">here</a>.
## Minimum & Maximum Values
@@ -307,6 +169,9 @@ If value(s) are supplied, they must be >= 0, otherwise an assertion will be thro
The min/max values are clamped to the ceiling and floor of the actual min/max values of the chart's data source; for example, if a maximumValue of 20 is supplied & the chart's actual max is 100, then 100 will be used. For min/max modifications to take effect, reloadData must be called.
## Performance
The nature of charting is to display all available information, unlike a UITableView, which can cache rows that are offscreen. JBChartView's performance will suffer if the number of data points exceed the resolution of the device. The same issue exists with MKMapView, when hundreds of pins are supplied within a certain geographic area. It's why Apple recommends clustering to avoid performance issues. As such, for large datasets, we recommend that your dataSource to supply a subset of points; clustering those that are close to one another.
## License