Masking UIImage in TableViewCell - ios

I have an UITableView where each cell is a picture, name and button, just like the favorites tab in the phone app in iOS 7. And, just like it is in the phone app, I want the image in each cell to be a circle, rather then a square.
Using a program called PaintCode, I have generated a UIBezierPath which I wanted to place over the cell.imageView in order to make the image look like it's a circle. Here is that code
//// Color Declarations
UIColor* fillColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 0];
UIColor* fillColor2 = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1];
//// Bezier Drawing
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(36.36, 26.36)];
[bezierPath addCurveToPoint: CGPointMake(30.5, 40.5) controlPoint1: CGPointMake(32.45, 30.26) controlPoint2: CGPointMake(30.5, 35.38)];
[bezierPath addLineToPoint: CGPointMake(30.5, 20.5)];
[bezierPath addLineToPoint: CGPointMake(50.5, 20.5)];
[bezierPath addCurveToPoint: CGPointMake(36.36, 26.36) controlPoint1: CGPointMake(45.38, 20.5) controlPoint2: CGPointMake(40.26, 22.45)];
[bezierPath closePath];
[bezierPath moveToPoint: CGPointMake(70.5, 60.5)];
[bezierPath addLineToPoint: CGPointMake(50.5, 60.5)];
[bezierPath addCurveToPoint: CGPointMake(64.64, 54.64) controlPoint1: CGPointMake(55.62, 60.5) controlPoint2: CGPointMake(60.74, 58.55)];
[bezierPath addCurveToPoint: CGPointMake(70.5, 40.5) controlPoint1: CGPointMake(68.55, 50.74) controlPoint2: CGPointMake(70.5, 45.62)];
[bezierPath addCurveToPoint: CGPointMake(64.64, 26.36) controlPoint1: CGPointMake(70.5, 35.38) controlPoint2: CGPointMake(68.55, 30.26)];
[bezierPath addCurveToPoint: CGPointMake(50.5, 20.5) controlPoint1: CGPointMake(60.74, 22.45) controlPoint2: CGPointMake(55.62, 20.5)];
[bezierPath addLineToPoint: CGPointMake(70.5, 20.5)];
[bezierPath addLineToPoint: CGPointMake(70.5, 60.5)];
[bezierPath closePath];
[bezierPath moveToPoint: CGPointMake(36.36, 54.64)];
[bezierPath addCurveToPoint: CGPointMake(50.5, 60.5) controlPoint1: CGPointMake(40.26, 58.55) controlPoint2: CGPointMake(45.38, 60.5)];
[bezierPath addLineToPoint: CGPointMake(30.5, 60.5)];
[bezierPath addLineToPoint: CGPointMake(30.5, 40.5)];
[bezierPath addCurveToPoint: CGPointMake(36.36, 54.64) controlPoint1: CGPointMake(30.5, 45.62) controlPoint2: CGPointMake(32.45, 50.74)];
[bezierPath closePath];
[fillColor2 setFill];
[bezierPath fill];
[fillColor setStroke];
bezierPath.lineWidth = 1;
[bezierPath stroke];
Simply put, I don't know how to use this code to apply this mask to the cell's image view. Any suggestions?

I think you can accomplish this more easily by just editing the cornerRadius property of the UIImageView's layer (after importing QuartzCore), and then setting masksToBounds to true. Check out this answer: How to crop UIImage on oval shape or circle shape?

Related

How to draw line on Image Pattern exactly

