I want to create a mask layer which is a circle that makes the circle content transparent and keep everything around. Unfortunately, the following code does the opposite, it draws a circle and make everything around transparent.
CAShapeLayer * shape = [CAShapeLayer layer];
shape.frame = CGRectMake((CGSSize().width/2.f)-40.f, -40.f, 80.f, 80.f);
CGPathRef pathRef =
CGPathCreateWithEllipseInRect(CGRectMakeBoundsWithSize(shape.frame.size), NULL);
shape.path = pathRef;
shape.fillColor = [UIColor blueColor].CGColor;
self.layer.mask = shape;
Yeah, kCAFillRuleEvenOdd didn't do it's magic without adding a rect first, here is a working snippet though:
CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = self.bounds;
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathAddRect(pathRef, NULL, self.bounds);
CGPathAddEllipseInRect(pathRef, NULL, self.bounds);
shape.fillRule = kCAFillRuleEvenOdd;
shape.path = pathRef;
self.layer.mask = shape;
Related
I tried to set button bottom rounded rectangle. But they apply only Right of bottom.
I want bothside bottom of button has rounded rectangle.
This is my code:
UIBezierPath *shapePath = [UIBezierPath bezierPathWithRoundedRect:registerbtn.bounds
byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
cornerRadii:CGSizeMake(9.0, 9.0)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = registerbtn.bounds;
shapeLayer.path = shapePath.CGPath;
[registerbtn.layer addSublayer:shapeLayer];
Output:
This is working fine. just try it
UIBezierPath *shapePath = [UIBezierPath bezierPathWithRoundedRect:registerbtn.bounds
byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight)
cornerRadii:CGSizeMake(9.0, 9.0)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = registerbtn.bounds;
shapeLayer.path = shapePath.CGPath;
[registerbtn.layer addSublayer:shapeLayer];
Your code looks fine.
Just write same code in viewWillAppear and check:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
UIBezierPath *shapePath = [UIBezierPath bezierPathWithRoundedRect:registerbtn.bounds
byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
cornerRadii:CGSizeMake(9.0, 9.0)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = registerbtn.bounds;
shapeLayer.path = shapePath.CGPath;
[registerbtn.layer addSublayer:shapeLayer];
}
Above mentioned answers should work but the problem is your button is getting rounded from both sides but its effect is not visible to you. If you will check by zooming then you can see your button is cornered and then there is another layer under the above layer on which you have added bezierpath.
let shapePath = UIBezierPath.init(roundedRect: view.bounds, byRoundingCorners: [UIRectCorner.BottomLeft,UIRectCorner.BottomRight], cornerRadii: CGSizeMake(8,8))
let newCornerLayer = CAShapeLayer()
newCornerLayer.frame = view.bounds
newCornerLayer.path = shapePath.CGPath;
view.layer.mask = newCornerLayer
This should work but you need to be careful on which you are applying the layer.
I used this to round top two corners of my UITextFeild
CAShapeLayer * maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect: self.emailFeild.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.}].CGPath;
I also have border added to this UITextField as
self.emailFeild.layer.borderColor = [[self colorFromHexString:#"0x3263A3"]CGColor];
self.emailFeild.layer.borderWidth = 1.0f;
self.emailFeild.layer.mask = maskLayer;
but when I run it. It did not round the corners of border and I get this result
The mask layer doesn't get drawn, just used to compute the mask. Try:
-(void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius
{
CGRect bounds = self.bounds;
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds
byRoundingCorners:corners
cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
CAShapeLayer* frameLayer = [CAShapeLayer layer];
frameLayer.frame = bounds;
frameLayer.path = maskPath.CGPath;
frameLayer.strokeColor = [UIColor redColor].CGColor;
frameLayer.fillColor = nil;
[self.layer addSublayer:frameLayer];
}
-(void)roundTopCornersRadius:(CGFloat)radius
{
[self roundCorners:(UIRectCornerTopLeft|UIRectCornerTopRight) radius:radius];
}
So I'm trying to cut a circle out of an existing layer; and here's my code:
CGRect bounds = _containerLayer.bounds;
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = bounds;
maskLayer.fillColor = [UIColor blackColor].CGColor;
CGFloat smallCircleRadius = (frame.size.width - barWidth)/2;
CGRect smallCircleRect = CGRectMake(CGRectGetMidX(bounds) - smallCircleRadius, CGRectGetMidY(bounds) - smallCircleRadius, 2 * smallCircleRadius, 2 * smallCircleRadius);
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:smallCircleRect];
[circlePath appendPath:[UIBezierPath bezierPathWithRect:bounds]];
maskLayer.path = circlePath.CGPath;
maskLayer.fillRule = kCAFillRuleEvenOdd;
_containerLayer.mask = maskLayer;
This code does work, as I now see a black rectangle with a hollow circle in the middle. But the problem is that when I tried to set maskLayer.fillColor = [UIColor clearColor].CGColor;, The whole thing including _containerLayer just disappears - I want to make the fillColor transparent so I can see what's originally in the _containerLayer (which wasn't cut out). What should I do to achieve this? Thanks!
How texture(like below) image can be applied to calayer with opacity levels like combining texture and calayer image?
Sample texture
You can use this
UIImage *yourImage = [UIImage imageNamed:#"yourTextureImage"];
self.yourView.layer.contents = (__bridge id) yourImage.CGImage;
EDIT Try this add sublayer on existing layer.It will give you idea how to do that.
//It will draw some circle
int radius = 30.0;
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 20.0, 20.0) cornerRadius:0];
UIBezierPath *circlePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius];
[path appendPath:circlePath];
[path setUsesEvenOddFillRule:YES];
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.7;
[self.view.layer addSublayer:fillLayer];
You can also try setting mask
[self.view.layer setMask:fillLayer];
I think, if I am not mistaken, you need to use CALayer's mask property to achieve the required result.
Please try the following
//create mask layer
CALayer *maskLayer = [CALayer layer];
maskLayer.frame = self.imageView.bounds;
UIImage *maskImage = [UIImage imageNamed:#"Your image"];
maskLayer.contents = (__bridge id)maskImage.CGImage;
//apply mask to image layer
self.imageView.layer.mask = maskLayer;
I've created a dashed CAShapeLayer using the code below. The line draws correctly when its path is on a perfectly horizontal plane. However as soon as the path moves up or down, the line suffers from some issues. See the images as an example.
CGMutablePathRef linePath = CGPathCreateMutable();
CGPathMoveToPoint(linePath, NULL, startShapeLayer.centerX, startShapeLayer.centerY);
CGPathAddLineToPoint(linePath, NULL, endShapeCenter.x, endShapeCenter.y);
CGPathCloseSubpath(linePath);
CAShapeLayer *lineLayer = [CAShapeLayer layer];
lineLayer.path = linePath;
lineLayer.fillColor = [UIColor clearColor].CGColor;
lineLayer.strokeColor = [UIColor whiteColor].CGColor;
lineLayer.lineCap = kCALineCapRound;
lineLayer.lineDashPattern = #[#5, #5];
lineLayer.lineDashPhase = 5.0;
lineLayer.lineWidth = 1.0;
If anyone has some advice about drawing these kinds of shapes it'd be great to hear.