Gradient as circle stroke color in CAShapeLayer - objective-c

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?

Related

Rotate CAShapeLayer

I'm trying to rotate a CAShapeLayer in place
UIBezierPath *aPath = [UIBezierPath bezierPath];
CGFloat originx = (97.5+250);
CGFloat originy = (205+250);
[aPath moveToPoint:CGPointMake(originx,originy)];
[aPath addArcWithCenter:CGPointMake(originx+15, originy-30) radius:15 startAngle:DEGREES_TO_RADIANS(180) endAngle:DEGREES_TO_RADIANS(360) clockwise:YES];
[aPath addLineToPoint:CGPointMake(originx+30,originy)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.anchorPoint = CGPointMake(originx, originy);
shapeLayer.path = [aPath CGPath];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.lineWidth = 3.0;
shapeLayer.fillColor = [[UIColor blueColor] CGColor];
[aPath closePath];
shapeLayer.transform = CATransform3DMakeRotation(310 * M_PI/180, 0.0, 0.0, 1.0);
[self.view.layer addSublayer:shapeLayer];
I want to rotate the shape around an axis within the shape itself (the code above makes my little shape rotate around an axis several hundred pixels from the actual centre.
I felt this should be controlled with an anchorpoint like this one:
shapeLayer.anchorPoint = CGPointMake(originx, originy);
but it seems to do nothing within the code.
Any ideas?
The anchorPoint is relative to the bounds of the layer. You can't use the anchor point to place your layer. Instead you can place your shape relative to the zero point, rotate it, and the move it to the desired point. Rotation and translation are done by the transform.

iOS 10 How to animate UIBezierPath of UIVisualEffectView maskView

I just updated to Xcode 8 and I had problem with Blur (UIVisualEffectView) on iOS 10, but I solve it. But after I fixed the blur layer mask second problem is appears, when I getting the reference of maskView from UIVisualEffectView and apply the new UIBezierPath nothing happens.
Code example:
-(void)prepareEffectView{
//Frame
CGRect frame = self.view.bounds;
UIView *maskView = [[UIView alloc] initWithFrame:frame];
maskView.backgroundColor = [UIColor blackColor];
maskView.layer.mask = ({ // This mask draws a rectangle and crops a circle inside it.
UIBezierPath *maskLayerPath = [UIBezierPath bezierPath];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithRect:frame]];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithRect:CGRectMake(self.btnScan.center.x, self.btnScan.center.y, 0, 0)]];
[maskLayer setPath:maskLayerPath.CGPath];
[maskLayerPath setUsesEvenOddFillRule:YES];
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = maskLayerPath.CGPath;
mask.fillRule = kCAFillRuleEvenOdd;
mask;
});
self.visualEffectView.maskView = maskView;
}
-(void)openAperture{
//Blur layer
CGRect frame = self.view.bounds;
CAShapeLayer *maskLayer = (CAShapeLayer *)self.visualEffectView.maskView.layer.mask;
//New path value
UIBezierPath *maskLayerPath = [UIBezierPath bezierPath];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithRect:frame]];
[maskLayerPath appendPath:[UIBezierPath bezierPathWithRoundedRect:UIEdgeInsetsInsetRect(frame, UIEdgeInsetsMake(58, 15, 66, 15)) cornerRadius:1]];
[maskLayer setPath:maskLayerPath.CGPath];
//Animation
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"path"];
animation.delegate = self;
animation.duration = 0.44;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.fromValue = (id)maskLayer.path;
animation.toValue = (id)maskLayerPath.CGPath;
[maskLayer addAnimation:animation forKey:#"animatePath"];
}
Apple Note About VisualEffectView issue on iOS 10
Transitions are tough in this realm, as maskView is the only way to
ensure that the effect works, but maskView also isn't animatable.
https://forums.developer.apple.com/message/184810#184810
The only the way to use "CAShapeLayer" as a mask is to apply your shape to UIView.layer.mask and then put it to UIVisualEffectView.maskView.
The maskView of UIVisualEffectView isn't animatable.
I have the same problem.
I tried to do next: (Swift code)
visualEffectView.layer.mask = maskView.layer.mask
instead of visualEffectView.mask = maskView
If so, path animation works fine, but then blur effect is gone.
If you find a solution, please update the post.

Masking a sublayer gradient to CAShapeLayer

I have this CAShapeLayer with a bezierPathWithOvalInRect. I want to make the gradient layer fill only the circle, but at the moment it fills the whole frame.
How do I do this?
CAShapeLayer *layerInsides = [CAShapeLayer layer];
layerInsides.path = [UIBezierPath bezierPathWithOvalInRect:rectFrom(frameInsides)].CGPath;
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = layerInsides.frame;
gradientLayer.colors = #[(id)[UIColor colorWithRed:1 green:0 blue:0 alpha:1].CGColor, (id)[UIColor colorWithRed:0 green:0 blue:0 alpha:1].CGColor];
gradientLayer.locations = #[#0.0, #1];
gradientLayer.cornerRadius = self.layer.cornerRadius;
[layerInsides addSublayer:gradientLayer];
Instead of adding your content to the shape as a sublayer you need to set your CAShapeLayer as a mask for your colored layer:
gradientLayer.mask = layerInsides;

Add a CAShapeLayer between annotation and MKMapView

I'm trying to add an animation below the annotations of my MKMapView but with no luck.
I tryed to change the CAShapeLayer zPosition but the circle end up below the map.
Here is my current code to add the animation to the map:
int radius = 55;
CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius)
cornerRadius:radius].CGPath;
circle.position = CGPointMake(CGRectGetMidX(self.view.frame)-radius,
CGRectGetMidY(self.view.frame)-radius);
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor blackColor].CGColor;
circle.lineWidth = radius*2;
circle.opacity = 0.5;
[self.mapView.layer addSublayer:circle];
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
drawAnimation.duration = 2.5; // "animate over 10 seconds or so.."
drawAnimation.repeatCount = 100.0; // Animate only once..
drawAnimation.removedOnCompletion = YES; // Remain stroked after the animation..
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue = [NSNumber numberWithFloat:1.0f];
functionWithName:kCAMediaTimingFunctionEaseIn];
[circle addAnimation:drawAnimation forKey:#"drawCircleAnimation"];
After 3 days without an answer I decided to remove my annotation from the mkview and put the animation and the image corresponding to the annotation in another view, above the map.

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"]];