why I get the converse mask with the "CGMutablePathRef" method - objective-c

I draw a view . The views frame = (0,0,44,44) and the views background color is black.
I want add a mask to make the view looks like this : the mask is a small circle in the middle of the view . but I get a converse result , only the middle of the view is not masked. the wrong result like this
my code is :
aView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
[aView.layer setBackgroundColor:[[UIColor blackColor] CGColor]];
CAShapeLayer *mask = [[CAShapeLayer alloc] init];
mask.frame = aView.bounds;
CGMutablePathRef p2 = CGPathCreateMutable();
CGPathAddEllipseInRect(p2, NULL, CGRectInset(mask.bounds, 10, 10));
mask.path = p2;
aView.layer.mask = mask;
CGPathRelease(p2);
[self addSubview:aView];
what is wrong with the code ? thanks.

First, add a rectangle to the masking path.
Second, set the fillRule property of shape layer to kCAFillRuleEvenOdd, so that the center part is left hollowed.
aView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
[aView.layer setBackgroundColor:[[UIColor blackColor] CGColor]];
CAShapeLayer *mask = [[CAShapeLayer alloc] init];
mask.fillRule = kCAFillRuleEvenOdd;
mask.frame = aView.bounds;
CGMutablePathRef p2 = CGPathCreateMutable();
CGPathAddRect(p2, &CGAffineTransformIdentity, mask.bounds);
CGPathCloseSubpath(p2);
CGPathAddEllipseInRect(p2, NULL, CGRectInset(mask.bounds, 10, 10));
mask.path = p2;
aView.layer.mask = mask;
CGPathRelease(p2);

Related

How to create only bottom border for label?

