iOS-仿膜拜貼紙滾動(dòng)(物理仿真)

導(dǎo)讀

簡(jiǎn)單用OC寫了一個(gè)小球滾動(dòng)效果;
類似平衡球.

膜拜滾動(dòng)

進(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

物理的幾種行為

  1. UIAttachmentBehavior 吸附行為

  2. UICollisionBehavior 碰撞行為

  3. UIGravityBehavior 重力行為

  4. UIPushBehavior 推力行為

  5. 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];
    
}
效果圖
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容