iOS版大转盘

iOS版大转盘

使用iOS自带的 CABasicAnimation 动画简单实现

一、核心代码
    // 旋转动画
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    // 开始位置
    [anim setFromValue:[NSNumber numberWithFloat:0]];
    // 结束
    [anim setToValue:[NSNumber numberWithFloat:M_PI * 2.97]];
    anim.duration = 5.0;
    // 动画结束不要回到开始位置
    anim.removedOnCompletion = NO;
    anim.fillMode = kCAFillModeForwards;
    [anim setDelegate:self];
    // 模式:先加速后减速
    [anim setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [imageView.layer addAnimation:anim forKey:@"rotation"];

旋转的时候,M_PI 为半圈,M_PI * 2 为一圈;
转盘等比平分,比如 items = 7;
从服务器得到停止位置,比如 resultItem = 3;
算出停止的角度为 orign = resultItem / items * 2 * M_PI;

核心就酱紫,在此基础上扩展下

二、扩展

.h

//
//  ViewController.h
//  demo
//
//  Created by zhangwb on 15/7/22.
//  Copyright (c) 2015年 lxmy. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

/** 旋转的位置 */
@property (nonatomic, strong) UISegmentedControl *segmentedItem;
/** 旋转的方向 */
@property (nonatomic, strong) UISegmentedControl *segmentedDirection;
/** 提示文本 */
@property (nonatomic, strong) UILabel *lblResult;
/** 底盘 */
@property (nonatomic, strong) UIImageView *imgRound;
/** 指针 */
@property (nonatomic, strong) UIButton *btnIndex;

@end

.m

//
//  ViewController.m
//  demo
//
//  Created by zhangwb on 15/7/22.
//  Copyright (c) 2015年 lxmy. All rights reserved.
//
//  大转盘的例子
//

#import "ViewController.h"
#import "Masonry.h"

const static CGFloat ANIM_TIME = 5.0; // 动画时间
const static CGFloat ROTATION_EXTEND = 20; // 旋转圈数延长 // 2 * M_PI = 1圈
const static NSInteger ITEM_COUNT = 14; // 转盘等比分割

@interface ViewController () {
    UIAlertView *alert;

    Boolean isCW; // 是否顺时针
    float random; // 位置,demo中从0开始
    float orign; // 角度
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self addView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

/** 添加控件 */
- (void) addView {
    if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
        self.edgesForExtendedLayout = UIRectEdgeNone;
    }

    self.title = @"大转盘";

    NSArray *arrayItem = [[NSArray alloc]initWithObjects:@"指针旋转", @"底盘旋转",nil];
    _segmentedItem = [[UISegmentedControl alloc]initWithItems:arrayItem];
    _segmentedItem.selectedSegmentIndex = 0;
    [_segmentedItem addTarget:self action:@selector(segmentedValueChanged) forControlEvents:UIControlEventValueChanged];
    _segmentedItem.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:_segmentedItem];

    NSArray *arrayDirection = [[NSArray alloc]initWithObjects:@"逆时针", @"顺时针", nil];
    _segmentedDirection = [[UISegmentedControl alloc]initWithItems:arrayDirection];
    _segmentedDirection.selectedSegmentIndex = 0;
    [_segmentedDirection addTarget:self action:@selector(segmentedDirectionValueChanged) forControlEvents:UIControlEventValueChanged];
    _segmentedDirection.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:_segmentedDirection];

    _lblResult = [UILabel new];
    _lblResult.textAlignment = NSTextAlignmentCenter;
    _lblResult.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:_lblResult];

    _imgRound = [UIImageView new];
    _imgRound.image = [UIImage imageNamed:@"round"];
    _imgRound.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:_imgRound];

    _btnIndex = [UIButton buttonWithType:UIButtonTypeCustom];
    [_btnIndex setImage:[UIImage imageNamed:@"start"] forState:UIControlStateNormal];
    [_btnIndex addTarget:self action:@selector(btnIndexClick) forControlEvents:UIControlEventTouchUpInside];
    _btnIndex.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:_btnIndex];

    int padding = 10;

    [_segmentedItem mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).offset(padding * 5);
        make.centerX.equalTo(self.view.mas_centerX);
    }];

    [_segmentedDirection mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_segmentedItem.mas_bottom).offset(padding);
        make.centerX.equalTo(self.view.mas_centerX);
    }];

    [_lblResult mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_segmentedDirection.mas_bottom).offset(padding);
        make.centerX.equalTo(self.view.mas_centerX);
        make.height.mas_equalTo(25);
    }];

    [_imgRound mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_lblResult.mas_bottom).offset(padding * 2);
        make.centerX.equalTo(self.view.mas_centerX);
    }];

    [_btnIndex mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(_imgRound);
    }];
}

