I want to draw a pie chart with some thickness. I have generated simple 2D pie chart. is there any way to make it 3D using some concepts of CALayer and then rotating in some direction.
-(void)CreatePieChart
{
graph = [[CPXYGraph alloc] initWithFrame: CGRectZero];
//CPGraphHostingView *hostingView = (CPGraphHostingView *)self.view;
viewGraphHostingPie.hostedGraph=graph;
CPPieChart *pieChart = [[CPPieChart alloc] init];
pieChart.dataSource = self;
pieChart.delegate = self;
pieChart.pieRadius = 100.0;
pieChart.identifier = #"PieChart1";
pieChart.startAngle=0;
pieChart.sliceDirection = CPPieDirectionCounterClockwise;
NSMutableArray *ValueArray = [[NSMutableArray alloc]init];
ValueArray = [NSArray arrayWithObjects:[NSNumber numberWithDouble:57.03],[NSNumber numberWithDouble:66.00],[NSNumber numberWithDouble:77.03],nil];
self.pieData = ValueArray;
CPTheme *theme = [CPTheme themeNamed:kCPDarkGradientTheme];
[graph applyTheme:theme];
[graph addPlot:pieChart];
[pieChart release];
}
It's not clear to me what you mean by "concepts of CALayer".
Have you considered using a free third party solution which will give you various charts, including pie charts, out of the box? Core Plot is free.
EDIT: Core Plot is 2D only, but you can produce a 3D effect by using shadows and/or overlay fill. See also the accepted answer here.
Related
I was using GPUImage framework (some old version) to blend two images (adding border overlay to a certain image).
After I have updated to latest framework version, after applying such a blend, I get an empty black image.
I'm using next method:
- (void)addBorder {
if (currentBorder != kBorderInitialValue) {
GPUImageAlphaBlendFilter *blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
GPUImagePicture *imageToProcess = [[GPUImagePicture alloc] initWithImage:self.imageToWorkWithView.image];
GPUImagePicture *border = [[GPUImagePicture alloc] initWithImage:self.imageBorder];
blendFilter.mix = 1.0f;
[imageToProcess addTarget:blendFilter];
[border addTarget:blendFilter];
[imageToProcess processImage];
self.imageToWorkWithView.image = [blendFilter imageFromCurrentlyProcessedOutput];
[blendFilter release];
[imageToProcess release];
[border release];
}
}
What is the problem?
You're forgetting to process the border image. After [imageToProcess processImage], add the line:
[border processImage];
For a two images being input into a blend, you have to use -processImage on both after they have been added to the blend filter. I changed the way that the blend filter works in order to fix some bugs, and this is how you need to do things now.
This is the code I'm currently using for merging two images with GPUImageAlphaBlendFilter.
GPUImagePicture *mainPicture = [[GPUImagePicture alloc] initWithImage:image];
GPUImagePicture *topPicture = [[GPUImagePicture alloc] initWithImage:blurredImage];
GPUImageAlphaBlendFilter *blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
[blendFilter setMix:0.5];
[mainPicture addTarget:blendFilter];
[topPicture addTarget:blendFilter];
[blendFilter useNextFrameForImageCapture];
[mainPicture processImage];
[topPicture processImage];
UIImage * mergedImage = [blendFilter imageFromCurrentFramebuffer];
i was just browsing the classes for an hour and cant find it! i started with searching the example of the AAPLot project.
i changed the graph a bit and was expecting to find all settings in the CPTTradingRangePlot class but it´s not there.
there are a lot of properties which i can change, but i can´t find the background settings in any of the classes.
could anybody give me a hint?
// OHLC plot
CPTMutableLineStyle *whiteLineStyle = [CPTMutableLineStyle lineStyle];
whiteLineStyle.lineColor = [CPTColor whiteColor];
whiteLineStyle.lineWidth = 1.0f;
CPTTradingRangePlot *ohlcPlot = [[[CPTTradingRangePlot alloc] initWithFrame:graph.bounds] autorelease];
ohlcPlot.identifier = #"OHLC";
ohlcPlot.lineStyle = whiteLineStyle;
ohlcPlot.barWidth = 4.0f;
ohlcPlot.increaseFill = [(CPTFill *)[CPTFill alloc] initWithColor:[CPTColor greenColor]];
ohlcPlot.decreaseFill = [(CPTFill *)[CPTFill alloc] initWithColor:[CPTColor redColor]];
CPTMutableTextStyle *whiteTextStyle = [CPTMutableTextStyle textStyle];
whiteTextStyle.color = [CPTColor whiteColor];
whiteTextStyle.fontSize = 12.0;
ohlcPlot.labelTextStyle = whiteTextStyle;
ohlcPlot.labelOffset = 5.0;
ohlcPlot.stickLength = 2.0f;
ohlcPlot.dataSource = self;
ohlcPlot.plotStyle = CPTTradingRangePlotStyleCandleStick;
[graph addPlot:ohlcPlot];
Here's a very simple example. This:
CPTColor *your_color = [CPTColor colorWithComponentRed:1 green:0 blue:0 alpha:1];
your_graph.fill = [CPTFill fillWithColor:your_color];
will turn your graph's background red. But as Eric Skroch said, you may want to do this...
your_graph.plotAreaFrame.fill = [CPTFill fillWithColor:your_color];
and / or this...
your_graph.plotAreaFrame.plotArea.fill = [CPTFill fillWithColor:your_color];
depending on the result you want to achieve.
Backgrounds in Core Plot are set using CPTFill objects similar to the increaseFill and decreaseFill in your code sample. Depending on the look you want to achieve, you need to set the fill on graph, graph.plotAreaFrame, and/or graph.plotAreaFrame.plotArea. The axis demo in the Mac version of CPTTestApp uses fills in all three areas so you can see the different parts.
You may set it in xAxis or yAxis using CPTColor.
axisSet.yAxis.alternatingBandFills = [NSArray arrayWithObjects:[CPTColor redColor],
[CPTColor whiteColor], [CPTColor purpleColor], nil];
i finally found it by myself. the background of the chart is managed by a theme. there are several theme files in the folder theme of the core-plot library and one of them is CPTStocksTheme. The CPTStocksTheme creates a blue gradient background which can be changed there.
I have write following code to show bar plot annotation. Annotations are shown but with unexpected alignment/position. Text of CPTextLayer is showing at top-left corner of the frame. I am trying to show it at center. I have used a background image of the CPTextLayer as background color. Please have a look through the code- (symbolTextAnnotation is a CPLayerAnnotation object decleared in the interface)
-(void)barPlot:(CPBarPlot *)plot barWasSelectedAtRecordIndex:(NSUInteger)index
{
CPXYGraph* graph = (CPXYGraph*)plot.graph;
NSNumber *value = [self numberForPlot:plot field:CPBarPlotFieldBarTip recordIndex:index];
if ( symbolTextAnnotation ) {
[graph.plotAreaFrame.plotArea removeAnnotation:symbolTextAnnotation];
symbolTextAnnotation = nil;
}
// Setup a style for the annotation
CPMutableTextStyle *hitAnnotationTextStyle = [CPMutableTextStyle textStyle];
hitAnnotationTextStyle.color = [CPColor whiteColor];
hitAnnotationTextStyle.fontSize = 9.0f;
hitAnnotationTextStyle.fontName = #"Helvetica-Bold";
// Determine point of symbol in plot coordinates
NSNumber *x = [NSNumber numberWithInt:index+1];
NSNumber *y = [NSNumber numberWithInt:0];
NSArray *anchorPoint = [NSArray arrayWithObjects:y, x, nil];
// Add annotation
// First make a string for the y value
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setMaximumFractionDigits:2];
NSString *yString = [formatter stringFromNumber:value];
// Now add the annotation to the plot area
UIImage *annotationBG = [UIImage imageNamed:#"annotation-bg.png"];
CPTextLayer *textLayer = [[[CPTextLayer alloc] initWithText:yString style:hitAnnotationTextStyle] autorelease];
textLayer.backgroundColor = [UIColor colorWithPatternImage:annotationBG].CGColor;
textLayer.frame = CGRectMake(0, 0, annotationBG.size.width, annotationBG.size.height);
symbolTextAnnotation = [[CPPlotSpaceAnnotation alloc] initWithPlotSpace:plot.plotSpace anchorPlotPoint:anchorPoint];
symbolTextAnnotation.contentLayer = textLayer;
symbolTextAnnotation.displacement = CGPointMake(-18.0f, 3.0f);
[graph.plotAreaFrame.plotArea addAnnotation:symbolTextAnnotation];
}
CPTextLayer sizes itself to the size of its text. Resizing it after setting the text is causing the drawing problem. You could make another CPLayer, set your background on that, make your CPTextLayer a sublayer, and position it however you want.
The displacement property works with the contentAnchorPoint property to position the annotation. The contentAnchorPoint is the Core Animation anchor point for your content layer. The displacement is the pixel offset of that point from the anchorPlotPoint of the annotation. For example, if you want your annotation centered at the anchorPlotPoint, set the contentAnchorPoint to CGPointMake(0.5, 0.5) and the displacement to CGPointZero.
I'm using Core-Plot for a trend chart in an iPhone app and haven't found how to customize the background. I can create a theme using the built-in themes, like kCPPlainWhiteTheme, but how can I change them? or create a new one?
What i basically need to do is make the background transparent.
EDIT / UPDATE
I jus tested this code but it doesn't seem to work:
//CPTheme *theme = [CPTheme themeNamed:kCPPlainWhiteTheme];
CPTheme *theme = [[CPTheme alloc]init];
chartTrend5 = (CPXYGraph *)[theme newGraph];
chartView.hostedGraph = chartTrend5;
chartTrend5.paddingLeft = 0.0;
chartTrend5.paddingTop = 0.0;
chartTrend5.paddingRight = 0.0;
chartTrend5.paddingBottom = 0.0;
chartTrend5.fill = nil;
chartTrend5.borderLineStyle = nil;
chartView.hostedGraph.fill = nil;
chartTrend5PlotSpace = (CPXYPlotSpace *)chartTrend5.defaultPlotSpace;
chartTrend5PlotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0)
length:CPDecimalFromFloat(5)];
// range is 0-125, but since the frame heights is 90,
// we need to convert the points to this adjusted scale. The factor is 0.72 => (90/125)
chartTrend5PlotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0)
length:CPDecimalFromFloat(90)];
CPXYAxisSet *axisSet = (CPXYAxisSet *)chartTrend5.axisSet;
CPXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPDecimalFromFloat(100);
//x.constantCoordinateValue = CPDecimalFromFloat(2);
x.minorTicksPerInterval = 2;
x.borderWidth = 0;
x.labelExclusionRanges = [NSArray arrayWithObjects:
[CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-1)
length:CPDecimalFromFloat(800)],
nil];;
CPXYAxis *y = axisSet.yAxis;
y.majorIntervalLength = CPDecimalFromFloat(100);
y.minorTicksPerInterval = 1;
//y.constantCoordinateValue = length:CPDecimalFromFloat(2);
y.labelExclusionRanges = [NSArray arrayWithObjects:
[CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-26)
length:CPDecimalFromFloat(100)],
nil];
CPScatterPlot *dataSourceLinePlot = [[[CPScatterPlot alloc] init] autorelease];
dataSourceLinePlot.identifier = #"TrendChart";
dataSourceLinePlot.dataLineStyle.lineWidth = 2.f;
dataSourceLinePlot.dataLineStyle.lineColor = [CPColor colorWithComponentRed:(16/255.f)
green:(101/255.f)
blue:(122/255.f)
alpha:1];
dataSourceLinePlot.dataSource = self;
[chartTrend5 addPlot:dataSourceLinePlot];
chartTrend5.fill = nil;
// Put an area gradient under the plot above
CPColor *areaColor = [CPColor colorWithComponentRed:(212/255.f)
green:(233/255.f)
blue:(216/255.f)
alpha:1];
CPGradient *areaGradient = [CPGradient gradientWithBeginningColor:areaColor
endingColor:areaColor];
areaGradient.angle = -90.0f;
CPFill *areaGradientFill = [CPFill fillWithGradient:areaGradient];
dataSourceLinePlot.areaFill = areaGradientFill;
dataSourceLinePlot.areaBaseValue = CPDecimalFromString(#"5.25");
here I set the the fill property of CPXYGraph *chartTrend5 and *CPXYPlotSpace *chartTrend5PlotSpace to nil.
In addition to what Eric suggests, you can also try setting the fill to a clear color. For example, I've used this in the past to provide a transparent background to graphs:
CPTTheme *theme = [CPTTheme themeNamed:kCPPlainWhiteTheme];
graph = (CPTXYGraph *)[theme newGraph];
graph.fill = [CPTFill fillWithColor:[CPTColor clearColor]];
graph.plotAreaFrame.fill = [CPTFill fillWithColor:[CPTColor clearColor]];
Themes are just a convenient way to set a lot of the style properties at once. You can set any of them individually to customize the look. Any time you want an area to be transparent, you can set its fill to nil. Same with line styles--set them to nil to prevent a line from being drawn.
There are two "background" areas that you might be concerned with. The graph has a fill as does the plot area. The plot area is the region where the plots are drawn. Set the fill property on both of these to nil to make the background transparent.
I tried this & it works for me:
// Here 'hostingView' is your CPTGraphHostingView to
// which you add your graph
UIImageView *backgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
[hostingView addSubview:backgorundImage];
[hostingView sendSubviewToBack:backgroundImage];
I used the .fill and .plot.AreaFrame.fill properties :
plot = [[CPTXYGraph alloc] initWithFrame:CGRectZero];
CPTTheme *theme = [CPTTheme themeNamed:kCPTSlateTheme];
[plot applyTheme:theme];
self.graph.collapsesLayers = NO;
self.graph.hostedGraph = plot;
plot.paddingLeft = 1.0;
plot.paddingTop = 1.0;
plot.paddingRight = 1.0;
plot.paddingBottom = 1.0;
plot.fill = [CPTFill fillWithColor:[CPTColor clearColor]];
plot.plotAreaFrame.fill = [CPTFill fillWithColor:[CPTColor clearColor]];
This works for me.
I am trying to remove the border around a core plot graph on the iPhone - but seem to be struggling on what should be simple in my mind.
Pointers please!
You should be able to nil out the borderLineStyle on the graph's plotArea to remove the border:
graph.plotAreaFrame.borderLineStyle = nil; // don't draw a border
You could also create your own theme, using the ones in the framework as examples, and simply not set the borderLineStyle in that.
None of the answers worked for me. This did the job:
graph.paddingLeft = 0;
graph.paddingRight = 0;
graph.paddingTop = 0;
graph.paddingBottom = 0;
graph.plotAreaFrame.borderWidth = 0;
graph.plotAreaFrame.cornerRadius = 0;
OK I found out how to do it - quite simple really!
CPLineStyle *borderLineStyle = [CPLineStyle lineStyle];
borderLineStyle.lineColor = [CPColor whiteColor];
borderLineStyle.lineWidth = 1.0;
graph.plotArea.borderLineStyle = borderLineStyle;
where graph is your graph object - the reason I had a border in the first place was because I used CPPlainWhiteTheme.
Hope this helps others - is there a better way?
You can set any line style to nil. This will cause the line to not be drawn at all.
In CorePlot 1.0, the structure of CPTGraph has changed slightly. The code for removing the border line of a graph, assuming that graph is of type GPTGraph or a subclass of CPTGraph, is
graph.plotAreaFrame.borderLineStyle = nil;
The correct way with borderLineStyle = nil after applyTheme:
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:hostView.bounds];
// Set padding for plot area
[graph applyTheme:[CPTTheme themeNamed:kCPTPlainWhiteTheme]];
graph.plotAreaFrame.borderLineStyle = nil;
If, like me, you are looking to not just remove the border line, but to make a plot that takes up the entire hosting view, the answer from Thomas Johannesmeyer got me on the right track.
Here's what I did:
CPTGraphHostingView* hostingView = [[CPTGraphHostingView alloc] initWithFrame: frame];
CGRect bounds = hostingView.bounds;
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:bounds];
hostingView.hostedGraph = graph;
graph.paddingTop = CPTFloat(0.0);
graph.paddingRight = CPTFloat(0.0);
graph.paddingBottom = CPTFloat(0.0);
graph.paddingLeft = CPTFloat(0.0);
graph.plotAreaFrame.paddingTop = CPTFloat(0.0);
graph.plotAreaFrame.paddingRight = CPTFloat(0.0);
graph.plotAreaFrame.paddingBottom = CPTFloat(0.0);
graph.plotAreaFrame.paddingLeft = CPTFloat(0.0);
graph.plotAreaFrame.masksToBorder = NO;
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTXYAxis *x = axisSet.xAxis;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.title = nil;
CPTXYAxis *y = axisSet.yAxis;
y.labelingPolicy = CPTAxisLabelingPolicyNone;
y.title = nil;