How do you set a gradient fillcolor for cashapelayer without using a mask? - cocoa-touch

How do you set a gradient fillcolor for cashapelayer?
Related question with clearer explanation:
Using Cocoa To Follow A Path With A Gradient
I need a gradient that's not a mask, but instead a gradient based on the drawing of the cashapelayer's path.
I can't use a gradient mask on top, because I'm making a route on the minimap in my game. So if the player walks over his own tracks, it should be in a different color.
I want it like this mapview's polyline:
Source: http://cdn4.raywenderlich.com/wp-content/uploads/2014/06/23_multicolor_polyline.png
I made the minimap route by:
logging all the user's different directions, then running them through a loop into bezier paths.
I appended the Bezier paths, and then put it on a cashapelayer.
Is there a way to have a multicolored in a cashapelayer?
Is there a keypath for cabasicanimation that can put a gradient?
My code is below, and some images.
[mymapview.layer.sublayers makeObjectsPerformSelector:#selector(removeFromSuperlayer)];
[[mymapview subviews]
makeObjectsPerformSelector:#selector(removeFromSuperview)];
int i = 0;
int x = 17;
int y = 272;
int m = 16;
UIBezierPath *kpath = [UIBezierPath bezierPath]; while (i < HistDirections.count)
{
if (i > 0)
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(x, y)];
if ([[HistDirections objectAtIndex:i] intValue] ==1)
{
[path addLineToPoint:CGPointMake(x, y-m)];
y = y - m;
}
else if ([[HistDirections objectAtIndex:i] intValue] ==2)
{
[path addLineToPoint:CGPointMake(x-m, y)];
x = x -m;
}
else if ([[HistDirections objectAtIndex:i] intValue] ==3)
{
[path addLineToPoint:CGPointMake(x+m, y)];
x = x+m;
}
else
{
[path addLineToPoint:CGPointMake(x, y+m)];
y = y - m;
}
[kpath appendPath:path];
}
i++;
}
[CATransaction begin];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[CATransaction setCompletionBlock:^{
UIImageView *viewpulse = [[UIImageView alloc] initWithFrame:CGRectMake(x -5, y-5, 10.0, 10.0)];
viewpulse.image = [UIImage imageNamed:#"arro.png"];
viewpulse.backgroundColor = [UIColor clearColor];
if(direction == 1)
{
viewpulse.transform = CGAffineTransformMakeRotation(-M_PI/2);
}
else if (direction == 2)
{
viewpulse.transform = CGAffineTransformMakeRotation(M_PI);
}
else if (direction == 4)
{
viewpulse.transform = CGAffineTransformMakeRotation(M_PI/2);
}
[mymapview addSubview:viewpulse];
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.duration = 0.8;
scaleAnimation.repeatCount = HUGE_VAL;
scaleAnimation.autoreverses = YES;
scaleAnimation.fromValue = [NSNumber numberWithFloat:1.6];
scaleAnimation.toValue = [NSNumber numberWithFloat:0.8];
[viewpulse.layer addAnimation:scaleAnimation forKey:#"scale"];
}];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
kpath.lineCapStyle = kCGLineCapRound;
kpath.lineCapStyle = kCGLineJoinRound;
shapeLayer.path = [kpath CGPath];
shapeLayer.strokeColor = [[UIColor colorWithRed:51/255.0f green:(51)/255.0f blue:170/255.0f alpha:1.0f] CGColor];
shapeLayer.lineWidth = 4.0;
shapeLayer.lineCap = kCALineCapRound;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];
[mymapview.layer addSublayer:shapeLayer];
CABasicAnimation *HAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
float dur = (HistDirections.count * 0.27);
if (dur > 2)
{
dur = 2;
}
HAnimation.duration = dur;
HAnimation.repeatCount = 1.0;
HAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
HAnimation.toValue = [NSNumber numberWithFloat:1.0f];
/*
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = mymapview.frame;
gradientLayer.colors = #[(__bridge id)[UIColor blueColor].CGColor,(__bridge id)[UIColor greenColor].CGColor,(__bridge id)[UIColor yellowColor].CGColor,(__bridge id)[UIColor orangeColor].CGColor, (__bridge id)[UIColor redColor].CGColor];
gradientLayer.startPoint = CGPointMake(0,0.5);
gradientLayer.endPoint = CGPointMake(1,0.5);
[mymapview.layer addSublayer:gradientLayer];
gradientLayer.mask = shapeLayer;*/
[CATransaction commit];
Gradient mask:
Monocolor line:

Nevermind! I figured out what I can do. Since I create the layer from multiple paths, I just put the cgpaths into an array, and looped each path into a unique cashapelayer with it's own color

Related

How to remove already created path using CGMutablePathRef?

I am plotting line according bottom selected dots.First Showing start from 0 and after that it showing according to selected dots But line chart is showing previous drawn line.
Here I am using SHLineGrapgView. Here is code :
- (void)drawPlot:(SHPlot *)plot {
NSDictionary *theme = plot.plotThemeAttributes;
//
CAShapeLayer *backgroundLayer = [CAShapeLayer layer];
backgroundLayer.frame = self.bounds;
backgroundLayer.fillColor = [UIColor clearColor].CGColor;
backgroundLayer.backgroundColor = [UIColor clearColor].CGColor;
[backgroundLayer setStrokeColor:[UIColor clearColor].CGColor];
[backgroundLayer setLineWidth:((NSNumber *)theme[kPlotStrokeWidthKey]).intValue];
CGMutablePathRef backgroundPath= CGPathCreateMutable();
//
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.frame = self.bounds;
circleLayer.fillColor = [UIColor redColor].CGColor;
circleLayer.backgroundColor = [UIColor clearColor].CGColor;
[circleLayer setStrokeColor:((UIColor *)theme[kPlotPointFillColorKey]).CGColor];
[circleLayer setLineWidth:((NSNumber *)theme[kPlotStrokeWidthKey]).intValue];
CGMutablePathRef circlePath = CGPathCreateMutable();
//
CAShapeLayer *graphLayer = [CAShapeLayer layer];
graphLayer.frame = self.bounds;
graphLayer.fillColor = [UIColor clearColor].CGColor;
graphLayer.backgroundColor = [UIColor clearColor].CGColor;
[graphLayer setStrokeColor:((UIColor *)theme[kPlotStrokeColorKey]).CGColor];
[graphLayer setLineWidth:((NSNumber *)theme[kPlotStrokeWidthKey]).intValue];
CGMutablePathRef graphPath = CGPathCreateMutable();
double yRange = [_yAxisRange doubleValue]; // this value will be in dollars
double yIntervalValue = yRange / INTERVAL_COUNT;
//logic to fill the graph path, ciricle path, background path.
NSLog(#"plottingValues Dictionary %#",plot.plottingValues);
[plot.plottingValues enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDictionary *dic = (NSDictionary *)obj;
NSLog(#"Plotting Dictionary %#",dic);
__block NSNumber *_key = nil;
__block NSNumber *_value = nil;
[dic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
_key = (NSNumber *)key;
_value = (NSNumber *)obj;
}];
int xIndex = [self getIndexForValue:_key forPlot:plot];
//x value
double height = self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE;
double y = height - ((height / ([_yAxisRange doubleValue] + yIntervalValue)) * [_value doubleValue]);
(plot.xPoints[xIndex]).x = ceil((plot.xPoints[xIndex]).x);
(plot.xPoints[xIndex]).y = ceil(y);
}];
//move to initial point for path and background.
CGPathMoveToPoint(graphPath, NULL, _leftMarginToLeave, plot.xPoints[0].y);
CGPathMoveToPoint(backgroundPath, NULL, _leftMarginToLeave, plot.xPoints[0].y);
int count = (int)_xAxisValues.count;
for(int i=0; i< count; i++)
{
CGPathRef path=CGPathCreateCopy(graphPath);
CGPoint point = plot.xPoints[i];
// CGContextRef ref=CGContextCopyPath(<#CGContextRef _Nullable c#>)
// CGContextClip
CGPathAddLineToPoint(graphPath, NULL, point.x, point.y);
CGPathAddLineToPoint(backgroundPath, NULL, point.x, point.y);
CGFloat dotsSize = [_themeAttributes[kDotSizeKey] floatValue];
CGPathAddEllipseInRect(circlePath, NULL, CGRectMake(point.x - dotsSize/2.0f, point.y - dotsSize/2.0f, dotsSize, dotsSize));
}
//move to initial point for path and background.
CGPathAddLineToPoint(NULL, NULL, _leftMarginToLeave + PLOT_WIDTH, plot.xPoints[count -1].y);
CGPathAddLineToPoint(backgroundPath, NULL, _leftMarginToLeave + PLOT_WIDTH, plot.xPoints[count - 1].y);
//additional points for background.
CGPathAddLineToPoint(backgroundPath, NULL, _leftMarginToLeave + PLOT_WIDTH, self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE);
CGPathAddLineToPoint(backgroundPath, NULL, _leftMarginToLeave, self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE);
CGPathCloseSubpath(backgroundPath);
backgroundLayer.path = backgroundPath;
graphLayer.path = graphPath;
circleLayer.path = circlePath;
//animation
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
animation.duration = 1;
animation.fromValue = #(0.0);
animation.toValue = #(1.0);
[graphLayer addAnimation:animation forKey:#"strokeEnd"];
backgroundLayer.zPosition = 0;
graphLayer.zPosition = 1;
circleLayer.zPosition = 2;
[self.layer addSublayer:graphLayer];
[self.layer addSublayer:circleLayer];
[self.layer addSublayer:backgroundLayer];
NSUInteger count2 = _xAxisValues.count;
for(int i=0; i< count2; i++){
CGPoint point = plot.xPoints[i];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.backgroundColor = [UIColor clearColor];
btn.tag = i;
btn.frame = CGRectMake(point.x, point.y - 20, 40, 40);
[btn addTarget:self action:#selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
objc_setAssociatedObject(btn, kAssociatedPlotObject, plot, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self addSubview:btn];
}
}

Rotating a CAShapeLayer arc about its center using CABasicAnimation

I have an arc that I have drawn using CAShapeLayer and I want it to rotate around the circle's center. I am trying to get this animation using a CABasicAnimation on the 'transform.rotation' property. But the rotation seems is happening about a point that is not the same as the circle's center.
-(void)drawRect:(CGRect)rect{
int radius = 100;
CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius].CGPath;
circle.fillColor = [UIColor orangeColor].CGColor;
circle.strokeColor = [UIColor blueColor].CGColor;
circle.lineWidth = 5;
circle.strokeStart = 0.0f;
circle.strokeEnd = 0.1f;
[self.layer addSublayer:circle];
CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
spinAnimation.byValue = [NSNumber numberWithFloat:2.0f*M_PI];
spinAnimation.duration = 4;
spinAnimation.repeatCount = INFINITY;
[circle addAnimation:spinAnimation forKey:#"indeterminateAnimation"];
}
I know its an old problem, but whats the way out. I have tinkered a lot by setting the layer's bounds or the anchor point but it doesn't rotate about the center yet.
circle.bounds = self.frame;
Here is how I add the view to the view controller.
[self.view addSubview:[[ProgressIndicator alloc] initWithFrame:CGRectMake(50, 50, 200, 200)]];
This is what I eventually did.
The mistake was to add the animation to the sublayer and not the layer.
There is no need to tinker with anchorPoint or position here when the rotation is just needed about the center of the circle.
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
int radius = 50;
CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius].CGPath;
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor blueColor].CGColor;
circle.lineWidth = 5;
circle.strokeStart = 0.0f;
circle.strokeEnd = 0.1f;
[self.layer addSublayer:circle];
}
return self; }
- (void)drawRect:(CGRect)rect {
CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
spinAnimation.byValue = [NSNumber numberWithFloat:2.0f*M_PI];
spinAnimation.duration = 4;
spinAnimation.repeatCount = INFINITY;
[self.layer addAnimation:spinAnimation forKey:#"indeterminateAnimation"]; }
Think is better to do something like this)
CGFloat center = CGRectGetWidth(frame) / 2;
CGFloat lineWidth = 5;
CGFloat radius = center - lineWidth / 2;
CGRect bounds = frame;
bounds.origin = CGPointZero;
CAShapeLayer *spinLayer = [CAShapeLayer layer];
spinLayer.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(center, center) radius:radius startAngle:0 endAngle:0.2 clockwise:YES].CGPath;
spinLayer.fillColor = [UIColor clearColor].CGColor;
spinLayer.strokeColor = [UIColor blueColor].CGColor;
spinLayer.lineWidth = 5;
spinLayer.lineCap = kCALineCapRound;
spinLayer.bounds = bounds;
spinLayer.position = CGPointMake(center, center);
[self.layer insertSublayer:spinLayer above:nil];
And animation:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
animation.byValue = [NSNumber numberWithFloat:2.f * M_PI];
animation.duration = 1.5f;
animation.repeatCount = INFINITY;
[spinLayer addAnimation:animation forKey:#"lineRotation"];
[self setNeedsLayout];
Swift 3
var bounds = frame
bounds.origin = CGPoint.zero
let center: CGFloat = frame.size.width
let lineWidth: CGFloat = 5
let radius = center - lineWidth / 2
let spinLayer = CAShapeLayer()
spinLayer.path = UIBezierPath(arcCenter: CGPoint(x: center, y: center),
radius: radius,
startAngle: 0,
endAngle: 0.2,
clockwise: true).cgPath
spinLayer.strokeColor = UIColor.blue.cgColor
spinLayer.fillColor = UIColor.clear.cgColor
spinLayer.lineWidth = lineWidth
spinLayer.lineCap = kCALineCapRound
spinLayer.bounds = bounds
spinLayer.position = CGPoint(x: center, y: center)
view.layer.insertSublayer(spinLayer, above: nil)
let rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation.byValue = NSNumber(value: 2*M_PI as Double)
rotation.duration = 1
rotation.repeatCount = Float.infinity
spinLayer.add(rotation, forKey: "lineRotation")

How to set the cagradientcolor to the uibutton cashapelayer objective c.I want to fill colour to different shaped button

I want to add the colour to UIButton CAShape layer.Is that possible according to the reference in the url Gradient color effect on CAShapeLayer.. we can add the colour to the UIButton CAShape layer.I can see the colour to the button stroke but i want the gradient colour to the button CAShape layer.please help in setting the colour to UIButton CAShape layer.The code is
-(void)changeColour:(id)sender
{
#try{
if(m_cObjbuttonPtr1.layer.sublayers.count > 0){for(CALayer *layer in m_cObjbuttonPtr1.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]]) [layer removeFromSuperlayer];}}if (m_cObjbuttonPtr2.layer.sublayers.count > 0){ for(CALayer *layer in m_cObjbuttonPtr2.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]])[layer removeFromSuperlayer];}}if(m_cObjbuttonPtr3.layer.sublayers.count > 0){for(CALayer *layer in m_cObjbuttonPtr3.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]]) [layer removeFromSuperlayer];}}if (m_cObjbuttonPtr4.layer.sublayers.count > 0){ for(CALayer *layer in m_cObjbuttonPtr4.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]])[layer removeFromSuperlayer];}}if(m_cObjbuttonPtr5.layer.sublayers.count > 0){ for(CALayer *layer in m_cObjbuttonPtr5.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]])[layer removeFromSuperlayer];}}}#catch (NSException *exception){}
UIButton *tempButton =(UIButton *)sender;
UIBezierPath *aPath = [UIBezierPath bezierPath];
[aPath moveToPoint:CGPointMake(0.0, 0.0)];
[aPath addLineToPoint:CGPointMake(0.0, 35.0)];
[aPath moveToPoint:CGPointMake(0.0, 35.0)];
[aPath addLineToPoint:CGPointMake(80.0, 55.0)];
[aPath moveToPoint:CGPointMake(80.0, 55.0)];
[aPath addLineToPoint:CGPointMake(180.0, 35.0)];
[aPath moveToPoint:CGPointMake(180.0, 35.0)];
[aPath addLineToPoint:CGPointMake(180.0, 0.0)];
[aPath moveToPoint:CGPointMake(180.0, 0.0)];
[aPath addLineToPoint:CGPointMake(0.0, 0.0)];
[aPath closePath];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
if(tempButton.tag == 1)
shapeLayer.frame = m_cObjbuttonPtr1.bounds;
if(tempButton.tag == 2)
shapeLayer.frame = m_cObjbuttonPtr2.bounds;
if(tempButton.tag == 3)
shapeLayer.frame = m_cObjbuttonPtr3.bounds;
if(tempButton.tag == 4)
shapeLayer.frame = m_cObjbuttonPtr4.bounds;
if(tempButton.tag == 5)
shapeLayer.frame = m_cObjbuttonPtr5.bounds;
shapeLayer.path = aPath.CGPath;
[shapeLayer setStrokeColor:[[UIColor redColor] CGColor]];
shapeLayer.fillColor = [[UIColor redColor] CGColor];
shapeLayer.lineWidth = 2;
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
if(tempButton.tag == 1)
gradientLayer.frame = m_cObjbuttonPtr1.bounds;
if(tempButton.tag == 2)
gradientLayer.frame = m_cObjbuttonPtr2.bounds;
if(tempButton.tag == 3)
gradientLayer.frame = m_cObjbuttonPtr3.bounds;
if(tempButton.tag == 4)
gradientLayer.frame = m_cObjbuttonPtr4.bounds;
if(tempButton.tag == 5)
gradientLayer.frame = m_cObjbuttonPtr5.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor colorWithRed:0.98f green:0.31f blue:0.46f alpha:0.0].CGColor,
(id)[UIColor colorWithRed:0.98f green:0.31f blue:0.14f alpha:0.0].CGColor,nil];
gradientLayer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:1.0f],
nil];
if(tempButton.tag == 1){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, shapeLayer.frame.size.width, shapeLayer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = colors;
[gradientLayer setMask:shapeLayer];
[shapeLayer setFillRule:kCAFillRuleEvenOdd];
[shapeLayer setFillColor:[[UIColor orangeColor] CGColor]];
[m_cObjbuttonPtr1.layer addSublayer:shapeLayer];
}
if(tempButton.tag == 2){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, m_cObjbuttonPtr2.layer.frame.size.width, m_cObjbuttonPtr2.layer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor colorWithRed:0.98f green:0.31f blue:0.46f alpha:0.0].CGColor,
(id)[UIColor colorWithRed:0.98f green:0.31f blue:0.14f alpha:0.0].CGColor,
nil];
[gradientLayer setMask:shapeLayer];
[m_cObjbuttonPtr2.layer addSublayer:shapeLayer];
}
if(tempButton.tag == 3){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, m_cObjbuttonPtr3.layer.frame.size.width, m_cObjbuttonPtr3.layer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = colors;
[gradientLayer setMask:shapeLayer];
[m_cObjbuttonPtr3.layer addSublayer:shapeLayer];
}
if(tempButton.tag == 4){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, m_cObjbuttonPtr4.layer.frame.size.width, m_cObjbuttonPtr4.layer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = colors;
[gradientLayer setMask:shapeLayer];
[m_cObjbuttonPtr4.layer addSublayer:shapeLayer];
}
if(tempButton.tag == 5){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, m_cObjbuttonPtr5.layer.frame.size.width, m_cObjbuttonPtr5.layer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = colors;
[gradientLayer setMask:shapeLayer];
[m_cObjbuttonPtr5.layer addSublayer:shapeLayer];
}
}

