4

UIScrollVIewで複数のサブビューをスクロールするために加速度計を使用しています。ユーザーがiPhoneを右にフリックするとビュー(縦向き)が右にスクロールし、デバイスが左にフリックすると左にスクロールするようにします。

正または負のx加速度値に注意するだけでそれができると思いましたが、通常、値は正と負の値の混合であることがわかります。揺れのない動きをなくすために床を1.5gに設定し、0.5秒間のx値を調べています。

フリックの全体的な方向を決定するための三角測量法があり、フリック動作の期間にわたって値を測定する必要があると確信しています。また、誰かがすでにこれを理解していると確信しています。

そこに何かアイデアはありますか?

ありがとう

4

2 に答える 2

8

提案されたソリューションよりも優れたフィードバックを提供するソリューションを開発しました (左右の揺れのみ)。ここで行った方法は非常に敏感です (小さな揺れを認識します) が、感度は、tresholdFirstMove と tresholdBackMove を変更することで適応させることができます (感度を下げるには増加させます)。

Swift の場合: (viewController に "import CoreMotion" を追加)

var startedLeftTilt = false
var startedRightTilt = false
var dateLastShake = NSDate(timeIntervalSinceNow: -2)
var dateStartedTilt = NSDate(timeIntervalSinceNow: -2)
var motionManager = CMMotionManager()
let tresholdFirstMove = 3.0
let tresholdBackMove = 0.5

override func viewDidLoad() {
    // your code

    motionManager.gyroUpdateInterval = 0.01
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    motionManager.startGyroUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler: { (gyroData, error) -> Void in
        self.handleGyroData(gyroData.rotationRate)
    })

}

private func handleGyroData(rotation: CMRotationRate) {

    if fabs(rotation.z) > tresholdFirstMove && fabs(dateLastShake.timeIntervalSinceNow) > 0.3
    {
        if !startedRightTilt && !startedLeftTilt
        {
            dateStartedTilt = NSDate()
            if (rotation.z > 0)
            {
                startedLeftTilt = true
                startedRightTilt = false
            }
            else
            {
                startedRightTilt = true
                startedLeftTilt = false
            }
        }
    }

    if fabs(dateStartedTilt.timeIntervalSinceNow) >= 0.3
    {
        startedRightTilt = false
        startedLeftTilt = false
    }
    else
    {
        if (fabs(rotation.z) > tresholdBackMove)
        {
            if startedLeftTilt && rotation.z < 0
            {
                dateLastShake = NSDate()
                startedRightTilt = false
                startedLeftTilt = false

                println("\\\n Shaked left\n/")
            }
            else if startedRightTilt && rotation.z > 0
            {
                dateLastShake = NSDate()
                startedRightTilt = false
                startedLeftTilt = false

                println("\\\n Shaked right\n/")
            }
        }
    }

}
于 2015-03-13T11:24:42.443 に答える
5

OK、解決策を見つけました。シェイク モーション (x 軸で 1.5 を超える加速度) を検出すると、タイマーを開始し、BOOL を true に設定します。BOOL が true の間、加速値を追加します。タイマーが切れると、加速度値の追加を停止し、合計加速度の符号によって揺れの方向を判断します。


- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler {

    if (fabsf(aceler.x) > 1.5)
    {
        shake = YES;
        NSTimeInterval myInterval = .75;
        [NSTimer scheduledTimerWithTimeInterval:myInterval target:self selector:@selector(endShake) userInfo:nil repeats:NO];
        return;
    }

    if(shake)
    {
        totalG += aceler.x;
    }
}

- (void) endShake {
    shake = NO;
    int direction;
    if (totalG isLessThan 0) direction = 1;
    if(totalG isGreaterThan 0) direction = -1;
    [self changePageByShake:direction];
    totalG = 0;
}

注: 上記のコードブロックで < および > 記号を正しくフォーマットすることができなかったので、記号を isLessThan および isGreaterThan に置き換えました。

于 2009-06-19T17:19:42.153 に答える