I have a UIImageView. Inside that I am drawing a line wit user touch event. Problem is that a line can be drawn anywhere in UIImageview, but I like to draw line with image pattern only.
For example, look at this image. I need to draw line on image pattern only.
This is my code:
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
touchPoint = [touch locationInView:self.imgColor];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(touchPoint.x,touchPoint.y)];
[path addLineToPoint:CGPointMake(startingPoint.x,startingPoint.y)];
startingPoint=touchPoint;
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.lineWidth = 3.0;
shapeLayer.fillColor = [[UIColor redColor] CGColor];
[self.imgColor.layer addSublayer:shapeLayer];
[arrLayer addObject:shapeLayer];
NSLog(#"Touch moving point =x : %f Touch moving point =y : %f", touchPoint.x, touchPoint.y);
}
I hope some one solve my problem.
You can try this way.
Let's say you have a bezierPath called maskPath,in my case it is textPath which is used to mask the imageView.
I am using a simple maskView which draws letter Q on imageView.
Adding the maskPath: (Adds a simple Q shaped mask to the imageView)
-(void)applyMask{
//// Text Drawing
textPath = [UIBezierPath bezierPath];
[textPath moveToPoint: CGPointMake(181, 179.8)];
[textPath addLineToPoint: CGPointMake(166, 197.2)];
[textPath addLineToPoint: CGPointMake(189.7, 216.1)];
[textPath addCurveToPoint: CGPointMake(160, 222.1) controlPoint1: CGPointMake(180.1, 220.1) controlPoint2: CGPointMake(170.2, 222.1)];
[textPath addCurveToPoint: CGPointMake(126.4, 214.45) controlPoint1: CGPointMake(147, 222.1) controlPoint2: CGPointMake(135.8, 219.55)];
[textPath addCurveToPoint: CGPointMake(103.3, 194.2) controlPoint1: CGPointMake(117, 209.35) controlPoint2: CGPointMake(109.3, 202.6)];
[textPath addCurveToPoint: CGPointMake(90.1, 165.85) controlPoint1: CGPointMake(97.3, 185.8) controlPoint2: CGPointMake(92.9, 176.35)];
[textPath addCurveToPoint: CGPointMake(85.9, 133.9) controlPoint1: CGPointMake(87.3, 155.35) controlPoint2: CGPointMake(85.9, 144.7)];
[textPath addCurveToPoint: CGPointMake(90.1, 101.95) controlPoint1: CGPointMake(85.9, 123.1) controlPoint2: CGPointMake(87.3, 112.45)];
[textPath addCurveToPoint: CGPointMake(103.3, 73.6) controlPoint1: CGPointMake(92.9, 91.45) controlPoint2: CGPointMake(97.3, 82)];
[textPath addCurveToPoint: CGPointMake(126.4, 53.35) controlPoint1: CGPointMake(109.3, 65.2) controlPoint2: CGPointMake(117, 58.45)];
[textPath addCurveToPoint: CGPointMake(160, 45.7) controlPoint1: CGPointMake(135.8, 48.25) controlPoint2: CGPointMake(147, 45.7)];
[textPath addCurveToPoint: CGPointMake(193.6, 53.35) controlPoint1: CGPointMake(173, 45.7) controlPoint2: CGPointMake(184.2, 48.25)];
[textPath addCurveToPoint: CGPointMake(216.7, 73.6) controlPoint1: CGPointMake(203, 58.45) controlPoint2: CGPointMake(210.7, 65.2)];
[textPath addCurveToPoint: CGPointMake(229.9, 101.95) controlPoint1: CGPointMake(222.7, 82) controlPoint2: CGPointMake(227.1, 91.45)];
[textPath addCurveToPoint: CGPointMake(234.1, 133.9) controlPoint1: CGPointMake(232.7, 112.45) controlPoint2: CGPointMake(234.1, 123.1)];
[textPath addCurveToPoint: CGPointMake(228.1, 171.85) controlPoint1: CGPointMake(234.1, 147.1) controlPoint2: CGPointMake(232.1, 159.75)];
[textPath addCurveToPoint: CGPointMake(209.5, 202.6) controlPoint1: CGPointMake(224.1, 183.95) controlPoint2: CGPointMake(217.9, 194.2)];
[textPath addLineToPoint: CGPointMake(181, 179.8)];
[textPath closePath];
[textPath moveToPoint: CGPointMake(244, 259.3)];
[textPath addLineToPoint: CGPointMake(258.4, 241.3)];
[textPath addLineToPoint: CGPointMake(230.2, 219.1)];
[textPath addCurveToPoint: CGPointMake(254.5, 180.7) controlPoint1: CGPointMake(241, 208.3) controlPoint2: CGPointMake(249.1, 195.5)];
[textPath addCurveToPoint: CGPointMake(262.6, 133.9) controlPoint1: CGPointMake(259.9, 165.9) controlPoint2: CGPointMake(262.6, 150.3)];
[textPath addCurveToPoint: CGPointMake(256.15, 91.75) controlPoint1: CGPointMake(262.6, 119.3) controlPoint2: CGPointMake(260.45, 105.25)];
[textPath addCurveToPoint: CGPointMake(236.8, 55.9) controlPoint1: CGPointMake(251.85, 78.25) controlPoint2: CGPointMake(245.4, 66.3)];
[textPath addCurveToPoint: CGPointMake(204.7, 31) controlPoint1: CGPointMake(228.2, 45.5) controlPoint2: CGPointMake(217.5, 37.2)];
[textPath addCurveToPoint: CGPointMake(160, 21.7) controlPoint1: CGPointMake(191.9, 24.8) controlPoint2: CGPointMake(177, 21.7)];
[textPath addCurveToPoint: CGPointMake(115.3, 31) controlPoint1: CGPointMake(143, 21.7) controlPoint2: CGPointMake(128.1, 24.8)];
[textPath addCurveToPoint: CGPointMake(83.2, 55.9) controlPoint1: CGPointMake(102.5, 37.2) controlPoint2: CGPointMake(91.8, 45.5)];
[textPath addCurveToPoint: CGPointMake(63.85, 91.75) controlPoint1: CGPointMake(74.6, 66.3) controlPoint2: CGPointMake(68.15, 78.25)];
[textPath addCurveToPoint: CGPointMake(57.4, 133.9) controlPoint1: CGPointMake(59.55, 105.25) controlPoint2: CGPointMake(57.4, 119.3)];
[textPath addCurveToPoint: CGPointMake(63.85, 176.05) controlPoint1: CGPointMake(57.4, 148.5) controlPoint2: CGPointMake(59.55, 162.55)];
[textPath addCurveToPoint: CGPointMake(83.2, 211.9) controlPoint1: CGPointMake(68.15, 189.55) controlPoint2: CGPointMake(74.6, 201.5)];
[textPath addCurveToPoint: CGPointMake(115.3, 236.65) controlPoint1: CGPointMake(91.8, 222.3) controlPoint2: CGPointMake(102.5, 230.55)];
[textPath addCurveToPoint: CGPointMake(160, 245.8) controlPoint1: CGPointMake(128.1, 242.75) controlPoint2: CGPointMake(143, 245.8)];
[textPath addCurveToPoint: CGPointMake(211.3, 233.2) controlPoint1: CGPointMake(179.8, 245.8) controlPoint2: CGPointMake(196.9, 241.6)];
[textPath addLineToPoint: CGPointMake(244, 259.3)];
[textPath closePath];
[UIColor.blackColor setFill];
[textPath fill];
maskLayer = [CAShapeLayer layer];
maskLayer.path = [textPath CGPath];
maskLayer.strokeColor = [[UIColor blackColor] CGColor];
maskLayer.lineWidth = 3.0;
maskLayer.fillColor = [[UIColor redColor] CGColor];
[self.imgView.layer addSublayer:maskLayer];
}
You already have the method:
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:self.imgView];
if ([textPath containsPoint:touchPoint]) {
path=nil; //this is not need,unless u want to start a new path everytime this condition executes.
path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(touchPoint.x,touchPoint.y)];
[path addLineToPoint: CGPointMake(_startingPoint.x,_startingPoint.y)];
_startingPoint=touchPoint;
drawLayer = [CAShapeLayer layer];
drawLayer.path = [path CGPath];
drawLayer.strokeColor = [[UIColor blackColor] CGColor];
drawLayer.lineWidth = 3.0;
drawLayer.fillColor = [[UIColor redColor] CGColor];
[self.imgView.layer addSublayer:drawLayer];
NSLog(#"Touch moving point =x : %f Touch moving point =y : %f", touchPoint.x, touchPoint.y);
}
}
You can now verify , if the touch point is in the textPath whcih is a bezierPath.
If the touchPoint is in the textPath, then allow the draw, else dont draw.
The result will be something like this:
As you see, this code will allow you to draw only in the masked path.
If you want to draw outside of the textPath, then you can do simply:
if (![textPath containsPoint:touchPoint]) {
path=nil; //this is not need,unless u want to start a new path everytime this condition executes.
path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(touchPoint.x,touchPoint.y)];
[path addLineToPoint:CGPointMake(_startingPoint.x,_startingPoint.y)];
_startingPoint=touchPoint;
drawLayer = [CAShapeLayer layer];
drawLayer.path = [path CGPath];
drawLayer.strokeColor = [[UIColor blackColor] CGColor];
drawLayer.lineWidth = 3.0;
drawLayer.fillColor = [[UIColor redColor] CGColor];
[self.imgView.layer addSublayer:drawLayer];
NSLog(#"Touch moving point =x : %f Touch moving point =y : %f", touchPoint.x, touchPoint.y);
}
Note: You need to take care of your touches moved method in drawing the line. As the bezier path method addLineToPoint will add line to the touchPoint and this line may cross the maskedPath. You need to make sure you are close the previosu bezier path and start a new one to avoid the lines to be drawn on the outside part of masked area.
I assume you are you trying to display alphabets in some language, may be you can use that language font for dynamic display. Just a thought. Together with the logic mentioned above you can try this.

