導(dǎo)讀
簡(jiǎn)單用OC寫了一個(gè)小球滾動(dòng)效果;
類似平衡球.
- GitHub地址:https://github.com/wangliujiayou/WLBallView 歡迎Star.
進(jìn)入正題-(傳感器)
傳感器是一種感應(yīng)\檢測(cè)裝置, 目前已經(jīng)廣泛應(yīng)用于智能手機(jī)上,用于感應(yīng)\檢測(cè)設(shè)備周邊的信息,不同類型的傳感器, 檢測(cè)的信息也不一樣
iOS中的傳感器

一、CoreMotion框架介紹
iOS中的一個(gè)核心運(yùn)動(dòng)框架CoreMotion.framework,CoreMotion是一個(gè)專門處理Motion的框架,其中包含了兩個(gè)部分加速度計(jì)和陀螺儀,在iOS4之前加速度計(jì)是由UIAccelerometer類來(lái)負(fù)責(zé)采集數(shù)據(jù),加速計(jì)由三個(gè)坐標(biāo)軸決定,用戶最常見的操作設(shè)備的動(dòng)作移動(dòng),晃動(dòng)手機(jī)(搖一搖),傾斜手機(jī)都可以被設(shè)備檢測(cè)到,加速計(jì)可以檢測(cè)到線性的變化,陀螺儀可以更好的檢測(cè)到偏轉(zhuǎn)的動(dòng)作,可以根據(jù)用戶的動(dòng)作做出相應(yīng)的動(dòng)作,iOS模擬器無(wú)法模擬以上動(dòng)作,真機(jī)調(diào)試需要開發(fā)者賬號(hào)。
二、CoreMotion數(shù)據(jù)獲取
CoreMotion中獲取數(shù)據(jù)主要是兩種方式:
Push方式:
提供一個(gè)線程管理器NSOperationQueue和一個(gè)回調(diào)Block,CoreMotion自動(dòng)在每一個(gè)采樣數(shù)據(jù)到來(lái)的時(shí)候回調(diào)這個(gè)Block,進(jìn)行處理。在這種情況下,Block中的操作會(huì)在你自己的主線程內(nèi)執(zhí)行。Pull方式,在這個(gè)方式里,你必須主動(dòng)去像
CMMotionManager要數(shù)據(jù),這個(gè)數(shù)據(jù)就是最近一次的采樣數(shù)據(jù)。
1. Pull方法
- (void)pull{
//初始化全局管理對(duì)象
CMMotionManager *manager = [[CMMotionManager alloc] init];
self.motionManager = manager;
//判斷加速度計(jì)可不可用,判斷加速度計(jì)是否開啟
if ([manager isAccelerometerAvailable] && [manager isAccelerometerActive]){
//告訴manager,更新頻率是100Hz
manager.accelerometerUpdateInterval = 1 / 60;
//開始更新,后臺(tái)線程開始運(yùn)行。這是Pull方式。
[manager startAccelerometerUpdates];
}
//獲取并處理加速度計(jì)數(shù)據(jù)
CMAccelerometerData *newestAccel = self.motionManager.accelerometerData;
NSLog(@"X = %.04f",newestAccel.acceleration.x);
NSLog(@"Y = %.04f",newestAccel.acceleration.y);
NSLog(@"Z = %.04f",newestAccel.acceleration.z);
}
2.Push方法
//判斷加速計(jì)是否可用
if([_motionManager isAccelerometerAvailable]) {
// 設(shè)置加速計(jì)頻率
[_motionManager setAccelerometerUpdateInterval:1 / 60];
//開始時(shí)時(shí)采樣數(shù)據(jù)
[_motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
NSLog(@"%f---%f",accelerometerData.acceleration.x,accelerometerData.acceleration.y);
}];
} else{
NSLog(@"設(shè)備不支持加速計(jì)");
}
陀螺儀和加速計(jì)是一樣的這里就不闡述了.
iOS UIDynamicAnimator
物理的幾種行為
UIAttachmentBehavior 吸附行為
UICollisionBehavior 碰撞行為
UIGravityBehavior 重力行為
UIPushBehavior 推力行為
UISnapBehavior 捕捉行為
UIAttachmentBehavior 吸附
// 1 可以跟錨點(diǎn) 2 可以item 與 item
self.attach = [[UIAttachmentBehavior alloc] initWithItem:self.view1 attachedToItem:self.view2];
self.attach.length = 100;// 距離
self.attach.damping = 0.3;// 阻尼系數(shù)(阻礙變化)
self.attach.frequency = 0.5;// 振動(dòng)頻率,(變化速度)
// self.attach.anchorPoint = CGPointMake(100, 100);
[self.animator addBehavior:self.attach];
// 2者在其他動(dòng)畫作用下保持相互作用力.
UICollisionBehavior 碰撞
# pragma mark - 碰撞
- (UICollisionBehavior *)collision {
if (_collision == nil) {
_collision = [[UICollisionBehavior alloc] init];
//參考邊界
_collision.translatesReferenceBoundsIntoBoundary = YES;
//所有事物碰撞
_collision.collisionMode = UICollisionBehaviorModeEverything;
[self.animator addBehavior:_collision];
}
return _collision;
}
// 1 bezierPath 邊界
UIBezierPath *bezierPath1 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetWidth(self.view.bounds)/2, CGRectGetHeight(self.view.bounds)) radius:CGRectGetWidth(self.view.bounds)/2 startAngle:0 endAngle:2*M_PI clockwise:YES];
[self.collision addBoundaryWithIdentifier:@"bezierPath1" forPath:bezierPath1];
// 2 point1 - point2 邊界
[self.collision addBoundaryWithIdentifier:@"point1_point2" fromPoint:CGPointMake(0, 300) toPoint:CGPointMake(CGRectGetWidth(self.view.bounds), 400)];
UIGravityBehavior 重力
# pragma mark - 重力
- (UIGravityBehavior *)gravity {
if (_gravity == nil) {
_gravity = [[UIGravityBehavior alloc] init];
// _gravity.magnitude = 1.0;
[self.animator addBehavior:_gravity];
}
return _gravity;
}
UIPushBehavior 推力
self.push = [[UIPushBehavior alloc] init];
self.push.active = YES;// 是否激活
self.push.angle = M_PI/4;// 方向
self.push.magnitude = 0.5;// 力
// self.push.pushDirection = CGVectorMake(1, 2);// 矢量
UISnapBehavior 捕捉
UISnapBehavior * snapbehavior = [[UISnapBehavior alloc] initWithItem:self.imageview snapToPoint:self.view.center];
snapbehavior.damping = 0.65;
[self.animator addBehavior:snapbehavior];
UIDynamicItemBehavior 動(dòng)力學(xué)屬性
# pragma mark - 動(dòng)力學(xué)屬性
- (UIDynamicItemBehavior *)dynamic {
if (_dynamic == nil) {
_dynamic = [[UIDynamicItemBehavior alloc] init];
_dynamic.friction = 0.2;
_dynamic.elasticity = 0.8;
_dynamic.density = 0.2;
_dynamic.allowsRotation = YES;
_dynamic.resistance = 0;
[self.animator addBehavior:_dynamic];
}
return _dynamic;
}
具體應(yīng)用
給視圖添加各種行為
[self.dynamic addItem:ballView];
[self.collision addItem:ballView];
[self.gravity addItem:ballView];
使物體發(fā)生物理效果
if (!self.manager.isDeviceMotionAvailable) {
NSLog(@"換手機(jī)吧");
return;
}
self.manager.deviceMotionUpdateInterval = 0.01;
__weak typeof(self) weakSelf = self;
[self.manager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
if (error != nil) {
NSLog(@"出錯(cuò)了 %@",error);
return;
}
weakSelf.gravity.gravityDirection = CGVectorMake(motion.gravity.x * 3, -motion.gravity.y * 3);
// self.bkView.transform = CGAffineTransformMakeRotation(atan2(motion.gravity.x, motion.gravity.y) - M_PI);
}];
框架使用
1.導(dǎo)入#import "WLBallView.h"
2.創(chuàng)建WLBallView控件
3.調(diào)用starMotion方法即可實(shí)現(xiàn)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 傳進(jìn)圖片名字
WLBallView * ballView = [[WLBallView alloc] initWithFrame:CGRectMake(0, 80, 50, 50) AndImageName:self.array[arc4random_uniform(4)]];
[self.view addSubview:ballView];
// 開始運(yùn)動(dòng)
[ballView starMotion];
}

- 源碼可以從這里下載