Search code examples
iphoneobjective-cioscarouselcgaffinetransform

How do I calculate the position of a view animated from a 3-D carousel?


I have developed a psuedo 3D carousel for the iPhone that looks pretty much like the image below: enter image description here

I basically create an array of UIViews and then register for the touch events:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // if we're not already tracking a touch then...
    if(!trackingTouch)
    {
        // ... track any of the new touches, we don't care which ...
        trackingTouch = [touches anyObject];
    }
}

While the movement is still being registered I do the following:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // if our touch moved then...
    if([touches containsObject:trackingTouch])
    {
        // use the movement of the touch to decide
        // how much to rotate the carousel
        CGPoint locationNow = [trackingTouch locationInView:self];
        CGPoint locationThen = [trackingTouch previousLocationInView:self];

        lastAngle = currentAngle;
        currentAngle += (locationNow.x - locationThen.x) * 180.0f / self.bounds.size.width;

        // and update the view positions
        [self setCarouselAngle:currentAngle];
    }
}

I then call when the touches end:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // if our touch ended then...
    if([touches containsObject:trackingTouch])
    {
        // make sure we're no longer tracking it
        trackingTouch = nil;

        // and kick off the inertial animation
        animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(animateAngle) userInfo:nil repeats:YES];
    }
}

The animageAngle method basically then calls another method with effectively divides 360 degrees by the number of views in the array and use the cosine and sine functions to generate the x and y coordinates.

The above all works good however, I am having difficulty comprehending the maths required to complete the following:

  1. Click on a view out of the main focus i.e. not at the front e.g the purple view in the image
  2. Rotate the purple view into focus i.e. to the front
  3. Load a new view controller once the rotation has complete

I understand that I have to calculate the angle between the view in its current position and the planned destination to make the rotation but I can not for the life of me figure it out.

Apologies for the prior confusion - I have been looking at this problem for sooooo long that I am starting to lose the plot.

Thanks


Solution

  • Finally....I managed to crack it.

    I was acting incredibly stupid and was not thinking logically. I basically re-ran a NSTimer calling a method that run the following calculation on the currentAngle property (in psuedo code):

    CGFloat currentLocation;
    CGFloat nextLocation;
    CGFloat destinationLocation;
    
    currentLocation = viewImInterestedIn.frame.origin.x;
    nextLocation = currentLocation - 1; //or + 1 if the selected view is to the left of centre
    
    destinationLocation = 115.0f //set this to a default value
    currentAngle += (currentLocation - nextLocation ) * 180.0f / self.bounds.size.width;
    
    // and update the view positions
    [self setCarouselAngle:currentAngle];
    

    Et voila!

    Remarkably simple - I have to learn to just take a step back sometimes and come back to a problem with a clear head.

    Thanks all