CABasicAnimation - Setting start stroke position

I'm animating the drawing of a basic circle. This works fine, except the animation begins drawing at the 3 o'clock position. Does anyone know how I can make it start at 12 o'clock?
self.circle = [CAShapeLayer layer];
self.circle.fillColor = nil;
self.circle.lineWidth = 7;
self.circle.strokeColor = [UIColor blackColor].CGColor;
self.circle.bounds = CGRectMake(0, 0, 200, 200);
self.circle.path = [UIBezierPath bezierPathWithOvalInRect:self.circle.bounds].CGPath;
[self.view.layer addSublayer:self.circle];
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
drawAnimation.duration = 5.0;
drawAnimation.repeatCount = 1.0;
drawAnimation.removedOnCompletion = NO;
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue = [NSNumber numberWithFloat:1.0f];
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[self.circle addAnimation:drawAnimation forKey:#"drawCircleAnimation"];
You can use bezierPathWithArcCenter instead of bezierPathWithOvalInRect, because that allows to specify a start and end angle:
CGFloat radius = self.circle.bounds.size.width/2; // Assuming that width == height
self.circle.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius)
radius:radius
startAngle:(-M_PI/2)
endAngle:(3*M_PI/2)
clockwise:YES].CGPath;
See the bezierPathWithArcCenter documentation for the meaning of the angles.

