前言函数
对于应用的交互,重力感应的加速器和陀螺仪能够开创一些比较新颖的交互方式,好比使用加速器实现摇一摇功能,使用陀螺仪实现图片跟随设备旋转或者是敲击反应(实现pop back效果)等等;atom
(一)利用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,达到不移动的效果。此方法参考至这篇文章。code
总结orm
以上只是实现了摇一摇的功能,一个简单的效果,其余的更好更复杂功能,你们能够去实践,经过cmmotionmanager获取获得数据,而后经过数据的计算,实现你想要的效果。server