Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 672513
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 14, 20262026-05-14T00:29:36+00:00 2026-05-14T00:29:36+00:00

I’m trying to implement a flip animation to be used in board game like

  • 0

I’m trying to implement a flip animation to be used in board game like iPhone-application. The animation is supposed to look like a game piece that rotates and changes to the color of its back (kind of like an Reversi piece). I’ve managed to create an animation that flips the piece around its orthogonal axis, but when I try to flip it around a diagonal axis by changing the rotation around the z-axis the actual image also gets rotated (not surprisingly). Instead I would like to rotate the image “as is” around a diagonal axis.

I have tried to change layer.sublayerTransform but with no success.

Here is my current implementation. It works by doing a trick to resolve the issue of getting a mirrored image at the end of the animation. The solution is to not actually rotate the layer 180 degrees, instead it rotates it 90 degrees, changes image and then rotates it back.

Final version: Based on Lorenzos suggestion to create a discrete keyed animation and calculate the transformation matrix for each frame. This version instead tries to estimate number of “guiding” frames needed based on the layer size and then uses a linear keyed animation. This version rotates with a arbitrary angle so to rotate around diagonal line use a 45 degree angle.

Example usage:

[someclass flipLayer:layer image:image angle:M_PI/4]

Implementation:

- (void)animationDidStop:(CAAnimationGroup *)animation
                finished:(BOOL)finished {
  CALayer *layer = [animation valueForKey:@"layer"];

  if([[animation valueForKey:@"name"] isEqual:@"fadeAnimation"]) {
    /* code for another animation */
  } else if([[animation valueForKey:@"name"] isEqual:@"flipAnimation"]) {
    layer.contents = [animation valueForKey:@"image"];
  }

  [layer removeAllAnimations];
}

- (void)flipLayer:(CALayer *)layer
            image:(CGImageRef)image
            angle:(float)angle {
  const float duration = 0.5f;

  CAKeyframeAnimation *rotate = [CAKeyframeAnimation
                                 animationWithKeyPath:@"transform"];
  NSMutableArray *values = [[[NSMutableArray alloc] init] autorelease];
  NSMutableArray *times = [[[NSMutableArray alloc] init] autorelease];
  /* bigger layers need more "guiding" values */
  int frames = MAX(layer.bounds.size.width, layer.bounds.size.height) / 2;
  int i;
  for (i = 0; i < frames; i++) {
    /* create a scale value going from 1.0 to 0.1 to 1.0 */
    float scale = MAX(fabs((float)(frames-i*2)/(frames - 1)), 0.1);

    CGAffineTransform t1, t2, t3;
    t1 = CGAffineTransformMakeRotation(angle);
    t2 = CGAffineTransformScale(t1, scale, 1.0f);
    t3 = CGAffineTransformRotate(t2, -angle);
    CATransform3D trans = CATransform3DMakeAffineTransform(t3);

    [values addObject:[NSValue valueWithCATransform3D:trans]];
    [times addObject:[NSNumber numberWithFloat:(float)i/(frames - 1)]];
  }
  rotate.values = values;
  rotate.keyTimes = times;
  rotate.duration = duration;
  rotate.calculationMode = kCAAnimationLinear;

  CAKeyframeAnimation *replace = [CAKeyframeAnimation
                                  animationWithKeyPath:@"contents"];
  replace.duration = duration / 2;
  replace.beginTime = duration / 2;
  replace.values = [NSArray arrayWithObjects:(id)image, nil];
  replace.keyTimes = [NSArray arrayWithObjects:
                      [NSNumber numberWithDouble:0.0f], nil];
  replace.calculationMode = kCAAnimationDiscrete;

  CAAnimationGroup *group = [CAAnimationGroup animation];
  group.duration = duration;
  group.timingFunction = [CAMediaTimingFunction
                          functionWithName:kCAMediaTimingFunctionLinear];
  group.animations = [NSArray arrayWithObjects:rotate, replace, nil];
  group.delegate = self;
  group.removedOnCompletion = NO;
  group.fillMode = kCAFillModeForwards;
  [group setValue:@"flipAnimation" forKey:@"name"];
  [group setValue:layer forKey:@"layer"];
  [group setValue:(id)image forKey:@"image"];

  [layer addAnimation:group forKey:nil];
}

Original code:

