先来看一下效果

这是通过调用iOS的陀螺仪和加速度计。通过倾斜手机实现的效果
Core Motion
   加速度计和陀螺仪是通过Core Motion框架,来管理访问的。此框架提供了CMMotionManager类,它提供的数据都是用来描述设备的移动的。还提供了CMAccelerometerData和CMGroData,他们可以访问原生的加速度计和陀螺仪信息。另外还有CMDeviceMotion,这个类里面包含有加速度计和陀螺仪的测量数据,以及方位信息。即设备是平放,朝上,朝下,还是朝左等信息。话不多说还是直接上代码。
   先来个坐标系作为参考
 
看一下各项数据
| 1 | 
 | 
然后我们来做一个Demo
  controller中代码实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@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文件1
2
3
4
5
6
@interface BallView : UIView
@property (nonatomic,assign)CMAcceleration acceleration;
- (void)update;
@end
.m文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89@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{
    _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];
}
- (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原来的版本有个摇动的球清理内存那样的效果)。
  如需转载请注明出处,请尊重作者的劳动成果。