/** 改变选择位置 */
- (void) segmentedValueChanged {
    orign = 0.0;
    _lblResult.text = @"";

    [_btnIndex.imageView.layer removeAllAnimations];
    [_imgRound.layer removeAllAnimations];

    _btnIndex.imageView.transform = CGAffineTransformMakeRotation(0);
    _imgRound.transform = CGAffineTransformMakeRotation(0);
}

/** 改变选择方向 */
- (void) segmentedDirectionValueChanged {
    isCW = _segmentedDirection.selectedSegmentIndex == 1;
    [self segmentedValueChanged];
}

/** 点击事件 */
- (void) btnIndexClick {
    _btnIndex.userInteractionEnabled = NO;

    [self getResult];

}

/** 模拟从服务器请求结果 */
- (void) getResult {
    // 产生随机数,作为停止项
    // 这里从0开始 0-ITEM_COUNT-1
    random = (arc4random() % ITEM_COUNT);

    _lblResult.text = [NSString stringWithFormat:@"停止项=%.0lf", random];

    if (_segmentedItem.selectedSegmentIndex == 0) {
        [self beginIndexRotate];

    } else {
        [self beginRoundRotate];
    }
}

/** 开始旋转-指针 */
- (void) beginIndexRotate {
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    if (isCW) {
        [anim setFromValue:[NSNumber numberWithFloat:M_PI * orign]];
        orign = random / ITEM_COUNT * 2;
        [anim setToValue:[NSNumber numberWithFloat:M_PI * (ROTATION_EXTEND + orign)]];

    } else {
        [anim setFromValue:[NSNumber numberWithFloat:-M_PI * orign]];
        orign = 2 - random / ITEM_COUNT * 2;
        [anim setToValue:[NSNumber numberWithFloat:-M_PI * (ROTATION_EXTEND + orign)]];

    }
    anim.duration = ANIM_TIME;
    anim.removedOnCompletion = NO;
    anim.fillMode = kCAFillModeForwards;
    [anim setDelegate:self];
    [anim setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

    [_btnIndex.imageView.layer addAnimation:anim forKey:@"rotation"];
}

/** 开始旋转-底盘 */
- (void) beginRoundRotate {
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    if (isCW) {
        [anim setFromValue:[NSNumber numberWithFloat:M_PI * orign]];
        orign = 2 - random / ITEM_COUNT * 2;
        [anim setToValue:[NSNumber numberWithFloat:M_PI * (ROTATION_EXTEND + orign)]];

    } else {
        [anim setFromValue:[NSNumber numberWithFloat:-M_PI * orign]];
        orign = random / ITEM_COUNT * 2;
        [anim setToValue:[NSNumber numberWithFloat:-M_PI * (ROTATION_EXTEND + orign)]];

    }
    anim.duration = ANIM_TIME;
    anim.removedOnCompletion = NO;
    anim.fillMode = kCAFillModeForwards;
    [anim setDelegate:self];
    [anim setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

    [_imgRound.layer addAnimation:anim forKey:@"rotation"];
}

/** 动画开始 */
- (void)animationDidStart:(CAAnimation *)anim {
    _btnIndex.userInteractionEnabled = NO;
    _segmentedItem.userInteractionEnabled = NO;
    _segmentedDirection.userInteractionEnabled = NO;
}

/** 动画结束 */
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    _btnIndex.userInteractionEnabled = YES;
    _segmentedItem.userInteractionEnabled = YES;
    _segmentedDirection.userInteractionEnabled = YES;

    if (!alert) {
        alert = [[UIAlertView alloc]initWithTitle:nil
                                          message:@""
                                         delegate:nil
                                cancelButtonTitle:@"OK"
                                otherButtonTitles:nil, nil];
    }

    alert.message = [NSString stringWithFormat:@"你抽中%.0lf", random];
    [alert show];

}

@end

看下效果

录制效果好差啊

三、其它存在问题:

demo中转盘是在拿到模拟数据后开始转动的,这样很容易控制;
但在实际运用中,请求结果时候来源于服务器,可能因为网络等问题延迟,出现单击“开始”后许久没转动的问题。

这里有必要进一步修正。

四、demo下载

代码下载

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值