前言函數
對於應用的交互,重力感應的加速器和陀螺儀能夠開創一些比較新穎的交互方式,好比使用加速器實現搖一搖功能,使用陀螺儀實現圖片跟隨設備旋轉或者是敲擊反應(實現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