来!我们来玩一下陀螺仪和加速度计

先来看一下效果

111.gif


这是通过调用iOS的陀螺仪和加速度计。通过倾斜手机实现的效果

Core Motion

  加速度计和陀螺仪是通过Core Motion框架,来管理访问的。此框架提供了CMMotionManager类,它提供的数据都是用来描述设备的移动的。还提供了CMAccelerometerData和CMGroData,他们可以访问原生的加速度计和陀螺仪信息。另外还有CMDeviceMotion,这个类里面包含有加速度计和陀螺仪的测量数据,以及方位信息。即设备是平放,朝上,朝下,还是朝左等信息。话不多说还是直接上代码。
  先来个坐标系作为参考


屏幕快照 2016-07-09 下午5.24.42.png
看一下各项数据
#define kUpdateInterval (1.f / 60.f)//定义一个更新时间
@property (nonatomic,strong)CMMotionManager *motionManager;
@property (nonatomic,strong)NSOperationQueue *quene;
//声明一个线程self.motionManager = [[CMMotionManager alloc]init];NSOperationQueue *quene = [[NSOperationQueue alloc]init];
初始化一个线程,动作管理器需要一个单独的线程来运行,以便在每次发生事件时放入要执行的工作。苹果文档之处不要放在默认队列,可能会被事件填满,无法处理别的事件if (self.motionManager.deviceMotionAvailable) {self.motionManager.deviceMotionUpdateInterval = 0.1;//设置更新数据的时间间隔[self.motionManager startDeviceMotionUpdatesToQueue: quene withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {CMRotationRate rotationRate = motion.rotationRate;//旋转速率对应x,y,z分别是设备绕x,y,z 轴(上面有图参考)的旋转速率,顺时针为正,逆时针为负CMAcceleration gravity = motion.gravity;//自然加速度,可是识别手机的放置方向,设备平放在桌上,z=-1;屏幕朝左侧立,x = -1;充电口朝下垂直放置,y=-1CMAcceleration userAcc = motion.userAcceleration;//用户运动手机造成的加速度,分别向xyz方向运动时,正向时即为正值CMAttitude *attitude = motion.attitude;//设备的旋转程度,也可以理解为设备绕xyz轴旋转的程度,单位是弧度,即旋转一周的值为2π,手机绕举个例子:把手机平放在桌面上,旋转手机Yaw(偏移)开始变化,旋转180°时yaw = 3.14;绕Y轴旋转时Roll变化;绕X轴旋转时Pitch变化(方向不在多做讨论,参考系不一样,没法统一)NSString *gyroscopeText = [NSString   stringWithFormat:@"Rotation:\n x = %.2f\n y = %.2f\n z = %.2f",rotationRate.x,rotationRate.y,rotationRate.z];NSString *acceleratiorText = [NSString stringWithFormat:@"Accelertion: \n Gravity x = %.2f\tUser x = %.2f 
\n Gravity y = %.2f\tUser y = %.2f \n Gravity z = %.2f\tUser z = %.2f \n",gravity.x,userAcc.x,gravity.y,userAcc.y,gravity.z,userAcc.z];NSString *attitudeText = [NSString stringWithFormat:@"Attitute:\n Roll = %.2f\nPitch = %.2f
\nYaw = %.2f\n",attitude.roll,attitude.pitch,attitude.yaw];
//            NSLog(@"%@",gyroscopeText);dispatch_async(dispatch_get_main_queue(), ^{_gyroscopeLabel.text = gyroscopeText;_accelerometerLabel.text = acceleratiorText;_attitudeLabel.text = attitudeText;});}];}
然后我们来做一个Demo

controller中代码实现

#define kUpdateInterval (1.f / 60.f)//更新频率高一点
@interface BallViewController ()
@property (nonatomic,strong)CMMotionManager *motionManager;
@property (nonatomic,strong)NSOperationQueue *quene;
@end
- (void)viewDidLoad {[super viewDidLoad];BallView *ballView = [[BallView alloc]initWithFrame:self.view.bounds];
//自己写的类继承自UIView[self.view addSubview:ballView];self.motionManager = [[CMMotionManager alloc]init];self.quene = [[NSOperationQueue alloc]init];self.motionManager.deviceMotionUpdateInterval = kUpdateInterval;[self.motionManager startDeviceMotionUpdatesToQueue:_quene withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
//此处也可以传入motion.userAcceleration。(用户移动手机产生的加速度)这样就可以实现摇动来控制(ballView里面的放大倍数记得要改大一点)[ballView setAcceleration:motion.gravity];dispatch_async(dispatch_get_main_queue(), ^{[ballView update];//主线程更新UI});}];
}

BallView的实现
.h文件

#import 
#import 
@interface BallView : UIView
@property (nonatomic,assign)CMAcceleration acceleration;
- (void)update;
@end

.m文件

@interface BallView ()
@property (nonatomic,assign)CGFloat width;
@property (nonatomic,assign)CGFloat height;
@property (nonatomic,assign)CGFloat imageWidth;
@property (nonatomic,assign)CGFloat imageHeight;
@property (nonatomic,strong)UIImage *image;
@property (nonatomic,strong)UIImageView *imageView;
@property (nonatomic,assign)CGPoint currentPoint;//当前ImageView位置
@property (nonatomic,assign)CGFloat ballXVelocity;//X方向速度
@property (nonatomic,assign)CGFloat ballYVelocity;//Y方向速度
@end@implementation BallView- (instancetype)initWithFrame:(CGRect)frame{self = [super initWithFrame:frame];if (self) {[self commoninit];self.backgroundColor = [UIColor whiteColor];}return self;
}
- (void)commoninit{self.image = [UIImage imageNamed:@"btn_nav04@3x"];self.imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.imageWidth, self.imageHeight)];self.imageView.image = _image;[self addSubview:self.imageView];self.currentPoint = CGPointMake(self.bounds.size.width/2.f+self.image.size.width/2.f, self.bounds.size.height/2.f+self.image.size.height/2.f);self.imageView.center = _currentPoint;
}- (void)setCurrentPoint:(CGPoint)newPoint{self.previousePoint = self.currentPoint;_currentPoint = newPoint;//边缘判断if (self.currentPoint.x <= self.imageWidth/2.f) {_currentPoint.x = self.imageWidth/2.f;self.ballXVelocity = -_ballXVelocity/2.f;//反弹效果,接触边缘后加速度反向减半}if (self.currentPoint.y <= self.imageHeight/2.f) {_currentPoint.y = self.imageHeight/2.f;self.ballYVelocity = -_ballYVelocity/2.f;//反弹效果,接触边缘后加速度反向减半}if (self.currentPoint.x >= self.width -self.imageWidth/2.f ) {_currentPoint.x = self.width -self.imageWidth/2.f;self.ballXVelocity = -_ballXVelocity/2.f;//反弹效果,接触边缘后加速度反向减半}if (self.currentPoint.y >= self.height -self.imageHeight/2.f ) {_currentPoint.y = self.height -self.imageHeight/2.f;self.ballYVelocity = -_ballYVelocity/2.f;//反弹效果,接触边缘后加速度反向减半}[self updateCenter];
}
- (void)updateCenter{self.imageView.center = _currentPoint;
}- (void)update{static NSDate *lastUpdateTime = nil;if (lastUpdateTime != nil) {NSTimeInterval secondsSinceLastDraw = [[NSDate date] timeIntervalSinceDate:lastUpdateTime];//两次更新的时间差self.ballXVelocity = self.ballXVelocity + (self.acceleration.x * secondsSinceLastDraw);//X方向上原速度加上加速度乘以时间,计算当前速度self.ballYVelocity = self.ballYVelocity - (self.acceleration.y * secondsSinceLastDraw);//Y方向上原速度加上加速度乘以时间,计算当前速度CGFloat xAccel = secondsSinceLastDraw * self.ballXVelocity * 1000;//计算位置变化量。由于这个值很小,所以我们要放大一些才更加真实此处//若想使用摇动,要把放大倍数调大,10000效果不错CGFloat yAccel = secondsSinceLastDraw * self.ballYVelocity * 1000;self.currentPoint = CGPointMake(self.currentPoint.x + xAccel, self.currentPoint.y + yAccel);}lastUpdateTime = [NSDate date];
}
#pragma mark - widthAndHeight
- (CGFloat)width{return self.bounds.size.width;
}
- (CGFloat)height{return self.bounds.size.height;
}
- (CGFloat)imageWidth{return self.image.size.width;
}
- (CGFloat)imageHeight{return self.image.size.height;
}

  这样你就可以实现,倾斜手机来移动图片,就像真是的重力产生的效果一样。同样也可以实现,摇动的效果。(就像安卓的360原来的版本有个摇动的球清理内存那样的效果)。
  如需转载请注明出处,请尊重作者的劳动成果。



文/_南山忆(简书作者)
原文链接:http://www.jianshu.com/p/0718f30b416e
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部