Does the way CALayer generate its contents Affect its scale animation?

#interface CircleRevealLayer : CALayer
#end
#implementation CircleRevealLayer
- (instancetype)init
{
if (self = [super init]) {
[self setNeedsDisplay];
[self displayIfNeeded];
}
return self;
}
- (void)display
{
self.contents = (__bridge id)([self maskImage].CGImage);
self.contentsGravity = kCAGravityCenter;
}
- (UIImage *)maskImage
{
static UIImage *mask = nil;
if (!mask) {
UIGraphicsBeginImageContext(CGSizeMake(SCREEN_WIDTH, SCREEN_HEIGHT));
UIBezierPath* bezierPath = UIBezierPath.bezierPath;
[bezierPath moveToPoint: CGPointMake(209.5, 368)];
[bezierPath addCurveToPoint: CGPointMake(207, 370.5) controlPoint1: CGPointMake(208.12, 368) controlPoint2: CGPointMake(207, 369.12)];
[bezierPath addCurveToPoint: CGPointMake(209.5, 373) controlPoint1: CGPointMake(207, 371.88) controlPoint2: CGPointMake(208.12, 373)];
[bezierPath addCurveToPoint: CGPointMake(212, 370.5) controlPoint1: CGPointMake(210.88, 373) controlPoint2: CGPointMake(212, 371.88)];
[bezierPath addCurveToPoint: CGPointMake(210.98, 368.49) controlPoint1: CGPointMake(212, 369.67) controlPoint2: CGPointMake(211.6, 368.94)];
[bezierPath addCurveToPoint: CGPointMake(209.5, 368) controlPoint1: CGPointMake(210.57, 368.18) controlPoint2: CGPointMake(210.05, 368)];
[bezierPath closePath];
[bezierPath moveToPoint: CGPointMake(411, 0)];
[bezierPath addCurveToPoint: CGPointMake(411, 736) controlPoint1: CGPointMake(411, 0) controlPoint2: CGPointMake(411, 736)];
[bezierPath addLineToPoint: CGPointMake(-3, 736)];
[bezierPath addLineToPoint: CGPointMake(-3, 0)];
[bezierPath addLineToPoint: CGPointMake(411, 0)];
[bezierPath addLineToPoint: CGPointMake(411, 0)];
[bezierPath closePath];
[UIColor.grayColor setFill];
[bezierPath fill];
mask = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//mask = [UIImage imageNamed:#"mask.PNG"];
}
return mask;
}
#end
#interface CircleRevealView : UIView
#end
#implementation CircleRevealView
+ (Class)layerClass{
return [CircleRevealLayer class];
}
#end
then, I create it like this:
_maskView = [[CircleRevealView alloc] initWithFrame:self.view.bounds];
_maskView.frame = self.view.bounds;
and add a scale animation:
POPSpringAnimation *springAnimation = [POPSpringAnimation animation];
springAnimation.property = [POPAnimatableProperty propertyWithName:kPOPViewScaleXY];
springAnimation.toValue=[NSValue valueWithCGPoint:CGPointMake(80, 80)];
springAnimation.velocity=[NSValue valueWithCGPoint:CGPointMake(1, 1)]; // change of value units per second
springAnimation.springBounciness=20; // value between 0-20 default at 4
springAnimation.springSpeed=3;
springAnimation.name=#"scaleXY1";
springAnimation.delegate=self;
[_maskView pop_addAnimation:springAnimation forKey:#"scaleXY1"];
the mask.PNG is just a white image with a hole in the center.
when I use UIBezierPath to draw the contents and assign it to the layer, the scale animation seems to happen from the top-left corner of the layer;
but if I instead use a image , the scale animation seems to happen from the center of it.
what I want is to generate dynamic contents with Core Graphics and scale the layer like when I use mask.PNG
update:
UIBezierPath
mask.PNG
the mask.PNG is generated from the UIBezierPath code, with the PaintCode.

Objective C - Create UIImage from this PaintCode code

I am using PaintCode and it has generated some code to create a shape with text overlayed.
I want to use the code to parse a string and generate a UIImage that I can save to the camera roll or share on FB, but I am struggling to generate the UIImage.
Any help would be great!
Here is the code:
- (void)drawShareImageWithText: (NSString*)text;
{
//// Color Declarations
UIColor* questionText = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1];
//// Bezier Drawing
UIBezierPath* bezierPath = UIBezierPath.bezierPath;
[bezierPath moveToPoint: CGPointMake(42.46, 0.09)];
[bezierPath addCurveToPoint: CGPointMake(53.37, 11) controlPoint1: CGPointMake(42.46, 0.09) controlPoint2: CGPointMake(47.66, 5.3)];
[bezierPath addLineToPoint: CGPointMake(255.6, 11)];
[bezierPath addCurveToPoint: CGPointMake(267.62, 11.92) controlPoint1: CGPointMake(261.76, 11) controlPoint2: CGPointMake(264.84, 11)];
[bezierPath addLineToPoint: CGPointMake(268.16, 12.05)];
[bezierPath addCurveToPoint: CGPointMake(275.95, 19.84) controlPoint1: CGPointMake(271.78, 13.37) controlPoint2: CGPointMake(274.63, 16.22)];
[bezierPath addCurveToPoint: CGPointMake(277, 32.4) controlPoint1: CGPointMake(277, 23.16) controlPoint2: CGPointMake(277, 26.24)];
[bezierPath addLineToPoint: CGPointMake(277, 148.6)];
[bezierPath addCurveToPoint: CGPointMake(276.08, 160.62) controlPoint1: CGPointMake(277, 154.76) controlPoint2: CGPointMake(277, 157.84)];
[bezierPath addLineToPoint: CGPointMake(275.95, 161.16)];
[bezierPath addCurveToPoint: CGPointMake(268.16, 168.95) controlPoint1: CGPointMake(274.63, 164.78) controlPoint2: CGPointMake(271.78, 167.63)];
[bezierPath addCurveToPoint: CGPointMake(255.6, 170) controlPoint1: CGPointMake(264.84, 170) controlPoint2: CGPointMake(261.76, 170)];
[bezierPath addLineToPoint: CGPointMake(21.4, 170)];
[bezierPath addCurveToPoint: CGPointMake(9.38, 169.08) controlPoint1: CGPointMake(15.24, 170) controlPoint2: CGPointMake(12.16, 170)];
[bezierPath addLineToPoint: CGPointMake(8.84, 168.95)];
[bezierPath addCurveToPoint: CGPointMake(1.05, 161.16) controlPoint1: CGPointMake(5.22, 167.63) controlPoint2: CGPointMake(2.37, 164.78)];
[bezierPath addCurveToPoint: CGPointMake(0, 148.6) controlPoint1: CGPointMake(0, 157.84) controlPoint2: CGPointMake(0, 154.76)];
[bezierPath addLineToPoint: CGPointMake(0, 32.4)];
[bezierPath addCurveToPoint: CGPointMake(0.92, 20.38) controlPoint1: CGPointMake(0, 26.24) controlPoint2: CGPointMake(0, 23.16)];
[bezierPath addLineToPoint: CGPointMake(1.05, 19.84)];
[bezierPath addCurveToPoint: CGPointMake(8.84, 12.05) controlPoint1: CGPointMake(2.37, 16.22) controlPoint2: CGPointMake(5.22, 13.37)];
[bezierPath addCurveToPoint: CGPointMake(21.4, 11) controlPoint1: CGPointMake(12.16, 11) controlPoint2: CGPointMake(15.24, 11)];
[bezierPath addLineToPoint: CGPointMake(31.54, 11)];
[bezierPath addCurveToPoint: CGPointMake(42.46, 0.09) controlPoint1: CGPointMake(37.25, 5.3) controlPoint2: CGPointMake(42.46, 0.09)];
[bezierPath closePath];
[StyleKit.Color1 setFill];
[bezierPath fill];
//// shareContent Drawing
CGRect shareContentRect = CGRectMake(15, 26, 247, 136.03);
NSMutableParagraphStyle* shareContentStyle = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
shareContentStyle.alignment = NSTextAlignmentCenter;
NSDictionary* shareContentFontAttributes = #{NSFontAttributeName: [UIFont fontWithName: #"Helvetica" size: 15], NSForegroundColorAttributeName: questionText, NSParagraphStyleAttributeName: shareContentStyle};
[text drawInRect: CGRectOffset(shareContentRect, 0, (CGRectGetHeight(shareContentRect) - [text boundingRectWithSize: shareContentRect.size options: NSStringDrawingUsesLineFragmentOrigin attributes: shareContentFontAttributes context: nil].size.height) / 2) withAttributes: shareContentFontAttributes];
}
All of this drawing code is generated under the expectation that it will be run within a graphics context created and managed by UIKit.
This is automatically the case within a UIView's drawRect method. But you want to generate a UIImage, so you need to setup a temporary graphics context just for that.
The general approach is as follows:
// specify size of the image
CGRect imageRect = CGRectMake(0,0,100,100);
// create the graphics context
UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0);
// insert calls to your drawing code here, to draw into the context
// ...
// save the image from the implicit context into an image
UIImage * finalImage = UIGraphicsGetImageFromCurrentImageContext();
// cleanup
UIGraphicsEndImageContext();
Erica Sadun's book on practical UIKit drawing is probably the best one-stop resource for this sort of thing.
Equivalent in Swift (language version 1.2):
// specify size of the image
let imageRect:CGRect = CGRectMake(0,0,100,100)
// create the graphics context
UIGraphicsBeginImageContextWithOptions(imageRect.size, false, 0)
// insert calls to your drawing code here, to draw into the context
// ...
// save the image from the implicit context into an image
let finalImage = UIGraphicsGetImageFromCurrentImageContext()
// cleanup
UIGraphicsEndImageContext()
Swift 4+ Version:
// specify size of the image
let imageSize = CGSize(width: 100, height: 100)
// create the graphics context
UIGraphicsBeginImageContextWithOptions(imageSize, false, 0)
// insert calls to your drawing code here, to draw into the context
// ...
// save the image from the implicit context into an image
let finalImage = UIGraphicsGetImageFromCurrentImageContext()
// cleanup
UIGraphicsEndImageContext()

