0

下の投稿の写真のようなカルーセルビューを開発しました

3Dカルーセルからアニメーション化されたビューの位置を計算するにはどうすればよいですか?

#pragma mark -

#pragma mark - VIEW LIFE CYCLE

- (void)viewDidLoad
{
    [super viewDidLoad];

    // VIEW FRAME
    CGRect Frame = CGRectMake(-40, -40, 80, 80);

    // CREATE 6 VIEWS
    _CarouselView = [[NSMutableArray alloc] initWithCapacity:6];

    int c = 5;

    while(c--)
    {
        UIView *View = [[UIView alloc] initWithFrame:Frame];
        View.backgroundColor = [UIColor colorWithRed:(c&4) ? 1.0 : 0.0 green:(c&2) ? 1.0 : 0.0 blue:(c&1) ? 1.0 : 0.0 alpha:1.0];

        [_CarouselView addObject:View];
        [self.view addSubview:View];
    }

    _CurrentAngle = _LastAngle = 0.0f;

    [self setCarouselAngle:_CurrentAngle];
}

- (void)viewDidUnload
{
}

#pragma mark -
#pragma mark - VIEW TOUCH GESTURE

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if(!_TrackingTouch)
    {
        _TrackingTouch = [touches anyObject];

        [_AnimationTimer invalidate];
        _AnimationTimer = nil;
        _LastAngle      = _CurrentAngle;
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    if([touches containsObject:_TrackingTouch])
    {
        // USE MOVEMENT TO DEVICE HOW MUCH TO ROTATE THE CAROUSEL
        CGPoint LocationNow  = [_TrackingTouch locationInView:self.view];
        CGPoint LocationThen = [_TrackingTouch previousLocationInView:self.view];

        _LastAngle     = _CurrentAngle;
        _CurrentAngle += (LocationNow.x - LocationThen.x) * 180.0f / self.view.bounds.size.width;
        // the 180.0f / self.view.bounds.size.width just says "let a full width of my view
        // be a 180 degree rotation"

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

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if([touches containsObject:_TrackingTouch])
    {
        _TrackingTouch = nil;

        _AnimationTimer = [NSTimer scheduledTimerWithTimeInterval:0.04 target:self selector:@selector(animateAngle) userInfo:nil repeats:YES];
    }
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesEnded:touches withEvent:event];
}

#pragma mark -
#pragma mark - CAROUSEL ACTIONS

- (void)setCarouselAngle:(float)Angle
{
    // ANGLE TO ADD AFTER EACH ELEM
    _AngleToAdd = 360.0f / [_CarouselView count];

    // APPLY TO ALL VIEWS
    for(UIView *View in _CarouselView)
    {
        float AngleInRadians = Angle * M_PI / 180.0f;

        // GET LOCATION
        float x = (self.view.bounds.size.width * 0.5f) + 100.0f * sinf(AngleInRadians);
        float y = ((self.view.bounds.size.height-200) * 0.5f) + 90.0f * cosf(AngleInRadians);

        // ADJUST SCALE BETWEEN 0.75 0.25
        float Scale = 0.75f + 0.25f * (cosf(AngleInRadians) + 1.0);

        // APPLY TRANSFORMATION
        View.transform = CGAffineTransformScale(CGAffineTransformMakeTranslation(x, y), Scale, Scale);

        // TWEAK ALPHA
        View.alpha = 0.1f + 0.5f * (cosf(AngleInRadians) + 1.0);

        // SETTING Z POSITION
        View.layer.zPosition = Scale;

        // GET THE NEXT ANGLE
        Angle += _AngleToAdd;
    }
}

- (void)animateAngle
{
    float AngleNow  = _CurrentAngle;
    _CurrentAngle  += (_CurrentAngle - _LastAngle) * 0.97f;
    _LastAngle      = AngleNow;

    // PUSH THE NEW ANGLE
    [self setCarouselAngle:_CurrentAngle];

    if(fabsf(_LastAngle - _CurrentAngle) < 0.001)
    {

        [_AnimationTimer invalidate];
        _AnimationTimer = nil;
    }
}

すべて正常に動作しますが、ページネーションコードを配置する場所を理解するのに苦労しています

4

1 に答える 1

1

このコードがお役に立てば幸いです。ViewControllerを作成してから、コードをコピーして貼り付けるだけです。

//  CarruselViewController.m
//
//  Created by Rosendo Castillo Perez on 2/25/14.
//  Copyright (c) 2014 Fundtech. All rights reserved.
//

#import "CarruselViewController.h"

@interface CarruselViewController ()
{
    NSMutableArray *_CarouselView;
    CGFloat _CurrentAngle,_LastAngle, _AngleToAdd;
    UITouch * _TrackingTouch;
    NSTimer * _AnimationTimer;
}
@end

@implementation CarruselViewController

#pragma mark -

