Custom shaped MPMoviePlayerController - ios

How can I achieve custom shaped movie in IOS?
I have a UIBezierPath and CAShapeLayer. I would like to display movie in that shape.
I'm looking for the effect like skew - http://i57.tinypic.com/16020ps.jpg
I'm using QR code reader and there I get the boundaries(UIBezierPath) of the found qr code. I want to be able to display the video over the qr code to achieve AR effect.
Thanks for the help!

You can do this by creating a mask layer on top of the MPMoviePlayerController view.
I just tested this by creating a simple single view project. I added the QuartzCore and MediaPlayer frameworks.
This is the code from ViewController.m:
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
#import <MediaPlayer/MediaPlayer.h>
#interface ViewController ()
#property (nonatomic, strong) MPMoviePlayerController *movieController;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *moviePath = [[NSBundle mainBundle] pathForResource:#"myMovie" ofType:#"mov"];
NSURL *url = nil;
if (moviePath != nil) {
url = [NSURL fileURLWithPath:moviePath];
}
self.movieController = [[MPMoviePlayerController alloc] initWithContentURL:url];
self.movieController.view.frame = CGRectMake(50, 50, 400, 400);
[self.view addSubview:self.movieController.view];
[self.movieController play];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.movieController.view.bounds;
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(118.81, 189.76)];
[bezierPath addCurveToPoint: CGPointMake(188.77, 37.51) controlPoint1: CGPointMake(118.81, 189.76) controlPoint2: CGPointMake(138.99, 36.06)];
[bezierPath addCurveToPoint: CGPointMake(255.06, 158.26) controlPoint1: CGPointMake(238.56, 38.96) controlPoint2: CGPointMake(226.1, 78.56)];
[bezierPath addCurveToPoint: CGPointMake(369.21, 200.26) controlPoint1: CGPointMake(284.02, 237.96) controlPoint2: CGPointMake(314.4, 134.08)];
[bezierPath addCurveToPoint: CGPointMake(269.79, 300.02) controlPoint1: CGPointMake(424.02, 266.44) controlPoint2: CGPointMake(319.71, 329.77)];
[bezierPath addCurveToPoint: CGPointMake(151.95, 300.02) controlPoint1: CGPointMake(219.86, 270.26) controlPoint2: CGPointMake(202.68, 327.08)];
[bezierPath addCurveToPoint: CGPointMake(15.71, 284.27) controlPoint1: CGPointMake(101.22, 272.95) controlPoint2: CGPointMake(-0.1, 369.78)];
[bezierPath addCurveToPoint: CGPointMake(118.81, 189.76) controlPoint1: CGPointMake(31.51, 198.75) controlPoint2: CGPointMake(118.81, 189.76)];
[bezierPath closePath];
maskLayer.fillColor = [[UIColor whiteColor] CGColor];
maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
maskLayer.path = [bezierPath CGPath];
self.movieController.view.layer.mask = maskLayer;
}
#end
(The bezier path is a hat shape created quickly in PaintCode, so it's a bit odd.)

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()

How to draw an open ended triangle with a specific angle in an UIView?

I'm stumped here and need some assistance with this. For testing purposes I have a UIView that I draw into via drawRect (code below). I'm able to draw a circle with an specific angle and such but it's filled and closed. I need it to be open and stroked. I'm currently using UIBezierPath to do this but is there better way to do this? I can draw the open ended triangle like I want in UIBezierPath but I can't specify the angle that I need it to be (code below also). Any assistance with this would be much appreciated. Thanks.
The picture below is how I would like it to look when I draw it with a specific angle.
#import "AngleView.h"
#define DEGREES_TO_RADIANS(degrees) ((M_PI * degrees)/ 180)
#implementation AngleView
-(void)drawRect:(CGRect)rect {
UIBezierPath *aPath = [UIBezierPath bezierPathWithArcCenter:CGPointZero
radius:50
startAngle:0
endAngle:DEGREES_TO_RADIANS(45)
clockwise:NO];
[aPath fill];
}
#end
and here is how I can draw it without a specific angle.
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(86.5, 33.5)];
[bezierPath addLineToPoint: CGPointMake(60.5, 62.5)];
[bezierPath addLineToPoint: CGPointMake(87.5, 62.5)];
[[UIColor blackColor] setStroke];
bezierPath.lineWidth = 1;
[bezierPath stroke];
Instead of trying draw one single line you can draw two separate originating from same point and you can give angle to one of them.
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0, 119.5); //here you can set originating point of line
CGContextRotateCTM(context, -45 * M_PI / 180); //Change Angle here -45
UIBezierPath* bezierPath = UIBezierPath.bezierPath;
[bezierPath moveToPoint: CGPointMake(0, 0)];
[bezierPath addCurveToPoint: CGPointMake(39, 0) controlPoint1: CGPointMake(39, 0) controlPoint2: CGPointMake(39, 0)];
[UIColor.blackColor setStroke];
bezierPath.lineWidth = 1;
[bezierPath stroke];
CGContextRestoreGState(context);
//Second UIBezierPath with 0 angle
context = UIGraphicsGetCurrentContext();
UIBezierPath* bezier2Path = UIBezierPath.bezierPath;
[bezier2Path moveToPoint: CGPointMake(0, 119.5)];
[bezier2Path addCurveToPoint: CGPointMake(38.5, 119.5) controlPoint1: CGPointMake(38.5, 119.5) controlPoint2: CGPointMake(38.5, 119.5)];
[UIColor.blackColor setStroke];
bezier2Path.lineWidth = 1;
[bezier2Path stroke];
CGContextRestoreGState(context);
}

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