I'm trying to create a plot with both text and an image as the data labels for each point. The code I'm using looks like this;
//Point symbol
NSInteger symbolIndex = interval.symbolIndex;
UIImage *img = [Common getPointSymbol:symbolIndex];
CGRect imageRect = CGRectMake(0, 0 , 60, 50);
CPTBorderedLayer * imageLayer = [[CPTBorderedLayer alloc] initWithFrame:imageRect];
imageLayer.fill = [CPTFill fillWithImage:[CPTImage imageWithCGImage:[img CGImage] scale:img.scale]];
//Point text
CPTMutableTextStyle *dataLabelTextStyle = [CPTMutableTextStyle textStyle];
dataLabelTextStyle.color = [CPTColor blackColor];
dataLabelTextStyle.fontSize = 12.0f;
dataLabelTextStyle.fontName = #"Helvetica";
CPTTextLayer *textLayer = [[CPTTextLayer alloc] initWithText:point.title style:dataLabelTextStyle];
[imageLayer addSublayer:textLayer];
return imageLayer;
This works well for the data points that are initially visible on the plot, but for points which are outside the starting plot area only the symbol-images are drawn. If zooming out and forcing the plot to redraw, both layers will again appear. The same problem occurs if reversing the order of the layers, and then only the text layer is drawn. In effect, it seems sublayers are not rendered if starting outside the plot.
Is this a core plot bug? Is it possible to merge layers into one to mitigate this problem?
Thankful for help!
CPTTextLayer is a subclass of CPTBorderedLayer. You can add the background fill to the text layer and then use the padding properties to position the text within the layer.
Related
I'm trying to create a horizontal gradient on my y axis in CorePlot:
CPTGradient *axisGradient = [CPTGradient gradientWithBeginningColor:[CPTColor redColor] endingColor:[CPTColor yellowColor]];
axisGradient.angle = 180.f;
CPTMutableLineStyle *axisStyle = [y.axisLineStyle mutableCopy];
axisStyle.lineWidth = 6.f;
axisStyle.lineGradient = axisGradient;
y.axisLineStyle = axisStyle;
No matter what I set the gradient angle to the gradient is vertical. Anyone have any ideas?
for horizontal gradient you can use
CPTColor *areaColorStart = [CPTColor colorWithComponentRed:0.74 green:0.78 blue:0.82 alpha:1];
CPTColor *areaColorEnd = [CPTColor colorWithComponentRed:0.9 green:0.91 blue:0.92 alpha:.2];
CPTGradient *areaGradient1 = [CPTGradient gradientWithBeginningColor:areaColorStart endingColor:areaColorEnd];
areaGradient1.angle = 0.0f;
CPTFill *areaGradientFill = [CPTFill fillWithGradient:areaGradient1];
plot.areaFill = areaGradientFill;
plot.areaBaseValue = CPTDecimalFromFloat(yRange);
hope it will help.
Core Plot draws gradient line fills along the line path. If you want a tall, skinny rectangle filled with a gradient that fades from one color at the top to another at the bottom, use a plot space annotation. Create a CPTBorderedLayer for the annotation content and give it a gradient fill ([CPTFill fillWithGradient:axisGradient]).
I am using CorePlot for Scatter plot and would like to know how to obtain the circles of the scatter plot with such a color effect as it is here http://i.stack.imgur.com/7ZcqY.jpg
I would like to get the color as in CPTXYScatterPlot - Can I set the Z order of plot symbols?.
In your symbolForScatterPlot implementation, create a circlePlotSymbol with a gradient fill, like so:
CPTPlotSymbol *circlePlotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
// Obviously for a real bubble chart you'll want to get the color from somewhere so they're not all the same
CPTColor *endColor = [CPTColor redColor];
CPTColor *startColor = [endColor colorWithAlphaComponent:0.4f];
CPTGradient *gradient = [CPTGradient gradientWithBeginningColor:startColor endingColor:endColor];
Then set the gradient type to Radial, and set your gradient as the fill on your plotSymbol. If you want it to look like it's lit from an angle, you can set the startAnchor to a point off center:
gradient.gradientType = CPTGradientTypeRadial;
graphGradient.startAnchor = CGPointMake(0.35, 0.75);
circlePlotSymbol.fill = [CPTFill fillWithGradient:gradient];
If you don't want a border around your circles, set the linestyle color to clear and/or set the width to 0.0f (probably don't need to do both):
CPTMutableLineStyle *lineStyle = [[CPTMutableLineStyle alloc] init];
lineStyle.lineColor = [CPTColor clearColor];
lineStyle.lineWidth = 0.0f;
circlePlotSymbol.lineStyle = lineStyle;
[lineStyle release];
Set the size of your bubble:
// For a real bubble chart, you'll need to calculate this from your data
circlePlotSymbol.size = CGSizeMake(50.0f, 50.0f);
and return your plot symbol:
return circlePlotSymbol;
That should do it. I don't have my code in front of me so I'm going from memory here (and please forgive any typos or bad syntax, as I don't have access to a compiler right now either), but hopefully this will be close enough to get you pointed in the right direction.
I am drawing icons at custom tick locations in an xy graph with a scatter plot using Core Plot 1.0 on iOS 5. I've been having performance issues on the iPad 3 with allowing user interaction and scrolling the graph horizontally. I started looking into using the collapsesLayers property of CPTGraphHostingView as a potential solution. Enabling it works quite well for me except for one particular issue that I have not yet been able to solve. My custom axis labels set up to render images will not display. I'm wondering if anyone has any thoughts about what might be the cause. As near as I can tell the axis labels are still being positioned properly at the correct custom tick locations. The only difference in my external code is swapping collapsesLayers from NO to YES.
Here is how I am constructing the axis labels:
+ (CPTAxisLabel *)buildIconAxisLabelAtLocation:(CGFloat)location withImageNamed:(NSString *)imageName
{
CPTLayer *imageLayer = [[CPTLayer alloc] initWithFrame:CGRectMake(0, 0, 16, 16)];
UIImage *image = [UIImage imageNamed:imageName];
CALayer *imageSubLayer = [[CALayer alloc] init];
imageSubLayer.frame = imageLayer.frame;
imageSubLayer.contents = (id)image.CGImage;
[imageLayer addSublayer:imageSubLayer];
CPTAxisLabel *iconLabel = [[CPTAxisLabel alloc] initWithContentLayer:imageLayer];
iconLabel.offset = 8;
iconLabel.tickLocation = CPTDecimalFromCGFloat(location);
iconLabel.rotation = M_PI;
return iconLabel;
}
Any help is appreciated.
Every layer in a Core Plot graph should be a CPTLayer or a subclass. This has many implications for layout and drawing.
Core Plot doesn't render the layer contents. Use a CPTBorderedLayer with an image fill instead.
I would try something like this:
UIImage *image = [UIImage imageNamed:imageName];
CPTImage *background = [CPTImage imageWithCGImage:image.CGImage];
CPTBorderedLayer *imageLayer = [[CPTBorderedLayer alloc] initWithFrame:CGRectMake(0, 0, 16, 16)];
imageLayer.fill = [CPTFill fillWithImage:background];
I've set up a scattered plots with time as the x axis. I'm drawing a little sun image in the background at noon time:
CGRect imageRect = CGRectMake(0, 0 , 50, 50);
CPTBorderedLayer * imageLayer = [[CPTBorderedLayer alloc] initWithFrame:imageRect];
imageLayer.fill = [CPTFill fillWithImage:[CPTImage imageWithCGImage:[[UIImage imageNamed:#"SunIcon.png"] CGImage]]];
NSArray *anchorPoint = [NSArray arrayWithObjects:
[NSNumber numberWithInt:12*60*60], [NSNumber numberWithInt:100],
nil];
CPTPlotSpaceAnnotation *imageAnnotation1 = [[CPTPlotSpaceAnnotation alloc] initWithPlotSpace:(CPTXYPlotSpace *)graph.defaultPlotSpace anchorPlotPoint:anchorPoint];
imageAnnotation.contentLayer = imageLayer;
[graph addAnnotation:imageAnnotation];
[graph addSublayer:imageLayer];
The problem is that the sun now hides my plots. How can I send the image to the background behind all plots?
Edit: The opposite case is that my right aligned y axis gets hidden by the plot. Can I bring this layer to the front?
Add the annotation to the plot area and then move the image layer to the front of the sublayer order.
[graph.plotAreaFrame.plotArea addAnnotation:imageAnnotation];
[imageLayer removeFromSuperlayer];
[graph.plotAreaFrame.plotArea insertSublayer:imageLayer atIndex:0];
I need to rotate an UIImageView:
UIImageView *img = [[UIImageView alloc] init];
img.layer.borderWidth = 3.0;
img.layer.borderColor = UIColorFromRGB(0xffffff).CGColor;
img.layer.shadowColor = UIColorFromRGB(0x000000).CGColor;
CATransform3D transform = CATransform3DMakeRotation ([Helper degreesToRadians:(5)], 1, 1, 1);
img.layer.shadowRadius = 2.0;
img.layer.shouldRasterize = YES;
The problem is that the border is not smooth at all:
Try adding a transparent border (1px may be) around your image. See this link.
Check UIImage+Alpha section in that page.
I see most of the answer for this problem is to add 1px transparent border but it only works if we are not using any border around UIImageView, if UIImageView itself has the border and we rotate it then the border is not smooth. I am stil trying to figure out on how to fix that issue.
HERE'S WHAT I DID TO FIX THIS ISSUE
UIImage *thumbnail = [photo thumbnailImage:thumbnailSize.width
transparentBorder:2
cornerRadius:0
interpolationQuality:kCGInterpolationHigh];
CGPoint randomPoint = [self getRandomOriginPoint];
UIImageView *thumbnailView = [[UIImageView alloc] initWithFrame:CGRectMake(10.0, 10.0, thumbnail.size.width, thumbnail.size.height)];
[thumbnailView.layer setBorderWidth:2];
[self setContentMode:UIViewContentModeCenter];
[thumbnailView.layer setBorderColor:[UIColor whiteColor].CGColor];
[thumbnailView.layer setShadowOffset:CGSizeMake(-3.0, 3.0)];
[thumbnailView.layer setShadowRadius:3.0];
[thumbnailView.layer setShadowOpacity:1.0];
thumbnailView.layer.shouldRasterize = YES;
I used UIImage+Resize.h from here to get the thumbnail image in my code, so with this even after you rotate image with any angle the border will look perfectly fine!
Without having to use categories, solution that made the fewest presumptions
#import <QuartzCore/QuartzCore.h>
We will use the following variable
UIView *myView;
This has been confirmed to work on UIImageViews / UIViews of all types
myView.layer.shouldRasterize = YES; //the single line that solved this problem from the above
You should not need to add a border of any type for this to work.
CATransform3D rotate = CATransform3DIdentity;
myView.layer.shouldRasterize = YES;
rotate = CATransform3DRotate(rotate,M_PI_4/8,0.0,0.0,1);
myView.layer.transform = rotate;
Note: This answer is provided to consolidate the information into a single answer that removes some of the other requirements. In this example I use M_PI_4/8 as it's a nice viewing angle for if you have a Stickie Note sort of view that you are implementing.