Circular view and color and cifilter with animation

I'm working on an app, and i need to make an effects when the user click on a UIButton.
http://imageshack.com/a/img802/3337/on55.png
When the user click on the button on center in the screenshot, there is an halo with colors on a picture that be loading with web request. The picture was load with color, and actually i apply on it a cifilter that remove colors.
If it's possible, just explain to me how i can reproduce the circular view with background image.
Thanks.
So, i'm trying to explain my solution, i'm french and i've a poor english :D
To make this possible, i make a uiview with a custom drawrect, PaintCode really help me to do this, because my designer make some svg exemple file and i load it in PaintCode to make the UIBezierPath. Like this.
UIBezierPath* bezier2Path = [UIBezierPath bezierPath];
[bezier2Path moveToPoint: CGPointMake(160, 228.1)];
[bezier2Path addCurveToPoint: CGPointMake(148.16, 239.5) controlPoint1: CGPointMake(153.46, 228.1) controlPoint2: CGPointMake(148.16, 233.2)];
[bezier2Path addCurveToPoint: CGPointMake(160, 250.9) controlPoint1: CGPointMake(148.16, 245.8) controlPoint2: CGPointMake(153.46, 250.9)];
[bezier2Path addCurveToPoint: CGPointMake(171.84, 239.5) controlPoint1: CGPointMake(166.54, 250.9) controlPoint2: CGPointMake(171.84, 245.8)];
[bezier2Path addCurveToPoint: CGPointMake(160, 228.1) controlPoint1: CGPointMake(171.84, 233.2) controlPoint2: CGPointMake(166.54, 228.1)];
[bezier2Path closePath];
[bezier2Path moveToPoint: CGPointMake(160, 249.51)];
[bezier2Path addCurveToPoint: CGPointMake(149.62, 239.5) controlPoint1: CGPointMake(154.26, 249.51) controlPoint2: CGPointMake(149.62, 245.03)];
[bezier2Path addCurveToPoint: CGPointMake(160, 229.49) controlPoint1: CGPointMake(149.62, 233.97) controlPoint2: CGPointMake(154.26, 229.49)];
[bezier2Path addCurveToPoint: CGPointMake(170.38, 239.5) controlPoint1: CGPointMake(165.74, 229.49) controlPoint2: CGPointMake(170.38, 233.97)];
[bezier2Path addCurveToPoint: CGPointMake(160, 249.51) controlPoint1: CGPointMake(170.38, 245.03) controlPoint2: CGPointMake(165.74, 249.51)];
[bezier2Path closePath];
bezier2Path.miterLimit = 4;
When the uiview is init, i init her when my image is download from internet with AFNetworking. And i set the image in backgroug of my view in drawrect like this :
//// General Declarations
CGContextRef context = UIGraphicsGetCurrentContext();
//// Image Declarations
UIImage* bGTest = [UIImage imageNamed:self.image];
//// Calque_2_-_copie
{
//// Bezier 2 Drawing
UIBezierPath* bezier2Path = [UIBezierPath bezierPath];
[bezier2Path moveToPoint: CGPointMake(160, 228.1)];
[bezier2Path addCurveToPoint: CGPointMake(148.16, 239.5) controlPoint1: CGPointMake(153.46, 228.1) controlPoint2: CGPointMake(148.16, 233.2)];
[bezier2Path addCurveToPoint: CGPointMake(160, 250.9) controlPoint1: CGPointMake(148.16, 245.8) controlPoint2: CGPointMake(153.46, 250.9)];
[bezier2Path addCurveToPoint: CGPointMake(171.84, 239.5) controlPoint1: CGPointMake(166.54, 250.9) controlPoint2: CGPointMake(171.84, 245.8)];
[bezier2Path addCurveToPoint: CGPointMake(160, 228.1) controlPoint1: CGPointMake(171.84, 233.2) controlPoint2: CGPointMake(166.54, 228.1)];
[bezier2Path closePath];
[bezier2Path moveToPoint: CGPointMake(160, 249.51)];
[bezier2Path addCurveToPoint: CGPointMake(149.62, 239.5) controlPoint1: CGPointMake(154.26, 249.51) controlPoint2: CGPointMake(149.62, 245.03)];
[bezier2Path addCurveToPoint: CGPointMake(160, 229.49) controlPoint1: CGPointMake(149.62, 233.97) controlPoint2: CGPointMake(154.26, 229.49)];
[bezier2Path addCurveToPoint: CGPointMake(170.38, 239.5) controlPoint1: CGPointMake(165.74, 229.49) controlPoint2: CGPointMake(170.38, 233.97)];
[bezier2Path addCurveToPoint: CGPointMake(160, 249.51) controlPoint1: CGPointMake(170.38, 245.03) controlPoint2: CGPointMake(165.74, 249.51)];
[bezier2Path closePath];
bezier2Path.miterLimit = 4;
CGContextSaveGState(context);
[bezier2Path addClip];
[bGTest drawInRect: CGRectMake(0, 0, bGTest.size.width, bGTest.size.height)];
CGContextRestoreGState(context);
}
It's really simple, and after i can animate my view only with alpha component to make my ripple animation.
See screenshot now :
http://imageshack.com/a/img839/4613/v2wm.png
Thanks for your reply.
I'm not sure that you're asking about progress circle, but you can use image masking to get any shape of view you want. This is example of progress circle:
Create custom view and override drawRect method like this
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, true);
CGContextClipToMask(context, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), [UIImage imageNamed:#"circle"]);
CGContextBeginPath(context);
UIColor* colour = [UIColor greenColor];
CGFloat red, green, blue, alpha;
[colour getRed:&red green:&green blue:&blue alpha:&alpha];
CGContextSetRGBFillColor(context,red,green,blue,alpha);
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 1.5f);
CGContextMoveToPoint(context, self.frame.size.width / 2,self.frame.size.height / 2);
CGContextAddArc(context, self.frame.size.width / 2,self.frame.size.height / 2, self.frame.size.width, M_PI_2 , M_PI_2 - 2 * M_PI * (1 - self.progress) , 0);
CGContextClosePath(context);
CGContextFillPath(context);
}
self.progress is value from 0 to 1.
Last part of code is used to draw green arc with a big radius inside your view:
circle image is a ring that will be user to mask arc (black with transparent background):
After you combine this two (draw and mask), you get something like this (you can mask your image with filled circle):
Changing circle you can change line width. Don't forget to set transparent background to your custom view.
Regards

