MrWooJ

Adding Scatter Graph to PNCHart

* this is compatible with new release.
* because of your huge change, I had to change the position of my codes
from viewController to tableViewController.
* minor changing and improvement.
... ... @@ -56,4 +56,10 @@
- (void) setup;
- (void) drawLineFromPoint : (CGPoint) startPoint ToPoint : (CGPoint) endPoint WithLineWith : (CGFloat) lineWidth AndWithColor : (UIColor*) color;
/**
* Update Chart Value
*/
- (void)updateChartData:(NSArray *)data;
@end
... ...
... ... @@ -15,6 +15,8 @@
@interface PNScatterChart ()
@property (nonatomic, weak) CAShapeLayer *pathLayer;
@property (nonatomic, weak) NSMutableArray *verticalLineLayer;
@property (nonatomic, weak) NSMutableArray *horizentalLinepathLayer;
@property (nonatomic) CGPoint startPoint;
... ... @@ -42,6 +44,8 @@
@property (nonatomic) CGFloat AxisX_Margin;
@property (nonatomic) CGFloat AxisY_Margin;
@property (nonatomic) BOOL isForUpdate;
- (void)setDefaultValues;
@end
... ... @@ -83,6 +87,7 @@
self.backgroundColor = [UIColor whiteColor];
self.clipsToBounds = YES;
_showLabel = YES;
_isForUpdate = NO;
self.userInteractionEnabled = YES;
// Coordinate Axis Default Values
... ... @@ -94,7 +99,7 @@
_AxisX_Margin = 30 ;
_AxisY_Margin = 30 ;
self.frame = CGRectMake((SCREEN_WIDTH - self.frame.size.width) / 2, 200, self.frame.size.width, self.frame.size.height) ;
// self.frame = CGRectMake((SCREEN_WIDTH - self.frame.size.width) / 2, 200, self.frame.size.width, self.frame.size.height) ;
self.backgroundColor = [UIColor clearColor];
_startPoint.y = self.frame.size.height - self.AxisY_Margin ;
... ... @@ -122,10 +127,14 @@
NSString *LabelFormat = self.yLabelFormat ? : @"%1.f";
CGFloat tempValue = minVal ;
[_axisX_labels addObject:[NSString stringWithFormat:LabelFormat,minVal]];
UILabel *label = [[UILabel alloc] init];
label.text = [NSString stringWithFormat:LabelFormat,minVal] ;
[_axisX_labels addObject:label];
for (int i = 0 ; i < _AxisX_partNumber; i++) {
tempValue = tempValue + _AxisX_step;
[_axisX_labels addObject:[NSString stringWithFormat:LabelFormat,tempValue]];
UILabel *tempLabel = [[UILabel alloc] init];
tempLabel.text = [NSString stringWithFormat:LabelFormat,tempValue] ;
[_axisX_labels addObject:tempLabel];
}
}
... ... @@ -136,13 +145,16 @@
_AxisY_partNumber = numberOfTicks - 1;
_AxisY_step = (float)((maxVal - minVal)/_AxisY_partNumber);
_axisY_labels = [NSMutableArray array];
NSString *LabelFormat = self.yLabelFormat ? : @"%1.f";
CGFloat tempValue = minVal ;
[_axisY_labels addObject:[NSString stringWithFormat:LabelFormat,minVal]];
UILabel *label = [[UILabel alloc] init];
label.text = [NSString stringWithFormat:LabelFormat,minVal] ;
[_axisY_labels addObject:label];
for (int i = 0 ; i < _AxisY_partNumber; i++) {
tempValue = tempValue + _AxisY_step;
[_axisY_labels addObject:[NSString stringWithFormat:LabelFormat,tempValue]];
UILabel *tempLabel = [[UILabel alloc] init];
tempLabel.text = [NSString stringWithFormat:LabelFormat,tempValue] ;
[_axisY_labels addObject:tempLabel];
}
}
... ... @@ -164,11 +176,10 @@
_startPointVectorY = _startPoint ;
}
- (void) showXLabelsInPosition : (CGPoint) point AndWithText : (NSString *) title
- (void) showXLabel : (UILabel *) descriptionLabel InPosition : (CGPoint) point
{
CGRect frame = CGRectMake(point.x, point.y, 30, 10);
UILabel *descriptionLabel = [[UILabel alloc] initWithFrame:frame];
descriptionLabel.text = title;
descriptionLabel.frame = frame;
descriptionLabel.font = _descriptionTextFont;
descriptionLabel.textColor = _descriptionTextColor;
descriptionLabel.shadowColor = _descriptionTextShadowColor;
... ... @@ -180,40 +191,38 @@
- (void)setChartData:(NSArray *)data
{
if (data != _chartData) {
__block CGFloat yFinilizeValue , xFinilizeValue;
__block CGFloat yValue , xValue;
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
pathAnimation.duration = _duration;
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
pathAnimation.fromValue = @(0.0f);
pathAnimation.toValue = @(1.0f);
pathAnimation.fillMode = kCAFillModeForwards;
self.layer.opacity = 1;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSThread sleepForTimeInterval:1];
// update UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
for (PNScatterChartData *chartData in data) {
for (NSUInteger i = 0; i < chartData.itemCount; i++) {
yValue = chartData.getData(i).y;
xValue = chartData.getData(i).x;
if (!(xValue >= _AxisX_minValue && xValue <= _AxisX_maxValue) || !(yValue >= _AxisY_minValue && yValue <= _AxisY_maxValue)) {
NSLog(@"input is not in correct range.");
exit(0);
}
xFinilizeValue = [self mappingIsForAxisX:true WithValue:xValue];
yFinilizeValue = [self mappingIsForAxisX:false WithValue:yValue];
CAShapeLayer *shape = [self drawingPointsForChartData:chartData AndWithX:xFinilizeValue AndWithY:yFinilizeValue];
[self.layer addSublayer:shape];
self.pathLayer = shape ;
[self.pathLayer addAnimation:pathAnimation forKey:@"fade"];
__block CGFloat yFinilizeValue , xFinilizeValue;
__block CGFloat yValue , xValue;
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
pathAnimation.duration = _duration;
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
pathAnimation.fromValue = @(0.0f);
pathAnimation.toValue = @(1.0f);
pathAnimation.fillMode = kCAFillModeForwards;
self.layer.opacity = 1;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSThread sleepForTimeInterval:1];
// update UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
for (PNScatterChartData *chartData in data) {
for (NSUInteger i = 0; i < chartData.itemCount; i++) {
yValue = chartData.getData(i).y;
xValue = chartData.getData(i).x;
if (!(xValue >= _AxisX_minValue && xValue <= _AxisX_maxValue) || !(yValue >= _AxisY_minValue && yValue <= _AxisY_maxValue)) {
NSLog(@"input is not in correct range.");
exit(0);
}
xFinilizeValue = [self mappingIsForAxisX:true WithValue:xValue];
yFinilizeValue = [self mappingIsForAxisX:false WithValue:yValue];
CAShapeLayer *shape = [self drawingPointsForChartData:chartData AndWithX:xFinilizeValue AndWithY:yFinilizeValue];
self.pathLayer = shape ;
[self.layer addSublayer:self.pathLayer];
[self.pathLayer addAnimation:pathAnimation forKey:@"fade"];
}
});
}
});
}
});
}
- (CGFloat) mappingIsForAxisX : (BOOL) isForAxisX WithValue : (CGFloat) value{
... ... @@ -231,52 +240,79 @@
return 0;
}
#pragma mark - Update Chart Data
- (void)updateChartData:(NSArray *)data
{
_chartData = data;
// will be work in future.
}
#pragma drawing methods
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
if (_showCoordinateAxis) {
CGContextSetStrokeColorWithColor(context, [_axisColor CGColor]);
CGContextSetLineWidth(context, _axisWidth);
//drawing x vector
CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
CGContextAddLineToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
//drawing y vector
CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
CGContextAddLineToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
//drawing x arrow vector
CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y + 3);
CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y - 3);
//drawing y arrow vector
CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
CGContextAddLineToPoint(context, _endPointVecotrY.x - 3, _endPointVecotrY.y + 5);
CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
CGContextAddLineToPoint(context, _endPointVecotrY.x + 3, _endPointVecotrY.y + 5);
}
CGContextRef context = UIGraphicsGetCurrentContext();
if (_showCoordinateAxis) {
CGContextSetStrokeColorWithColor(context, [_axisColor CGColor]);
CGContextSetLineWidth(context, _axisWidth);
//drawing x vector
CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
CGContextAddLineToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
//drawing y vector
CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
CGContextAddLineToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
//drawing x arrow vector
CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y + 3);
CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y - 3);
//drawing y arrow vector
CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
CGContextAddLineToPoint(context, _endPointVecotrY.x - 3, _endPointVecotrY.y + 5);
CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
CGContextAddLineToPoint(context, _endPointVecotrY.x + 3, _endPointVecotrY.y + 5);
}
if (_showLabel) {
NSString *str;
//drawing x steps vector and putting axis x labels
float temp = _startPointVectorX.x + (_vectorX_Steps / 2) ;
for (int i = 0; i < _AxisX_partNumber; i++) {
CGContextMoveToPoint(context, temp, _startPointVectorX.y - 2);
CGContextAddLineToPoint(context, temp, _startPointVectorX.y + 3);
str = [_axisX_labels objectAtIndex:i];
[self showXLabelsInPosition:CGPointMake(temp - 15, _startPointVectorX.y + 10 ) AndWithText:str];
for (int i = 0; i < _axisX_labels.count; i++) {
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(temp, _startPointVectorX.y - 2)];
[path addLineToPoint:CGPointMake(temp, _startPointVectorX.y + 3)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [_axisColor CGColor];
shapeLayer.lineWidth = _axisWidth;
shapeLayer.fillColor = [_axisColor CGColor];
[self.horizentalLinepathLayer addObject:shapeLayer];
[self.layer addSublayer:shapeLayer];
UILabel *lb = [_axisX_labels objectAtIndex:i] ;
str = lb.text;
[self showXLabel:lb InPosition:CGPointMake(temp - 15, _startPointVectorX.y + 10 )];
temp = temp + _vectorX_Steps ;
}
//drawing y steps vector and putting axis x labels
temp = _startPointVectorY.y - (_vectorY_Steps / 2) ;
for (int i = 0; i < _AxisY_partNumber; i++) {
CGContextMoveToPoint(context, _startPointVectorY.x - 3, temp);
CGContextAddLineToPoint(context, _startPointVectorY.x + 2, temp);
str = [_axisY_labels objectAtIndex:i];
[self showXLabelsInPosition:CGPointMake(_startPointVectorY.x - 30, temp - 5) AndWithText:str];
for (int i = 0; i < _axisY_labels.count; i++) {
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(_startPointVectorY.x - 3, temp)];
[path addLineToPoint:CGPointMake( _startPointVectorY.x + 2, temp)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [_axisColor CGColor];
shapeLayer.lineWidth = _axisWidth;
shapeLayer.fillColor = [_axisColor CGColor];
[self.verticalLineLayer addObject:shapeLayer];
[self.layer addSublayer:shapeLayer];
UILabel *lb = [_axisY_labels objectAtIndex:i];
str = lb.text;
[self showXLabel:lb InPosition:CGPointMake(_startPointVectorY.x - 30, temp - 5)];
temp = temp - _vectorY_Steps ;
}
}
... ...
... ... @@ -16,6 +16,7 @@
@property (nonatomic) PNBarChart * barChart;
@property (nonatomic) PNCircleChart * circleChart;
@property (nonatomic) PNPieChart *pieChart;
@property (nonatomic) PNScatterChart *scatterChart;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
... ...
... ... @@ -7,6 +7,7 @@
//
#import "PCChartViewController.h"
#define ARC4RANDOM_MAX 0x100000000
@implementation PCChartViewController
... ... @@ -120,6 +121,41 @@
[self.view addSubview:self.pieChart];
self.changeValueButton.hidden = YES;
}
else if ([self.title isEqualToString:@"Scatter Chart"])
{
self.titleLabel.text = @"Scatter Chart";
self.scatterChart = [[PNScatterChart alloc] initWithFrame:CGRectMake(SCREEN_WIDTH /6.0 - 30, 135, 280, 200)];
[self.scatterChart setAxisXWithMinimumValue:20 andMaxValue:100 toTicks:6];
[self.scatterChart setAxisYWithMinimumValue:30 andMaxValue:50 toTicks:5];
NSArray * data01Array = [self randomSetOfObjects];
PNScatterChartData *data01 = [PNScatterChartData new];
data01.strokeColor = PNGreen;
data01.fillColor = PNFreshGreen;
data01.size = 2;
data01.itemCount = [[data01Array objectAtIndex:0] count];
data01.inflexionPointStyle = PNScatterChartPointStyleCircle;
__block NSMutableArray *XAr1 = [NSMutableArray arrayWithArray:[data01Array objectAtIndex:0]];
__block NSMutableArray *YAr1 = [NSMutableArray arrayWithArray:[data01Array objectAtIndex:1]];
data01.getData = ^(NSUInteger index) {
CGFloat xValue = [[XAr1 objectAtIndex:index] floatValue];
CGFloat yValue = [[YAr1 objectAtIndex:index] floatValue];
return [PNScatterChartDataItem dataItemWithX:xValue AndWithY:yValue];
};
[self.scatterChart setup];
self.scatterChart.chartData = @[data01];
/***
this is for drawing line to compare
CGPoint start = CGPointMake(20, 35);
CGPoint end = CGPointMake(80, 45);
[self.scatterChart drawLineFromPoint:start ToPoint:end WithLineWith:2 AndWithColor:PNBlack];
***/
self.scatterChart.delegate = self;
self.changeValueButton.hidden = YES;
[self.view addSubview:self.scatterChart];
}
}
... ... @@ -171,6 +207,10 @@
{
[self.circleChart updateChartByCurrent:@(arc4random() % 100)];
}
else if ([self.title isEqualToString:@"Scatter Chart"])
{
// will be code soon.
}
}
... ... @@ -195,4 +235,19 @@
[bar.layer addAnimation:animation forKey:@"Float"];
}
/* this function is used only for creating random points */
- (NSArray *) randomSetOfObjects{
NSMutableArray *array = [NSMutableArray array];
NSString *LabelFormat = @"%1.f";
NSMutableArray *XAr = [NSMutableArray array];
NSMutableArray *YAr = [NSMutableArray array];
for (int i = 0; i < 25 ; i++) {
[XAr addObject:[NSString stringWithFormat:LabelFormat,(((double)arc4random() / ARC4RANDOM_MAX) * (self.scatterChart.AxisX_maxValue - self.scatterChart.AxisX_minValue) + self.scatterChart.AxisX_minValue)]];
[YAr addObject:[NSString stringWithFormat:LabelFormat,(((double)arc4random() / ARC4RANDOM_MAX) * (self.scatterChart.AxisY_maxValue - self.scatterChart.AxisY_minValue) + self.scatterChart.AxisY_minValue)]];
}
[array addObject:XAr];
[array addObject:YAr];
return (NSArray*) array;
}
@end
... ...
... ... @@ -7,7 +7,6 @@
//
#import "PCChartsTableViewController.h"
#define ARC4RANDOM_MAX 0x100000000
@implementation PCChartsTableViewController
... ... @@ -44,76 +43,9 @@
} else if ([segue.identifier isEqualToString:@"scatterChart"])
{
//Add scatter chart
UILabel * scatterChartLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 90, SCREEN_WIDTH, 30)];
scatterChartLabel.text = @"Scatter Chart";
scatterChartLabel.textColor = PNFreshGreen;
scatterChartLabel.font = [UIFont fontWithName:@"Avenir-Medium" size:23.0];
scatterChartLabel.textAlignment = NSTextAlignmentCenter;
PNScatterChart *scatterChart = [[PNScatterChart alloc] initWithFrame:CGRectMake(0, 0, 280, 200)];
[scatterChart setAxisXWithMinimumValue:20 andMaxValue:100 toTicks:6];
[scatterChart setAxisYWithMinimumValue:30 andMaxValue:50 toTicks:5];
NSArray * data01Array = [self randomSetOfObjectsForScatterChart:scatterChart];
PNScatterChartData *data01 = [PNScatterChartData new];
data01.strokeColor = PNGreen;
data01.fillColor = PNFreshGreen;
data01.size = 2;
data01.itemCount = [[data01Array objectAtIndex:0] count];
data01.inflexionPointStyle = PNScatterChartPointStyleCircle;
__block NSMutableArray *XAr1 = [NSMutableArray arrayWithArray:[data01Array objectAtIndex:0]];
__block NSMutableArray *YAr1 = [NSMutableArray arrayWithArray:[data01Array objectAtIndex:1]];
data01.getData = ^(NSUInteger index) {
CGFloat xValue = [[XAr1 objectAtIndex:index] floatValue];
CGFloat yValue = [[YAr1 objectAtIndex:index] floatValue];
return [PNScatterChartDataItem dataItemWithX:xValue AndWithY:yValue];
};
NSArray * data02Array = [self randomSetOfObjectsForScatterChart:scatterChart];
PNScatterChartData *data02 = [PNScatterChartData new];
data02.strokeColor = PNBlue;
data02.fillColor = PNBlue;
data02.size = 2;
data02.itemCount = [[data02Array objectAtIndex:0] count];
data02.inflexionPointStyle = PNScatterChartPointStyleCircle;
__block NSMutableArray *XAr2 = [NSMutableArray arrayWithArray:[data02Array objectAtIndex:0]];
__block NSMutableArray *YAr2 = [NSMutableArray arrayWithArray:[data02Array objectAtIndex:1]];
data02.getData = ^(NSUInteger index) {
CGFloat xValue = [[XAr2 objectAtIndex:index] floatValue];
CGFloat yValue = [[YAr2 objectAtIndex:index] floatValue];
return [PNScatterChartDataItem dataItemWithX:xValue AndWithY:yValue];
};
[scatterChart setup];
scatterChart.chartData = @[data01 , data02];
// this is for drawing line to compare
CGPoint start = CGPointMake(20, 35);
CGPoint end = CGPointMake(80, 45);
[scatterChart drawLineFromPoint:start ToPoint:end WithLineWith:2 AndWithColor:PNBlack];
scatterChart.delegate = self;
[viewController.view addSubview:scatterChartLabel];
[viewController.view addSubview:scatterChart];
viewController.title = @"Scatter Chart";
}
}
/* this function is used only for creating random points */
- (NSArray *) randomSetOfObjectsForScatterChart:(PNScatterChart *)chart{
NSMutableArray *array = [NSMutableArray array];
NSString *LabelFormat = @"%1.f";
NSMutableArray *XAr = [NSMutableArray array];
NSMutableArray *YAr = [NSMutableArray array];
for (int i = 0; i < 25 ; i++) {
[XAr addObject:[NSString stringWithFormat:LabelFormat,(((double)arc4random() / ARC4RANDOM_MAX) * (chart.AxisX_maxValue - chart.AxisX_minValue) + chart.AxisX_minValue)]];
[YAr addObject:[NSString stringWithFormat:LabelFormat,(((double)arc4random() / ARC4RANDOM_MAX) * (chart.AxisY_maxValue - chart.AxisY_minValue) + chart.AxisY_minValue)]];
}
[array addObject:XAr];
[array addObject:YAr];
return (NSArray*) array;
}
@end
... ...