#pragma mark - VIEW LIFE CYCLE

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:(BOOL)animated];

    // VIEW FRAME
    CGRect Frame = CGRectMake(-40, -40, 80, 40);

    // CREATE 6 VIEWS
    _CarouselView = [[NSMutableArray alloc] initWithCapacity:6];

    int c = 0;

    while(c < 5)
    {

        UILabel *View = [[UILabel alloc] initWithFrame:Frame];
        View.backgroundColor = [UIColor colorWithRed:(c&4) ? 1.0 : 0.0 green:(c&2) ? 1.0 : 0.0 blue:(c&1) ? 1.0 : 0.0 alpha:1.0];
        [View setTextAlignment:NSTextAlignmentCenter];
        [View setTextColor:[UIColor whiteColor]];
        [View setFont:[UIFont boldSystemFontOfSize:14]];
        [View setText:[NSString stringWithFormat:@"%d",c]];

        [_CarouselView addObject:View];
        [self.view addSubview:View];
         c++;
    }

    _CurrentAngle = _LastAngle = 0.0f;

    [self setCarouselAngle:_CurrentAngle];
}

#pragma mark -
#pragma mark - VIEW TOUCH GESTURE

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{


    if(!_TrackingTouch)
    {
        _TrackingTouch = [touches anyObject];

        [_AnimationTimer invalidate];
        _AnimationTimer = nil;
        _LastAngle      = _CurrentAngle;
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    if([touches containsObject:_TrackingTouch])
    {
        // USE MOVEMENT TO DEVICE HOW MUCH TO ROTATE THE CAROUSEL
        CGPoint LocationNow  = [_TrackingTouch locationInView:self.view];
        CGPoint LocationThen = [_TrackingTouch previousLocationInView:self.view];

        _LastAngle     = _CurrentAngle;
        _CurrentAngle += (LocationNow.x - LocationThen.x) * 180.0f / self.view.bounds.size.width;
        // the 180.0f / self.view.bounds.size.width just says "let a full width of my view
        // be a 180 degree rotation"

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

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if([touches containsObject:_TrackingTouch])
    {
        _TrackingTouch = nil;

        _AnimationTimer = [NSTimer scheduledTimerWithTimeInterval:0.04 target:self selector:@selector(animateAngle) userInfo:nil repeats:YES];
    }
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesEnded:touches withEvent:event];
}

#pragma mark -
#pragma mark - CAROUSEL ACTIONS

- (void)setCarouselAngle:(float)Angle
{
    // ANGLE TO ADD AFTER EACH ELEM
    _AngleToAdd = 360.0f / [_CarouselView count];

    // APPLY TO ALL VIEWS
    for(UIView *View in _CarouselView)
    {
        float AngleInRadians = Angle * M_PI / 180.0f;

        // GET LOCATION
        float x = (self.view.bounds.size.width * 0.5f) + 100.0f * sinf(AngleInRadians);
        float y = ((self.view.bounds.size.height-200) * 0.5f) + 40.0f * cosf(AngleInRadians);

        // ADJUST SCALE BETWEEN 0.75 0.25
        float Scale = 0.75f + 0.25f * (cosf(AngleInRadians) + 1.0);

        // APPLY TRANSFORMATION
        View.transform = CGAffineTransformScale(CGAffineTransformMakeTranslation(x, y), Scale, Scale);

        // TWEAK ALPHA
        View.alpha = 0.1f + 0.5f * (cosf(AngleInRadians) + 1.0);

        // SETTING Z POSITION
        View.layer.zPosition = Scale;

        // GET THE NEXT ANGLE
        Angle += _AngleToAdd;
    }
}

- (void)animateAngle
{
    float AngleNow  = _CurrentAngle;
    _CurrentAngle  += (_CurrentAngle - _LastAngle) * 0.97f;
    _LastAngle      = AngleNow;

    // PUSH THE NEW ANGLE
    [self setCarouselAngle:_CurrentAngle];

    if(fabsf(_LastAngle - _CurrentAngle) < 0.1)
    {
        _CurrentAngle = ((int)_CurrentAngle % 360);

        if (_CurrentAngle < 0.0)
        {
            _CurrentAngle += 360.0;
        }

        [self setCarouselAngle:_CurrentAngle];

        int currentAngle = (int) _CurrentAngle;
        int angleToAdd = (int) _AngleToAdd;

        int residuo = currentAngle % angleToAdd;

        if (residuo != 0)
        {
            forward = (residuo > (angleToAdd / 2));
            [_AnimationTimer invalidate];
            _AnimationTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(centerAngle) userInfo:nil repeats:YES];
        }
        else
        {
            NSLog(@"angle: %d - index: %d",currentAngle,([_CarouselView count] - ((currentAngle / angleToAdd) % [_CarouselView count])));
        }

    }
}

BOOL forward = TRUE;

- (void)centerAngle
{
    _CurrentAngle += (forward?1.0:-1.0);
    [self setCarouselAngle:_CurrentAngle];

    int currentAngle = (int) _CurrentAngle;
    int angleToAdd = (int) _AngleToAdd;

    int residuo = currentAngle % angleToAdd;

    if (residuo == 0)
    {
        _LastAngle = _CurrentAngle = currentAngle;
        [self setCarouselAngle:_CurrentAngle];
        [_AnimationTimer invalidate];
        _AnimationTimer = nil;
        NSLog(@"angle: %d - index: %d",currentAngle,([_CarouselView count] - ((currentAngle / angleToAdd) % [_CarouselView count])));
    }
}

@end
于 2014-02-25T20:01:24.593 に答える