iOS-重力感应

前言

对于应用的交互,重力感应的加速器和陀螺仪可以开创一些比较新颖的交互方式,比如使用加速器实现摇一摇功能,使用陀螺仪实现图片跟随设备旋转或者是敲击反应(实现pop back效果)等等;

 

(一)利用cmmotionmanager获取设备的及速度实现摇一摇的功能,再配合上自己设计的业务逻辑,就可以现实市面上很多应用的摇一摇功能了。

#import "MotionViewController.h"
#import <CoreMotion/CoreMotion.h>
#import "FloatTextField.h"

static const double accelerationThreshold = 2.0f;

@interface MotionViewController ()

@property CMMotionManager *motionManager;
@property NSOperationQueue *operationQueue;

@property (nonatomic, strong) UIImageView *image;

@end

@implementation MotionViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    _operationQueue = [[NSOperationQueue alloc] init];
    
    _motionManager = [CMMotionManager new];
    _motionManager.accelerometerUpdateInterval = 1.0f / 60;
    
    
    _image = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    _image.center = self.view.center;
    _image.backgroundColor = [UIColor blueColor];
    
    
    [self.view addSubview:_image];
    
    FloatTextField *textfield = [[FloatTextField alloc] initWithFrame:CGRectMake(0, 100, 200, 40)];
    textfield.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:textfield];
}

- (void)viewDidAppear:(BOOL)animated {
    
    [super viewDidAppear:animated];
    [self startAccelermeter];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:UIApplicationDidEnterBackgroundNotification object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:UIApplicationWillEnterForegroundNotification object:nil];
}


- (void)receiveNotification:(NSNotification *)notification {
    
    if ([notification.name isEqualToString:UIApplicationDidEnterBackgroundNotification]) {
        
        [_motionManager stopAccelerometerUpdates];
    } else {
        
        [self startAccelermeter];
    }
}


- (void)startAccelermeter {
    
    [_motionManager startAccelerometerUpdatesToQueue:_operationQueue withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
        
        [self outputaccelerometerData:accelerometerData.acceleration];
    }];
}

- (void)outputaccelerometerData:(CMAcceleration)acceleration {
    
    double accelermeter = sqrt(pow(acceleration.x, 2) + pow(acceleration.y, 2) + pow(acceleration.z, 2));
    if (accelermeter > accelerationThreshold) {
        
        [_motionManager stopAccelerometerUpdates];
        [_operationQueue cancelAllOperations];
        
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            
            [self turnRight];
        }];
    }
}


-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
    CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x,
                                   view.bounds.size.height * anchorPoint.y);
    CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x,
                                   view.bounds.size.height * view.layer.anchorPoint.y);
    
    newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
    oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
    
    CGPoint position = view.layer.position;
    
    position.x -= oldPoint.x;
    position.x += newPoint.x;
    
    position.y -= oldPoint.y;
    position.y += newPoint.y;
    
    view.layer.position = position;
    view.layer.anchorPoint = anchorPoint;
}


- (void)turnRight {
    
    CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    rotate.fromValue = [NSNumber numberWithFloat:0];
    rotate.toValue = [NSNumber numberWithFloat:M_PI / 3.0];
    rotate.duration = 0.18;
    rotate.repeatCount = 2;
    rotate.autoreverses = YES;
    
    [CATransaction begin];
    [self setAnchorPoint:CGPointMake(-0.2, 0.9) forView:_image];
    [CATransaction setCompletionBlock:^{
        
        [self getData];
    }];
    
    [_image.layer addAnimation:rotate forKey:nil];
    
    [CATransaction commit];
}


- (void)getData {
    
    [self startAccelermeter];
}
@end

解释一下-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view函数,此函数是通过设置的anchorPoint,计算出对应的position,达到不移动的效果。此方法参考至这篇文章

 

总结

以上只是实现了摇一摇的功能,一个简单的效果,其他的更好更复杂功能,大家可以去实践,通过cmmotionmanager获取得到数据,然后通过数据的计算,实现你想要的效果。

转载于:https://my.oschina.net/u/1450995/blog/719871

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值