Hi I used the the following code to create a bottom border to my label
CALayer *border = [CALayer layer];
CGFloat borderWidth = 2;
border.borderColor = [UIColor darkGrayColor].CGColor;
border.frame = CGRectMake(0, _label.frame.size.height - borderWidth, _label.frame.size.width, _label.frame.size.height);
border.borderWidth = borderWidth;
[_label.layer addSublayer:border];
_label.layer.masksToBounds = YES;
But it the border is breaks at half of label. How can I fix it. Thanks in advance.
You can do like this :
With the use of CALayer you can create border on UILabel or any other UIControl.
1) Bottom Border
CALayer *bottomBorder = [CALayer layer];
bottomBorder.borderColor = [UIColor blackColor].CGColor;
bottomBorder.borderWidth = 1;
bottomBorder.frame = CGRectMake(0, CGRectGetHeight(myLabel.frame)-1, CGRectGetWidth(myLabel.frame), 1);
myLabel.clipsToBounds = YES;
[myLabel.layer addSublayer:bottomBorder];
2) Top Border
CALayer *topBorder = [CALayer layer];
topBorder.borderColor = [UIColor blackColor].CGColor;
topBorder.borderWidth = 1;
topBorder.frame = CGRectMake(0, 0, CGRectGetWidth(myLabel.frame), 1);
myLabel.clipsToBounds = YES;
[myLabel.layer addSublayer:topBorder];
3) Left Border
CALayer *leftBorder = [CALayer layer];
leftBorder.borderColor = [UIColor blackColor].CGColor;
leftBorder.borderWidth = 1;
leftBorder.frame = CGRectMake(0, 0, 1, CGRectGetHeight(myLabel.frame));
myLabel.clipsToBounds = YES;
[myLabel.layer addSublayer:leftBorder];
4) Right Border
CALayer *rightBorder = [CALayer layer];
rightBorder.borderColor = [UIColor blackColor].CGColor;
rightBorder.borderWidth = 1;
rightBorder.frame = CGRectMake(CGRectGetWidth(myLabel.frame)-1, 0, 1, CGRectGetHeight(myLabel.frame));
myLabel.clipsToBounds = YES;
[myLabel.layer addSublayer:rightBorder];
Try it,
CALayer* layer = [lbl layer];
CALayer *bottomBorder = [CALayer layer];
bottomBorder.borderColor = [UIColor darkGrayColor].CGColor;
bottomBorder.borderWidth = 1;
bottomBorder.frame = CGRectMake(-1, layer.frame.size.height-1,layer.frame.size.width, 1);
[bottomBorder setBorderColor:[UIColor blackColor].CGColor];
[layer addSublayer:bottomBorder];
You need to calculate width of label based on string and also font which you require.
You can get size like this
CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font
constrainedToSize:maximumLabelSize
lineBreakMode:yourLabel.lineBreakMode];
and use expectedLabelSize while setting frame for your border.
border.frame = CGRectMake(0, _label.frame.size.height - borderWidth, _expectedLabelSize.width , _label.frame.size.height);
Hope it helps. Happy Coding !!
Please try with the following code.
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 50)];
[lbl setText:#"Testo di prova..."];
[lbl setBackgroundColor:[UIColor clearColor]];
[[self view] addSubview:lbl];
[lbl sizeToFit];
CALayer* layer = [lbl layer];
CALayer *bottomBorder = [CALayer layer];
bottomBorder.borderColor = [UIColor darkGrayColor].CGColor;
bottomBorder.borderWidth = 1;
bottomBorder.frame = CGRectMake(-1, layer.frame.size.height-1, layer.frame.size.width, 1);
[bottomBorder setBorderColor:[UIColor blackColor].CGColor];
[layer addSublayer:bottomBorder];

Adding animated layer on video using CAKeyframeAnimation

I'm trying to add an overlay to my video which contains a sublayer that has the content changed over time. So I'm adding CAKeyframeAnimation to the layer as follows:
CALayer *overlayLayer = [CALayer layer];
[overlayLayer setFrame:CGRectMake(0, 0, size.width, size.height)];
[overlayLayer setMasksToBounds:YES];
NSArray *frames = [self.gifImage frames];
CALayer *aLayer = [CALayer layer];
UIImage *firstImage = [frames objectAtIndex:0];
CGFloat nativeWidth = CGImageGetWidth(firstImage.CGImage);
CGFloat nativeHeight = CGImageGetHeight(firstImage.CGImage);
CGRect frame = CGRectMake(0.0, 0.0, nativeWidth, nativeHeight);
aLayer.frame = frame;
aLayer.contents = (id)firstImage.CGImage;
[aLayer setMasksToBounds:YES];
CAKeyframeAnimation *animationSequence = [CAKeyframeAnimation animationWithKeyPath:#"contents"];
animationSequence.calculationMode = kCAAnimationDiscrete;
animationSequence.duration = [self.gifImage totalDuration];
animationSequence.repeatCount = HUGE_VALF;
NSMutableArray *animationSequenceArray = [[NSMutableArray alloc] init];
for (UIImage *image in frames) {
[animationSequenceArray addObject:(id)image.CGImage];
}
animationSequence.values = animationSequenceArray;
[aLayer addAnimation:animationSequence forKey:#"contents"];
[overlayLayer addSublayer:aLayer];
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, size.width, size.height);
videoLayer.frame = CGRectMake(0, 0, size.width, size.height);
[parentLayer addSublayer:videoLayer];
[parentLayer addSublayer:overlayLayer];
composition.animationTool = [AVVideoCompositionCoreAnimationTool
videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
Somehow when I add aLayer as a sublayer of my view, it animates properly. But When I add it to the overlay of the video, the animation doesn't work. Is there something I'm missing here? Any help is appreciated.
If you use kCAAnimationDiscrete, here's a checklist:
keyTimes needs a value from 0-1, not a time
keyTimes must start at 0.0 and end with value 1.0
keyTimes must have one more value than your animation frames count
I've finally managed to fix this issue by changing calculationMode to kCAAnimationLinear. This seems to be a silly issue, but I hope it may be useful for someone.

Objective-c SpriteKit CGRectMake left border

I'm trying to draw vertical line on the left border of screen, but line is't showed. What is wrong?
CGRect leftRect = CGRectMake(0, 0, 10, self.size.height);
SKShapeNode *leftBorder = [SKShapeNode shapeNodeWithRect:leftRect];
leftBorder.strokeColor = [SKColor redColor];
leftBorder.fillColor = [SKColor redColor];
leftBorder.name = #"leftBorder";
leftBorder.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:leftBorder.frame];
leftBorder.physicsBody.dynamic = NO;
[self addChild:leftBorder];
You must set size gameScene ,when u init it.
_gameScene = [GameScene unarchiveFromFile:#"GameScene"];
// Here
_gameScene.size = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
_gameScene.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:_gameScene];
Try this out
SKShapeNode *yourline = [SKShapeNode node];
CGMutablePathRef pathToDraw = CGPathCreateMutable();
CGPathMoveToPoint(pathToDraw, NULL, 100.0, 100.0);
CGPathAddLineToPoint(pathToDraw, NULL, 50.0, 50.0);
yourline.path = pathToDraw;
[yourline setStrokeColor:[UIColor redColor]];
[self addChild:yourline];
If it's not working, than it can be self. Be sure, that self is instance of SKScene.

Using a CALayer as a mask to a backing layer of a GLKView blocks touch events?

I'm trying to use a CAShapeLayer as a mask to the backing layer of a GLKView like so:
CGRect circleFrame = CGRectMake(0, 0, 800, 800);
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:circleFrame];
CGPoint circleAnchor = CGPointMake(CGRectGetMidX(circleFrame) / CGRectGetMaxX(circleFrame),CGRectGetMidY(circleFrame) / CGRectGetMaxY(circleFrame));
shapeLayerMask = [[CAShapeLayer alloc] init];
shapeLayerMask.path = path.CGPath;
shapeLayerMask.anchorPoint = circleAnchor;
shapeLayerMask.frame = CGRectMake(0, 0,800, 800);
shapeLayerMask.fillColor = [UIColor blackColor].CGColor;
shapeLayerMask.backgroundColor = [UIColor clearColor].CGColor;
shapeLayerMask.opacity = 1.0f;
shapeLayerMask.hidden = NO;
self.view.layer.mask = shapeLayerMask;
But as soon as i do this, all my touch events stop firing. No more touchesBegan, touchesEnded, etc. Anyone knows why? Thanks in advance!

sub CALayer can not be displayed

my code is like this:
// layer
highlightLayer = [[CALayer alloc]init];
highlightLayer.frame = CGRectMake(0, 420, 320, 11);
highlightLayer.backgroundColor = [UIColor greenColor].CGColor;
CALayer *contentLayer = [[CALayer alloc]init];
contentLayer.frame = CGRectMake(0, 420, 80, 11);
contentLayer.backgroundColor = [UIColor redColor].CGColor;
[highlightLayer addSublayer:contentLayer];
[contentLayer release];
but this sublayer does not appear. i don't know why.
Because contentLayer's frame is outside highlightLayer's bounds (0, 0, 320, 11). contentLayer's frame is expressed in highlightLayer's coordinate system. I think you should simply adjust contentLayer's frame origin.