Draw a border around an oval CAShapeLayer on MacOS - objective-c

I need to display an oval layer with a predefined fillColor and a 1px borderColor.
Here is code:
CGRect r = CGRectMake(28, self.bounds.size.height - 5 - 12, 12.0, 12.0);
NSBezierPath *path = [NSBezierPath bezierPathWithOvalInRect:r];
NSColor *fillColor = [NSColor colorWithRed:255.0/255.0 green:193.0/255.0 blue:47.0/255.0 alpha:1.0f];
NSColor *borderColor = [NSColor colorWithRed:226.0/255.0 green:70.0/255.0 blue:84.0/255.0 alpha:1.0f];
minimizeButtonLayer = [CAShapeLayer layer];
minimizeButtonLayer.path = path.CGPath;
minimizeButtonLayer.fillColor = fillColor.CGColor;
minimizeButtonLayer.borderColor = borderColor.CGColor;
minimizeButtonLayer.borderWidth = 1.0;
The oval shape is correctly displayed but without any border.
Why? Please help me.
P.S. Please note that path.CGPath is from a NSBezierPath category.

I solved the problem by replacing borderColor with strokeColor
minimizeButtonLayer.borderColor = borderColor.CGColor;
with
minimizeButtonLayer.strokeColor = borderColor.CGColor;

Related

Shapes in sprite kit

How do you make a circle or another shape in sprite kit I have seen some that use CGPath but i haven't really ever used CGPath ever . I was able to make a square with SKSpritenode but I can't seem to make triangles or circles.
This creates an SKShapeNode and sets its path property to a circle path with radius 16.
SKShapeNode *shape = [SKShapeNode node];
CGRect rect = CGRectMake(0, 0, 32, 32);
shape.path = [self circleInRect:rect];
shape.strokeColor = [SKColor greenColor];
shape.fillColor = [SKColor redColor];
shape.position = CGPointMake(100,100);
[self addChild:shape];
This method returns a CGPath object initialized with a oval path
- (CGPathRef) circleInRect:(CGRect)rect
{
// Adjust position so path is centered in shape
CGRect adjustedRect = CGRectMake(rect.origin.x-rect.size.width/2, rect.origin.y-rect.size.height/2, rect.size.width, rect.size.height);
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:adjustedRect];
return bezierPath.CGPath;
}
Here's a triangle path...
- (CGPathRef) triangleInRect:(CGRect)rect
{
CGFloat offsetX = CGRectGetMidX(rect);
CGFloat offsetY = CGRectGetMidY(rect);
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(offsetX, 0)];
[bezierPath addLineToPoint: CGPointMake(-offsetX, offsetY)];
[bezierPath addLineToPoint: CGPointMake(-offsetX, -offsetY)];
[bezierPath closePath];
return bezierPath.CGPath;
}
Code snippet to create Triangle using Sprite Kit
SKShapeNode* leftContainer = [SKShapeNode node];
leftContainer.position = CGPointMake(CGRectGetMidX(self.frame),
CGRectGetMidY(self.frame));
CGMutablePathRef pathLeftContainer = CGPathCreateMutable();
// Move to position and Draws line to form a triangle
CGPathMoveToPoint(pathLeftContainer, NULL, 60, 100);
CGPathAddLineToPoint(pathLeftContainer, 0, 120, 160);
CGPathAddLineToPoint(pathLeftContainer, 0,180,100);
CGPathAddLineToPoint(pathLeftContainer, 0,60,100);
[leftContainer setPath:pathLeftContainer];
leftContainer.lineWidth = 10.0;
leftContainer.strokeColor = [UIColor redColor];
leftContainer.physicsBody = [SKPhysicsBody bodyWithEdgeChainFromPath:leftContainer.path];
leftContainer.physicsBody.dynamic = FALSE;
[leftContainer.physicsBody setAllowsRotation:FALSE];
[self addChild:leftContainer];
CGPathRelease(pathLeftContainer);
Code snippet to create Circle using Sprite Kit
SKShapeNode* leftContainer = [SKShapeNode node];
leftContainer.position = CGPointMake(CGRectGetMidX(self.frame),
CGRectGetMidY(self.frame));
CGMutablePathRef pathLeftContainer = CGPathCreateMutable();
// Draw circle with radius 20
CGPathAddArc(pathLeftContainer, NULL, 0, 20, 20, 0, 2*M_PI, true);
[leftContainer setPath:pathLeftContainer];
leftContainer.lineWidth = 10.0;
leftContainer.strokeColor = [UIColor redColor];
leftContainer.physicsBody = [SKPhysicsBody bodyWithEdgeChainFromPath:leftContainer.path];
leftContainer.physicsBody.dynamic = FALSE;
[leftContainer.physicsBody setAllowsRotation:FALSE];
[self addChild:leftContainer];
CGPathRelease(pathLeftContainer);

Gradient as circle stroke color in CAShapeLayer

CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(x, y, 100, 100) cornerRadius:50].CGPath;
// Configure the apperence of the circle
circle.fillColor = [UIColor whiteColor].CGColor;
circle.strokeColor = [UIColor darkGrayColor].CGColor;
circle.lineWidth = 1.8;
circle.lineDashPattern = #[#6, #3];
// Add to parent layer
[cell.layer addSublayer:circle];
I am using this code to draw a circle. Now, I want to use a gradient as stroke color. How can I do that?

How to set a tiled background image for a CALayer?

When I set the background for the IKBrowserView the background is resized according to the view size: is there a way to set it as tiled image, repeated but never resized ?
NSImage* backgroundImage = [NSImage imageNamed:#"wood-bg2.jpg"];
CALayer* aLayer = [CALayer layer];
//aLayer.contents = backgroundImage;
CIColor *ci = [[CIColor alloc] initWithColor:[NSColor colorWithPatternImage:backgroundImage]];
CGColorSpaceRef cs = [ci colorSpace];
const CGFloat *comps = [ci components];
CGColorRef cgColor = CGColorCreate(cs, comps);
aLayer.backgroundColor = cgColor;
[itemThumbnailImageBrowserView setBackgroundLayer:aLayer];
I've tried both the commented out code and the current code, but none work.
thanks
There's a method of NSColor:
+ (NSColor *)colorWithPatternImage:(NSImage *)image
So you can do something like this:
NSImage* backgroundImage = [NSImage imageNamed:#"wood-bg2.jpg"];
CALayer* aLayer = [CALayer layer];
aLayer.backgroundColor = [[NSColor colorWithPatternImage:backgroundImage] CGColor]; // - (CGColor) CGColor; is only available in OS X 10.8 and later
[itemThumbnailImageBrowserView setBackgroundLayer:aLayer];
Update for OS X 10.8 and lower
Convert NSColor to CGColor (not tested):
CIColor *ci = [[CIColor alloc] initWithColor:[NSColor colorWithPatternImage:backgroundImage]];
CGColorSpaceRef cs = [ci colorSpace];
const CGFloat *comps = [ci components];
CGColorRef cgColor = CGColorCreate(cs, comps);

how to position a rotating CAShapeLayer at certain point in UIImageView?

I have the following code which makes an oval rotating around its center. I would like to be able to position it within UIImageView at a certain position (say a middle of the view).
I would really appreciate if someone could help me out on this one.
-(void)drawCircle
{
CGMutablePathRef circlePath = CGPathCreateMutable();
int radius = 400;
CGRect circleRect = CGRectMake(CENTER_Y-radius*0.7, CENTER_X-radius, 1.4*radius, 2*radius);
float midX = CGRectGetMidX(circleRect);
float midY = CGRectGetMidY(circleRect);
CGAffineTransform transform = CGAffineTransformMakeTranslation(-midX, -midY);
CGPathAddEllipseInRect( circlePath ,&transform , circleRect);
CAShapeLayer *circle = [[CAShapeLayer alloc] init];
circle.path = circlePath;
circle.opacity = 0.1;
circle.contentsScale = SCREEN_SCALE;
circle.fillColor = [UIColor blueColor].CGColor;
[aView.layer addSublayer:circle];
CABasicAnimation* theAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
theAnimation.fromValue = 0;
theAnimation.toValue = #(2*M_PI);
theAnimation.duration=3.5;
theAnimation.autoreverses=FALSE;
theAnimation.repeatCount=HUGE_VALF;
theAnimation.fillMode = kCAFillModeBoth;
theAnimation.removedOnCompletion=FALSE;
theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[circle addAnimation:theAnimation forKey:#"transform.rotation.z"];
}
a missing piece:
[circle setPosition:CGPointMake(CENTER_X, CENTER_Y)];

Rounder corners in UIView

i have a UIView and i would like to round it and add shadow color like this image :
For Rounder Corner
CAShapeLayer * maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect: self.bounds byRoundingCorners: UIRectCornerBottomLeft | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.}].CGPath;
self.layer.mask = maskLayer;
For Shadow
self.layer.masksToBounds = NO;
self.layer.shadowOffset = CGSizeMake(-15, 20);
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = 0.5;
Hope this helps you!
To get the very same shadow as your image I would recommend you using a background image. Otherwise you should include <Quartzcore/Quartzcore.h> and use the following code:
view.layer.cornerRadius = 10;
view.frame = CGRectMake(15, 15, 100, 100);
view.backgroundColor = [UIColor redColor];
view.layer.shadowColor = [UIColor blackColor].CGColor;
view.layer.shadowOffset = CGSizeMake(2.0, 2.0);
view.layer.shadowOpacity = 0.8;
view.layer.shadowRadius = 10;
Some more information for the background image-option
Create a UIView that has the same width and height as the image including the shadow and assign the image to it this way:
view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"backgroundview.png"]];