I'm using CorePlot to draw a bar chart according to a specific design, and I'm having trouble getting the ticks on my Y-Axis centred. By that I mean that half the tick should be on the left side of the axis, and the other half on the right.
Here's the code I'm using so far:
CPTLineStyle *majorTickStyle = [[CPTMutableLineStyle alloc] init];
majorTickStyle.lineColor = GlobalColors.lightPinkColor.CPTColor;
CPTLineStyle *minorTickStyle = [[CPTMutableLineStyle alloc] init];
minorTickStyle.lineColor = GlobalColors.greyColor.CPTColor;
CPTXYAxis *y = axisSet.yAxis;
//y.titleOffset = 50.0f;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.majorGridLineStyle = majorGridLineStyle;
y.minorGridLineStyle = minorGridLineStyle;
y.axisConstraints = [CPTConstraints constraintWithUpperOffset:0];
y.tickDirection = CPTSignPositive;
y.majorTickLineStyle = majorTickStyle;
y.majorTickLength = 10;
y.minorTickLineStyle = minorTickStyle;
y.labelTextStyle = axisLabelStyle;
The image on the left is what the code above gave me, and the right is what the designer presented (i.e. what I'm trying to achieve):
(I'm not too worried abut the number of ticks, and the "L" on the end of the number is a separate issue entirely)
This isn't supported right now. Please add an enhancement request on the Core Plot issue tracker.
In the mean time, you could use custom axis labels (CPTAxisLabelingPolicyNone) and offset the label locations from the tick locations slightly.
If your app requires iOS 6 or later, Core Plot added support for attributed text in labels after release 1.2. This would make adding the small "L" easy. This would also require custom axis labels.
Related
I have a CorePlot graph that i'm trying to change to be a different color. I have changed all the labels, and the axes, the grid lines, the title, to be this uniform color. Only thing I'm having trouble is changing the color of the tick marks that correspond to values on the y and x axis. I'm sure it's one line of code to do this but I've looked through the documentation and couldn't find anything that corresponded to this. I figured changing the color the grid lines would change the color the tick marks since they are a extension of the grid lines outsides the axes. I can attach a picture if this is hard to visualize what I'm referring to. Thanks for any help on this simple issue.
Set the majorTickLineStyle for the major tick marks and the minorTickLineStyle for the minor ticks.
First set up a MutableLineStyle:
// Configure Line-Style //
CPTMutableLineStyle *tickLineStyle = [CPTMutableLineStyle lineStyle];
tickLineStyle.lineWidth = 1.0f;
tickLineStyle.lineColor = [CPTColor blackColor];
Get a reference to the axisSet //
// Get the Graph's axis set //
CPTXYAxisSet *axisSet = (CPTXYAxisSet *) self.hostViewRRDataValues.hostedGraph.axisSet;
Then apply the LineStyle to for the minor and major Tick //
axisSet.yAxis.minorTickLineStyle = tickLineStyle;
axisSet.yAxis.majorTickLineStyle = tickLineStyle;
Or set to nil if you do not want any thick marks at all
axisSet.yAxis.minorTickLineStyle = nil; // No minorTickLines
axisSet.yAxis.majorTickLineStyle = nil; // No majorTickLines
I'm working with Core Plot 1.1 to draw a simple scatter plot in iOS6. I am using the following code to properly format my y-axis which then dynamically scales to the plot data.
CPTXYAxis *y = axisSet.yAxis;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.minorTicksPerInterval = 3;
y.preferredNumberOfMajorTicks = 6;
y.majorGridLineStyle = majorGridLineStyle;
y.minorGridLineStyle = minorGridLineStyle;
...
NSNumberFormatter * yformatter = [[NSNumberFormatter alloc] init];
[yformatter setUsesSignificantDigits:YES];
[yformatter setMaximumSignificantDigits:4];
[yformatter setMaximumFractionDigits:1];
[yformatter setRoundingMode:NSNumberFormatterRoundCeiling];
y.labelFormatter = yformatter;
Then I dynamically change the range based on the data to be plotted using maxPlotValue but bound it to a minimum.
plotSpace.xRange = [CPTPlotRange
plotRangeWithLocation:CPTDecimalFromFloat(0)
length:CPTDecimalFromFloat(5)];
plotSpace.yRange = [CPTPlotRange
plotRangeWithLocation:CPTDecimalFromFloat(0)
length:CPTDecimalFromFloat(maxPlotValue)];
This works great in most cases but sometimes I get a strange formatting error like in the below fig 1 where 0.6001 is displayed in stead of 0.6. If I manually change the minimum range to 2 the error disappears.
The reason I'm using 4 significant digits is that I can have numbers up to 8000 and then they are displayed without the fraction. If I change the setMaximumSignificantDigits to 3 I get 0.601 which I guess indicates that the problem is with the CPTAxisLabelingPolicyAutomatic.
Any help on this would be greatly appreciated.
Fig 1, Error in formatting:
https://dl.dropbox.com/u/8083213/fig_1.png
Fig 2, No error in formatting:
https://dl.dropbox.com/u/8083213/fig_2.png
This sounds like a rounding error in the labeling calculations. Please report it on the Core Plot issue tracker.
I have spent the last couple of days to use Core Plot for the first time. It took me some some figure out how it works but I could realize almost all features I was looking for. But for one thing I did not find a solution:
I am using a XY-Plot with labels on both axes. The plotAreaFrame has a left padding to shift the plotArea to the right and create some free space for the y axis labels. This works fine as long as the labels are not to big, e.g. for values up to 100. But if the y values become bigger, eg. 10.0000, the padding is not enough to show the complete label.
Of course I could just use a higher padding but this would waste space if I have only small y values.
Is there any way to autosize the padding according to the labels?
Andrei,
I realize this is an old question but perhaps this is a useful thought to you or others. I wonder if you can do a bit better than just guessing the padding size you need. How about this code snippet:
// set up the Y axis
float minY = 0;
float maxY = 100; // just some max value
float tickLength = 10; // just a pleasing value
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(minY) length:CPTDecimalFromFloat(maxY)];
// set up the line style for y axis
CPTMutableLineStyle * lineStyle = [CPTLineStyle lineStyle];
lineStyle.lineColor = [CPTColor blackColor];
lineStyle.lineWidth = 2.0f; // just picked a pleasing value
// set up the y axis
axisSet = [[CPTXYAxisSet alloc]init];
axisSet.yAxis.majorTickLength = tickLength;
// Now you can determine the size of the rectangle needed to display axis and labels by getting
// the axis font and measureing how many pixels were needed to draw the maximum Y axis label.
UIFont * font = [UIFont fontWithName:axisSet.yAxis.labelTextStyle.fontName size:axisSet.yAxis.labelTextStyle.fontSize];
NSString * maxYLabel = [axisSet.xAxis.labelFormatter stringFromNumber:[NSNumber numberWithDouble:plotSpace.yRange.maxLimitDouble] ];
CGSize textSize = [maxYLabel sizeWithFont:font];
// The offset you are looking for can now be computed by:
textSize.width + axisSet.yAxis.majorTickLength + axisSet.yAxis.labelOffset;
Anyway, I haven't testing the code above but the concept should apply I think...
After getting no answer here I looked all over the web but found no answer there either. The solution which now works for me is just checking the current range of the Y axis, look how many digits the value have and calculate the necessary width manually: number_of_digits * width_per_digit + fixed_padding
Of course this is only an estimation. But it is better that a fixed padding wich is too big for small numbers and too small for large number...
I've used the proposed solution by Yohst first. But then I realized that sometimes bigger number for the maximum range won't result in a bigger label, for example when the Y value is time (as on the screenshot below).
So I iterated over the labels of the axis to find the maximum width of the label and to set it as graph's left padding:
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)_graph.axisSet;
CPTXYAxis *yAxis = axisSet.yAxis;
[yAxis relabel];
CGFloat maxLabelWidth = 0;
for (CPTAxisLabel *label in yAxis.axisLabels) {
maxLabelWidth = MAX(maxLabelWidth, label.contentLayer.bounds.size.width);
}
_graph.plotAreaFrame.paddingLeft = /* extra padding + */ maxLabelWidth;
// force update axes because of the new padding
[axisSet relabelAxes];
[axisSet setNeedsLayout];
in the moment im wrestling with core plot, and I´m trying to achieve that the labels of my x-Axis are sticking to the bottom bounds of my graphView. Means:
when I set a range depending on the min/max Values of my PlotData I want to see the Labels everytime on the bottom of the graph.
This is how I set the AutoScaling to make the scaling depending on the min/max values to see only whats needed:
// Auto scale the plot space to fit the plot data
[plotSpace scaleToFitPlots:[NSArray arrayWithObjects:dataSourceLinePlot, nil]];
CPTMutablePlotRange *xRange = [[plotSpace.xRange mutableCopy] autorelease];
CPTMutablePlotRange *yRange = [[plotSpace.yRange mutableCopy] autorelease];
[xRange expandRangeByFactor:CPTDecimalFromDouble(1.0)];
[yRange expandRangeByFactor:CPTDecimalFromDouble(8.15)];
So when I now want to zoom the graph, the labels are staying where they are.
In some cases they´re not visible but they have to be visible all the time. Any tips?
Thanks in Advance
Cheers
// EDIT
I worked with the labelOffset already, but it´s not working when you want to zoom the view or the min/max values are changing.
If you want to have x-axis labels visible all the time even when zooming in, you should set CPTConstraints for the axis. The following code should do the trick:
CPTXYGraph *barchar = <#(create the chart here)#>
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)barChart.axisSet;
CPTXYAxis *xAxis = axisSet.xAxis;
CPTConstraints *axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0f];
xAxis.axisConstraints = axisConstraints;
i implemented an iPad application that uses a scatter plot (library: coreplot 0.9).
The plot data itself is displayed correctly, but the labels for the plot points are not displayed initially.
As soon as i drag the plot space, the labels show up as expected.
When i dynamically add a second plot to the graph (tap a special button for that) the lables of the first plot are shown, those of the second plot are not shown.
After a long time of trying to get it work and lots of web search i am pretty stuck here and would appreciate any ideas on that topic very much.
In the code example below i create my own plot space. The problem is the same for plots on the graph's default plot space.
…
graph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];
myPlotView.hostedGraph = graph;
[graph release];
…
myPlot = [[CPTScatterPlot alloc] init];
CPTMutableLineStyle *lineStyle = [[myPlot.dataLineStyle mutableCopy] autorelease];
lineStyle.lineWidth = 3.f;
lineStyle.lineColor = [CPTColor greenColor];
myPlot.dataLineStyle = lineStyle;
myPlot.dataSource = self;
myPlot.plotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
[myGraph addPlot:myPlot];
[myPlot release];
CPTMutableTextStyle *whiteTextStyle = [CPTMutableTextStyle textStyle];
whiteTextStyle.color = [CPTColor whiteColor];
myPlot.labelTextStyle = whiteTextStyle;
myPlot.labelOffset = -10.0;
myOwnPlotSpace = [[CPTXYPlotSpace alloc]init];
[myGraph addPlotSpace:myOwnPlotSpace];
myPlot.plotSpace = myOwnPlotSpace;
[myOwnPlotSpace release];
myOwnPlotSpace.delegate = self;
myOwnPlotSpace.allowsUserInteraction = YES;
myOwnPlotSpace.xRange = ((CPTXYPlotSpace *)(myGraph.defaultPlotSpace)).xRange;
…
These screenshots show the situation (since i am new to Stack Overflow, i am not yet allowed to post pictures):
Initial display of plot (lables not shown):
http://gallery.me.com/timoseeberger#100038/screenshot_graph_before&bgcolor=black
display of plot after dragging (lables are shown immediately):
http://gallery.me.com/timoseeberger#100038/screenshot_graph_after&bgcolor=black
Your problem appears to be related to a known Core Plot issue. See the Core Plot issue tracker for details and notification when it's fixed.
I'm having a somewhat similar problem (labels appear in the wrong place at first, then move to the correct location), and find that in my case setting collapsesLayers=NO on the host view works around the issue.