Core animation: why can I not composite two animations? - animation

I am trying to animate a wheel
When the finger rests for > 0.1s, the wheel ' pops out ' ie I animate Scale from 1.0 to 1.2.
when the finger moves, the wheel rotates with it ( only if it is popped out ).
But I'm getting a problem: as soon as it starts to rotate, the scale reduces back to 1.0.
- (void) spin: (Direction) direction
{
float thetaOld = thetaWheel;
float k = (direction == AntiClockwise) ? -1 : 1;
float t = 2 * M_PI * ( k / 12.0 );
thetaWheel += t;
CABasicAnimation * anim = [CABasicAnimation animationWithKeyPath:#"transform"];
anim.fromValue = [NSNumber numberWithDouble: thetaOld];
anim.toValue = [NSNumber numberWithDouble: thetaWheel];
anim.valueFunction = [CAValueFunction functionWithName: kCAValueFunctionRotateZ];
anim.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
anim.duration = 0.1f;
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
[self.wheelLayer addAnimation: anim forKey:#"transform"];
}
- (void) popOut
{
CABasicAnimation * anim = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
anim.fromValue = [NSNumber numberWithDouble: 1.0];
anim.toValue = [NSNumber numberWithDouble: 1.2];
anim.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
anim.duration = 0.25f;
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
[self.wheelLayer addAnimation: anim forKey:#"transform.scale"];
}
// doesnt get used yet
- (void) popBack
{
CABasicAnimation * anim = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
anim.fromValue = [NSNumber numberWithDouble: 1.2];
anim.toValue = [NSNumber numberWithDouble: 1.0];
anim.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
anim.duration = 0.1f;
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
[self.wheelLayer addAnimation: anim forKey:#"transform.scale"];
}
The last routine is not getting used at this time! So I can't see what is reducing the scale back to 1...
it looks like somehow the second animation is overwriting the first one...
how to do this properly?

I guess (have not tested that) that layer transform applied in animation for 'transform' keyPath overrides transformation you applied in your scaling animation.
For rotation try using animation with transform.rotation.z keypath instead (and you won't need to set valueFunction in that case)

Related

Change speed of "marching ants" effect after every 10 seconds

I'd like to change the Speed of my "Marching ants" effect after it has looped every 10 times. So it's looping the animation with a duration of 1, after the 10 loops it should change the duration to 0.95, after 10 more seconds to 0.9 and so on....
Do you have an idea how I could do this?
Here's the code for my current animation:
CAShapeLayer *lineLayer = [CAShapeLayer layer];
lineLayer.bounds = CGRectMake(0, 0, self.view.bounds.size.width, 20);
lineLayer.position = self.view.center;
lineLayer.strokeColor = [UIColor whiteColor].CGColor;
lineLayer.lineDashPattern = #[#100];
lineLayer.lineWidth = CGRectGetHeight(lineLayer.bounds);
UIBezierPath *linePath = [UIBezierPath bezierPath];
[linePath moveToPoint:CGPointMake(0, CGRectGetMidY(lineLayer.bounds))];
[linePath addLineToPoint:CGPointMake(CGRectGetMaxX(lineLayer.bounds), CGRectGetMidY(lineLayer.bounds))];
lineLayer.path = linePath.CGPath;
// [self.view.layer addSublayer:lineLayer];
NSNumber *totalDashLenght = [lineLayer.lineDashPattern valueForKeyPath:#"#sum.self"]; // KVC is awesome :)
CABasicAnimation *animatePhase = [CABasicAnimation animationWithKeyPath:#"lineDashPhase"];
animatePhase.byValue = totalDashLenght; // using byValue means that even if the layer has a shifted phase, it will shift on top of that.
animatePhase.duration = 0.5;
animatePhase.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animatePhase.repeatCount = 10;
// [lineLayer addAnimation:animatePhase forKey:#"marching ants"];
// Create the shape layer
shapeLayer = [CAShapeLayer layer];
CGRect shapeRect = CGRectMake(0.0f, 0.0f, 2200.0f, 2000.0f);
[shapeLayer setBounds:shapeRect];
[shapeLayer setPosition:CGPointMake(160.0f, 1350.0f)];
[shapeLayer setFillColor:[[UIColor clearColor] CGColor]];
[shapeLayer setStrokeColor:[[UIColor whiteColor] CGColor]];
[shapeLayer setLineWidth:20.0f];
[shapeLayer setLineJoin:kCALineJoinRound];
[shapeLayer setLineDashPattern:
[NSArray arrayWithObjects:[NSNumber numberWithInt:200],
[NSNumber numberWithInt:100],
nil]];
// Setup the path
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, shapeRect);
[shapeLayer setPath:path];
CGPathRelease(path);
// Set the layer's contents
//[shapeLayer setContents:(id)[[UIImage imageNamed:#"GEIST.jpg"] CGImage]];
[[[self view] layer] addSublayer:shapeLayer];
if ([shapeLayer animationForKey:#"linePhase"])
[shapeLayer removeAnimationForKey:#"linePhase"];
else {
CABasicAnimation *dashAnimation;
dashAnimation = [CABasicAnimation
animationWithKeyPath:#"lineDashPhase"];
[dashAnimation setFromValue:[NSNumber numberWithFloat:0.0f]];
[dashAnimation setToValue:[NSNumber numberWithFloat:300.0f]];
[dashAnimation setDuration:1];
[dashAnimation setRepeatCount:10];
[shapeLayer addAnimation:dashAnimation forKey:#"linePhase"];
Just set yourself up to detect the end of your animation, either with a delegate method or with a completion block on the transaction. When your animation completes its ten repetitions, you can schedule a new animation with a shorter duration.
(And remember being small, playing under the table and dreaming...)

NSWindow flip animation (easy and universal)

How to make flip animation for OS X application windows without complex coding?
Finally, I did it. I have created object that work with NSWindowController objects instead of NSWidows.
ALWindowFlipAnimator.h
#import <Foundation/Foundation.h>
//............................................................................................................
// Shorten macroes:
#define FLIPANIMATOR [ALWindowFlipAnimator sharedWindowFlipAnimator]
//............................................................................................................
// Window flip direction:
typedef NS_ENUM(NSUInteger, ALFlipDirection)
{
ALFlipDirectionLeft,
ALFlipDirectionRight,
ALFlipDirectionUp,
ALFlipDirectionDown
};
#interface ALWindowFlipAnimator : NSObject
+(ALWindowFlipAnimator *)sharedWindowFlipAnimator;
-(void)flipToWindowNibName:(NSString *)nibName direction:(ALFlipDirection)direction;
#end
ALWindowFlipAnimator.m
#import "ALWindowFlipAnimator.h"
#import <QuartzCore/QuartzCore.h>
#implementation ALWindowFlipAnimator
{
NSWindowController *_currentWindowController; // Current window controller
NSWindowController *_nextWindowController; // Next window controller to flip to
NSWindow *_animationWindow; // Window where flip animation plays
}
//============================================================================================================
// Initialize flip window controller
//============================================================================================================
-(id)init
{
self = [super init];
if (self)
{
_currentWindowController = nil;
_nextWindowController = nil;
_animationWindow = nil;
}
return self;
}
//============================================================================================================
// Create shared flip window manager
//============================================================================================================
+(ALWindowFlipAnimator *)sharedWindowFlipAnimator
{
static ALWindowFlipAnimator *wfa = nil;
if (!wfa) wfa = [[ALWindowFlipAnimator alloc] init];
return wfa;
}
//============================================================================================================
// Flip to window with selected NIB file name from the current one
//============================================================================================================
-(void)flipToWindowNibName:(NSString *)nibName direction:(ALFlipDirection)direction
{
if (!_currentWindowController || ![[_currentWindowController window] isVisible])
{
// No current window controller or window is closed
_currentWindowController = [[NSClassFromString(nibName) alloc] initWithWindowNibName:nibName];
[_currentWindowController showWindow:self];
}
else
{
if ([[_currentWindowController className] isEqualToString:nibName])
// Bring current window to front
[[_currentWindowController window] makeKeyAndOrderFront:self];
else
{
// Flip to new window
_nextWindowController = [[NSClassFromString(nibName) alloc] initWithWindowNibName:nibName];
[self flipToNextWindowControllerDirection:direction];
}
}
}
#pragma mark - Flip animation
#define DEF_DURATION 2.0 // Animation duration
#define DEF_SCALE 1.2 // Scaling factor for animation window (_animationWindow)
//============================================================================================================
// Start window flipping animation
//============================================================================================================
-(void)flipToNextWindowControllerDirection:(ALFlipDirection)direction
{
NSWindow *currentWindow = [_currentWindowController window];
NSWindow *nextWindow = [_nextWindowController window];
NSView *currentWindowView = [currentWindow.contentView superview];
NSView *nextWindowView = [nextWindow.contentView superview];
// Create window for animation
CGFloat maxWidth = MAX(currentWindow.frame.size.width, nextWindow.frame.size.width);
CGFloat maxHeight = MAX(currentWindow.frame.size.height, nextWindow.frame.size.height);
CGFloat xscale = DEF_SCALE * 2.0;
maxWidth += maxWidth * xscale;
maxHeight += maxHeight * xscale;
CGRect animationFrame = CGRectMake(NSMidX(currentWindow.frame) - (maxWidth / 2),
NSMidY(currentWindow.frame) - (maxHeight / 2),
maxWidth, maxHeight);
_animationWindow = [[NSWindow alloc] initWithContentRect:NSRectFromCGRect(animationFrame)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[_animationWindow setOpaque:NO];
[_animationWindow setHasShadow:NO];
[_animationWindow setBackgroundColor:[NSColor clearColor]];
[_animationWindow.contentView setWantsLayer:YES];
[_animationWindow setLevel:NSScreenSaverWindowLevel];
// Move next window closer to the current one
CGRect nextFrame = CGRectMake(NSMidX(currentWindow.frame) - (NSWidth(nextWindow.frame) / 2 ),
NSMaxY(currentWindow.frame) - NSHeight(nextWindow.frame),
NSWidth(nextWindow.frame), NSHeight(nextWindow.frame));
[nextWindow setFrame:NSRectFromCGRect(nextFrame) display:NO];
// Make snapshots of current and next windows
[CATransaction begin];
CALayer *currentWindowSnapshot = [self snapshotToImageLayerFromView:currentWindowView];
CALayer *nextWindowSnapshot = [self snapshotToImageLayerFromView:nextWindowView];
[CATransaction commit];
currentWindowSnapshot.frame = [self rect:currentWindowView.frame
fromView:currentWindowView
toView:[_animationWindow contentView]];
nextWindowSnapshot.frame = [self rect:nextWindowView.frame
fromView:nextWindowView
toView:[_animationWindow contentView]];
// Create 3D transform matrix to snapshots
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -(1.0 / 1500.0);
currentWindowSnapshot.transform = transform;
nextWindowSnapshot.transform = transform;
// Add snapshots to animation window
[CATransaction begin];
[[_animationWindow.contentView layer] addSublayer:currentWindowSnapshot];
[[_animationWindow.contentView layer] addSublayer:nextWindowSnapshot];
[CATransaction commit];
[_animationWindow makeKeyAndOrderFront:nil];
// Animation for snapshots
[CATransaction begin];
CAAnimation *currentSnapshotAnimation = [self animationWithDuration:(DEF_DURATION * 0.5) flip:YES direction:direction];
CAAnimation *nextSnapshotAnimation = [self animationWithDuration:(DEF_DURATION * 0.5) flip:NO direction:direction];
[CATransaction commit];
// Start animation
nextSnapshotAnimation.delegate = self;
[currentWindow orderOut:nil];
[CATransaction begin];
[currentWindowSnapshot addAnimation:currentSnapshotAnimation forKey:#"flipAnimation"];
[nextWindowSnapshot addAnimation:nextSnapshotAnimation forKey:#"flipAnimation"];
[CATransaction commit];
}
//============================================================================================================
// Convert rectangle from one view coordinates to another
//============================================================================================================
-(CGRect)rect:(NSRect)rect fromView:(NSView *)fromView toView:(NSView *)toView
{
rect = [fromView convertRect:rect toView:nil];
rect = [fromView.window convertRectToScreen:rect];
rect = [toView.window convertRectFromScreen:rect];
rect = [toView convertRect:rect fromView:nil];
return NSRectToCGRect(rect);
}
//============================================================================================================
// Get snapshot of selected view as layer with bitmap image
//============================================================================================================
-(CALayer *)snapshotToImageLayerFromView:(NSView*)view
{
// Make view snapshot
NSBitmapImageRep *snapshot = [view bitmapImageRepForCachingDisplayInRect:view.bounds];
[view cacheDisplayInRect:view.bounds toBitmapImageRep:snapshot];
// Convert snapshot to layer
CALayer *layer = [CALayer layer];
layer.contents = (id)snapshot.CGImage;
layer.doubleSided = NO;
// Add shadow of window to snapshot
[layer setShadowOpacity:0.5];
[layer setShadowOffset:CGSizeMake(0.0, -10.0)];
[layer setShadowRadius:15.0];
return layer;
}
//============================================================================================================
// Create animation
//============================================================================================================
-(CAAnimation *)animationWithDuration:(CGFloat)time flip:(BOOL)flip direction:(ALFlipDirection)direction
{
// Set flip direction
NSString *keyPath = #"transform.rotation.y";
if (direction == ALFlipDirectionUp || direction == ALFlipDirectionDown) keyPath = #"transform.rotation.x";
CABasicAnimation *flipAnimation = [CABasicAnimation animationWithKeyPath:keyPath];
CGFloat startValue = flip ? 0.0 : -M_PI;
CGFloat endValue = flip ? M_PI : 0.0;
if (direction == ALFlipDirectionLeft || direction == ALFlipDirectionUp)
{
startValue = flip ? 0.0 : M_PI;
endValue = flip ? -M_PI : 0.0;
}
flipAnimation.fromValue = [NSNumber numberWithDouble:startValue];
flipAnimation.toValue = [NSNumber numberWithDouble:endValue];
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.toValue = [NSNumber numberWithFloat:DEF_SCALE];
scaleAnimation.duration = time * 0.5;
scaleAnimation.autoreverses = YES;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:flipAnimation, scaleAnimation, nil];
animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animationGroup.duration = time;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion = NO;
return animationGroup;
}
//============================================================================================================
// Flip animation did finish
//============================================================================================================
-(void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
{
[[_nextWindowController window] makeKeyAndOrderFront:nil];
[_animationWindow orderOut:nil];
_animationWindow = nil;
_currentWindowController = _nextWindowController;
}
#end
How to use:
Create some new NSWindowController objects with NIBs in your project
Call [FLIPANIMATOR flipToWindowNibName:#"SecondWindowController" direction:ALFlipDirectionRight]; to flip to second window, or [FLIPANIMATOR flipToWindowNibName:#"FirstWindowController" direction:ALFlipDirectionLeft]; to return back
Link QuarzCore.framework to your project
That's all!

How to rotate a view that is already moving with core animation?

I use core animation (CAKeyframeAnimation) to move a view using a given path and at the same time to display the path (dotted line).
While animating the view along the given path i want it to face the direction it is going to.
In other words i want the view to rotate progressively while moving.
After some research i find out it may be possible to do it with CAKeyFrameAnimation using keytimes and values but no success. I have no idea on how to implement it.
As i am still new in IOS programming, i don't know if there is another (better?) way to do such kind of animation.
Here is the code i use:
- (CGMutablePathRef) getPathFromPoints:(NSMutableArray*)points {
CGMutablePathRef path = CGPathCreateMutable();
CGPoint p = [points[0] CGPointValue];
CGPathMoveToPoint(path, NULL, p.x, p.y);
for (int i = 1; i < points.count; ++i) {
p = [points[i] CGPointValue];
CGPathAddLineToPoint(path, NULL, p.x, p.y);
}
return path;
}
- (void)animateView:(UIView*)view
withPoints:(NSMutableArray*)points
withFillMode:(NSString*)fillMode
withDuration:(int)duration
withRepeatCount:(int)repeat
withSpeed:(int)speed
withDashed:(BOOL)dashed{
CGMutablePathRef path = [self getPathFromPoints:points];
if (dashed) {
CAShapeLayer* pathLayer = [CAShapeLayer layer];
pathLayer.frame = view.superview.layer.bounds;
pathLayer.bounds = view.superview.layer.bounds;
pathLayer.geometryFlipped = NO;
pathLayer.path = path;
pathLayer.strokeColor = [[UIColor blackColor] CGColor];
pathLayer.fillColor = nil;
pathLayer.lineWidth = 10.0f;
pathLayer.lineJoin = kCALineJoinBevel;
[pathLayer setLineDashPattern:[[NSArray alloc] initWithObjects:
[NSNumber numberWithInt:15],
[NSNumber numberWithInt:15],
nil]];
[view.superview.layer addSublayer:pathLayer];
CABasicAnimation *dottedAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
dottedAnimation.duration = duration;
dottedAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
dottedAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[pathLayer addAnimation:dottedAnimation forKey:#"strokeEnd"];
[view.superview bringSubviewToFront:view];
}
CAKeyframeAnimation* pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = fillMode;
pathAnimation.duration = duration;
pathAnimation.repeatCount = repeat;
pathAnimation.speed = speed;
pathAnimation.path = path;
[view.layer addAnimation:pathAnimation forKey:_myAnimationKey];
CGPoint p = [[points lastObject] CGPointValue];
view.layer.position = CGPointMake(p.x, p.y);
}
Thank you in advance for you help,
Have a look at CAKeyframeAnimation's rotationMode property. That should accomplish exactly what you are hoping to do.
Add this line to the -animateView: method where the properties for the *pathAnimation CAKeyframeAnimation instance are being set:
pathAnimation.rotationMode = kCAAnimationRotateAuto;
There's also another setting value, kCAAnimationRotateAutoReverse, that allows the animated object to maintain an anti-parallel orientation with respect to the path tangent.
Link to Apple docs: CAKeyframeAnimation

UIBezierPath pulse animation

I'm drawing a UIBezierPath on a UIScrollView I have made an animation that draws the path from start to end point but this is not the animation that I want.
UIBezierPath *linePath = [UIBezierPath bezierPath];
[linePath moveToPoint:startPoints];
[linePath addLineToPoint:endPoints;
//shape layer for the line
CAShapeLayer *line = [CAShapeLayer layer];
line.path = [linePath CGPath];
// line.fillColor = [[UIColor blackColor] CGColor];
line.strokeColor = [[colors objectAtIndex:i] CGColor];
line.lineWidth = 5;
// line.contents = (id)[[UIImage imageNamed:#"Mask.png"] CGImage];
// line.contentsGravity = kCAGravityCenter;
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
pathAnimation.duration = 3.0;
pathAnimation.fromValue = #(0.0f);
pathAnimation.toValue = #(1.0f);
pathAnimation.repeatCount = HUGE_VAL;
[line addAnimation:pathAnimation forKey:#"strokeEnd"];
I have tried adding a contents to the shape layer but I'm bad at animations. The effect I want to achieve is the same animation as "slide to unlock" has, or a path that pulses.
I've tried to do the same thing as the answer from slide-to-unlock but can't seem to manage
I ended up dooing this:
UIBezierPath *linePath = [UIBezierPath bezierPath];
[linePath moveToPoint:startPoints];
[linePath addLineToPoint:endPoints];
//gradient layer for the line
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(0, 0, 150.0, 1.0);
gradient.cornerRadius = 5.0f;
gradient.startPoint = CGPointMake(0.0, 0.5);
gradient.endPoint = CGPointMake(1.0, 0.5);
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor clearColor] CGColor],(id)[[UIColor whiteColor] CGColor],(id)[[UIColor blueColor] CGColor],(id)[[UIColor clearColor] CGColor], nil];
[scrollViewContent.layer addSublayer:gradient];
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:#"position"];
anim.path = [linePath CGPath];
anim.rotationMode = kCAAnimationRotateAuto;
anim.repeatCount = 0;
anim.duration = 1;
[gradient addAnimation:anim forKey:#"gradient"];

Inaccurate rotation with CABasicAnimation... doesn't match the correct angle

I am developing a maps application. I draw an animated line in the map and then use an image (a ruler image) which should be draw just over the line. To draw the line I use a CABasicAnimation with path:
-(void)lineaAnimation {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"path"];
animation.duration = animDuration;
animation.delegate=self;
animation.repeatCount = 0;
animation.autoreverses = NO;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.fromValue = (id)inip;
animation.toValue = (id)finp;
animation.fillMode=kCAFillModeForwards;
animation.removedOnCompletion=NO;
[shapeLayer addAnimation:animation forKey:#"animatePath"];
}
-(void)linea:(CGPoint)origen to:(CGPoint)destino animado:(BOOL)anim duracion:(float)durac inicio:(float)delay {
inip = CGPathCreateMutable();
finp = CGPathCreateMutable();
CGPathMoveToPoint(inip, nil, origen.x, origen.y);
CGPathAddLineToPoint(inip, nil, origen.x, origen.y);
CGPathCloseSubpath(inip);
CGPathMoveToPoint(finp, nil, origen.x, origen.y);
CGPathAddLineToPoint(finp, nil, destino.x, destino.y);
CGPathCloseSubpath(finp);
rootLayer = [CALayer layer];
rootLayer.frame = fondo.bounds;
[fondo.layer addSublayer:rootLayer];
shapeLayer = [CAShapeLayer layer];
shapeLayer.path = inip;
UIColor *fillColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.7];
shapeLayer.fillColor = fillColor.CGColor;
UIColor *strokeColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.7];
shapeLayer.strokeColor = strokeColor.CGColor;
shapeLayer.lineWidth = 5.0;
shapeLayer.fillRule = kCAFillRuleEvenOdd;
[morrallaLayer addObject:shapeLayer];
[rootLayer addSublayer:shapeLayer];
animDuration=durac;
[self performSelector:#selector(lineaAnimation) withObject:nil afterDelay:delay];
}
Then I try to move the center of the rule to the point and rotate the ruler image using this code:
delta=acos((destino.y-origen.y)/(destino.x-origen.x));
giroIni=0.0;
giroFin=delta;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
animation.fromValue= [NSNumber numberWithFloat:giroIni];
animation.toValue= [NSNumber numberWithFloat:giroFin];
animation.delegate = self;
animation.repeatCount = 0;
animation.autoreverses = NO;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.duration = animDuration;
animation.fillMode=kCAFillModeForwards;
animation.removedOnCompletion=NO;
[ruleL addAnimation:animation forKey:#"giroAngulo"];
The problem is that the ruler borderline doesn't match the line draw, there are around a degree of difference depending on the final orientation... why?
Thanks a lot!
Ooooops... sorry for your time :(
I found the problem and.. as usual the error is not in the stars but in ourselves
I use the acos function when OBVIOUSLY I should use atan

Resources