Why does my marque not follow my image?

When adding an image as a SubView to another UIImageView, I am adding a marque over the new image that should follow as it is being edited (moved, zoom in/out, rotate).
I can not get the marque to stay connected to the frame of the new image though. It is initially connected when the image is added but once moved the marque goes away from the image frame.
Here is my code:
**viewDidLoad:**
if (!_marque)
{
_marque = [[CAShapeLayer layer] retain];
_marque.fillColor = [[UIColor clearColor] CGColor];
_marque.strokeColor = [[UIColor cyanColor] CGColor];
_marque.lineWidth = 1.0f;
_marque.lineJoin = kCALineJoinRound;
_marque.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:10],[NSNumber numberWithInt:5], nil];
_marque.bounds = CGRectMake(_stampedImageView.frame.origin.x, _stampedImageView.frame.origin.y, 0, 0);
_marque.position = CGPointMake(_stampedImageView.frame.origin.x + self.view.frame.origin.x, _stampedImageView.frame.origin.y + self.view.frame.origin.y);
}
[[_stampedImageView layer] addSublayer:_marque];
**marque Method:**
if (![_marque actionForKey:#"linePhase"])
{
CABasicAnimation *dashAnimation;
dashAnimation = [CABasicAnimation animationWithKeyPath:#"lineDashPhase"];
[dashAnimation setFromValue:[NSNumber numberWithFloat:0.0f]];
[dashAnimation setToValue:[NSNumber numberWithFloat:15.0f]];
[dashAnimation setDuration:0.5f];
[dashAnimation setRepeatCount:HUGE_VALF];
[_marque addAnimation:dashAnimation forKey:#"linePhase"];
}
_marque.bounds = CGRectMake(_stampedImageView.frame.origin.x, _stampedImageView.frame.origin.y, 0, 0);
_marque.position = CGPointMake(_stampedImageView.frame.origin.x, _stampedImageView.frame.origin.y);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, frame);
[_marque setPath:path];
CGPathRelease(path);
_marque.hidden = NO;
**panGestureRecognizer:**
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan)
{
_firstX = [_stampedImageView center].x;
_firstY = [_stampedImageView center].y;
}
translatedPoint = CGPointMake(_firstX+translatedPoint.x, _firstY+translatedPoint.y);
[_stampedImageView setCenter:translatedPoint];
[self showOverlayWithFrame:_stampedImageView.frame];
Could someone help me see what I am missing please?
Thanks!
I think you may have an error in this line:
CGPathAddRect(path, NULL, frame);
You haven't defined frame anywhere that I can see. Maybe _stampedImageView.frame?