Change direction in stroke animation

I want to revert the direction of a path drawing. So I changed fromValue and toValue propeties, but now full path is visible at the start of animation and it begins to disappear.
I have the path:
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(213.79, 170.83)];
[bezierPath addCurveToPoint: CGPointMake(131.93, 95) controlPoint1: CGPointMake(212.14, 128.68) controlPoint2: CGPointMake(176.13, 95)];
[bezierPath addCurveToPoint: CGPointMake(50, 173.85) controlPoint1: CGPointMake(86.68, 95) controlPoint2: CGPointMake(50, 130.3)];
[bezierPath addCurveToPoint: CGPointMake(131.93, 252.7) controlPoint1: CGPointMake(50, 217.4) controlPoint2: CGPointMake(86.68, 252.7)];
[bezierPath addCurveToPoint: CGPointMake(157.55, 248.76) controlPoint1: CGPointMake(140.88, 252.7) controlPoint2: CGPointMake(149.49, 251.32)];
[bezierPath addCurveToPoint: CGPointMake(209.69, 281) controlPoint1: CGPointMake(166.59, 267.78) controlPoint2: CGPointMake(186.54, 281)];
[bezierPath addCurveToPoint: CGPointMake(267, 225.85) controlPoint1: CGPointMake(241.34, 281) controlPoint2: CGPointMake(267, 256.31)];
[bezierPath addCurveToPoint: CGPointMake(213.79, 170.83) controlPoint1: CGPointMake(267, 196.71) controlPoint2: CGPointMake(243.53, 172.86)];
[bezierPath closePath];
[color0 setStroke];
bezierPath.lineWidth = 11;
[bezierPath stroke];
And the animation:
UIColor* color = [UIColor colorWithRed: 0.369 green: 0.42 blue: 0.475 alpha: 1];
UIBezierPath *bezierPath = [self bezierPath];
CAShapeLayer *bezier = [[CAShapeLayer alloc] init];
bezier.path = bezierPath.CGPath;
bezier.lineCap = kCALineCapRound;
bezier.strokeColor = color.CGColor;
bezier.fillColor = [UIColor clearColor].CGColor;
bezier.strokeStart = 1.0;
bezier.strokeEnd = 0.0;
bezier.lineWidth = 8.0;
bezier.strokeStart = 0.0;
bezier.strokeEnd = 1.0;
[self.view.layer addSublayer:bezier];
if (animate)
{
CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
animateStrokeEnd.duration = appDelegate.myPlayer.audioPlayer.duration;
animateStrokeEnd.fromValue = [NSNumber numberWithFloat:1.0f];
animateStrokeEnd.toValue = [NSNumber numberWithFloat:0.0f];
[bezier addAnimation:animateStrokeEnd forKey:#"strokeEndAnimation"];
}
You were on the right track but you should have animated the strokeStart property instead.
Start with having both strokeStart and strokeEnd as 1.0.
Then animate strokeStart from 1.0 to 0.0. This will give you the effect of the path being stroked from the end to the start.
For example when 25% of the path is stoked you will have strokeStart at 0.75 and strokeEnd at 1.0.

Resources