+ (void)flipLayer:(CALayer *)layer
          toImage:(CGImageRef)image
        withAngle:(double)angle {
  const float duration = 0.5f;

  CAKeyframeAnimation *diag = [CAKeyframeAnimation
                               animationWithKeyPath:@"transform.rotation.z"];
  diag.duration = duration;
  diag.values = [NSArray arrayWithObjects:
                 [NSNumber numberWithDouble:angle],
                 [NSNumber numberWithDouble:0.0f],
                 nil];
  diag.keyTimes = [NSArray arrayWithObjects:
                   [NSNumber numberWithDouble:0.0f],
                   [NSNumber numberWithDouble:1.0f],
                   nil];
  diag.calculationMode = kCAAnimationDiscrete;

  CAKeyframeAnimation *flip = [CAKeyframeAnimation
                               animationWithKeyPath:@"transform.rotation.y"];
  flip.duration = duration;
  flip.values = [NSArray arrayWithObjects:
                 [NSNumber numberWithDouble:0.0f],
                 [NSNumber numberWithDouble:M_PI / 2],
                 [NSNumber numberWithDouble:0.0f],
                 nil];
  flip.keyTimes = [NSArray arrayWithObjects:
                   [NSNumber numberWithDouble:0.0f],
                   [NSNumber numberWithDouble:0.5f],
                   [NSNumber numberWithDouble:1.0f],
                   nil];
  flip.calculationMode = kCAAnimationLinear;

  CAKeyframeAnimation *replace = [CAKeyframeAnimation
                                  animationWithKeyPath:@"contents"];
  replace.duration = duration / 2;
  replace.beginTime = duration / 2;
  replace.values = [NSArray arrayWithObjects:(id)image, nil];
  replace.keyTimes = [NSArray arrayWithObjects:
                      [NSNumber numberWithDouble:0.0f], nil];
  replace.calculationMode = kCAAnimationDiscrete;

  CAAnimationGroup *group = [CAAnimationGroup animation];
  group.removedOnCompletion = NO;
  group.duration = duration;
  group.timingFunction = [CAMediaTimingFunction
                          functionWithName:kCAMediaTimingFunctionLinear];
  group.animations = [NSArray arrayWithObjects:diag, flip, replace, nil];
  group.fillMode = kCAFillModeForwards;

  [layer addAnimation:group forKey:nil];
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-14T00:29:36+00:00Added an answer on May 14, 2026 at 12:29 am

    you can fake it this way: create an affine transform that collapse the layer along it’s diagonal:

    A-----B           B
    |     |          /
    |     |   ->   A&D
    |     |        /
    C-----D       C
    

    change the image, and trasform the CALayer back in another animation.
    This will create the illusion of the layer rotating around its diagonal.

    the matrix for that should be if I remember math correctly:

    0.5 0.5 0
    0.5 0.5 0
    0   0   1
    

    Update:
    ok, CA doen’t really likes to use degenerate transforms, but you can approximate it this way:

    CGAffineTransform t1 = CGAffineTransformMakeRotation(M_PI/4.0f);
    CGAffineTransform t2 = CGAffineTransformScale(t1, 0.001f, 1.0f);
    CGAffineTransform t3 = CGAffineTransformRotate(t2,-M_PI/4.0f);  
    

    in my tests on the simulator there still was a problem because the rotations happens faster than te translation so with a solid black square the effect was a bit weird. I suppose that if you have a centered sprite with transparent area around it the effect will be close to what expected. You can then tweak the value of the t3 matrix to see if you get a more appealing result.

    after more research, it appears that one should animate it’s own transition via keyframes to obtaim the maximum control of the transition itself. say you were to display this animation in a second, you should make ten matrix to be shown at each tenth of a second withouot interpolation using kCAAnimationDiscrete; those matrix can be generated via the code below:

    CGAffineTransform t1 = CGAffineTransformMakeRotation(M_PI/4.0f);
    CGAffineTransform t2 = CGAffineTransformScale(t1, animationStepValue, 1.0f);
    CGAffineTransform t3 = CGAffineTransformRotate(t2,-M_PI/4.0f);  
    

    where animationStepValue for ech of the keyFrame is taken from this progression:

    {1 0.7 0.5 0.3 0.1 0.3 0.5 0.7 1}
    

    that is: you’re generating ten different transformation matrix (actually 9), pushing them as keyframes to be shown at each tenth of a second, and then using the “don’t interpolate” parameter. you can tweak the animation number for balancing smoothness and performance*

    *sorry for possible errors, this last part was written without a spellchecker.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I'm trying to decode HTML entries from here NYTimes.com and I cannot figure out
I am trying to understand how to use SyndicationItem to display feed which is
Basically, what I'm trying to create is a page of div tags, each has
link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I am trying to loop through a bunch of documents I have to put
I have some data like this: 1 2 3 4 5 9 2 6
I'm new to using the Perl treebuilder module for HTML parsing and can't figure
Seemingly simple, but I cannot find anything relevant on the web. What is the

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.