Record a jitter problem using gyroscope 3D effect on iOS

When using the gyroscope, I encountered a problem. When dragging the scrollView to scroll, the 3D effect picture would shake.

Code to achieve 3D effect

- (void)updateWithGravityX:(double)gravityX
                  gravityY:(double)gravityY
                  gravityZ:(double)gravityZ
{
    //因为在斜向上45度角的时候,gravity的值是-0.5,设计要求以这个位置为基准,所以要减去-0.5
    gravityY -= (-0.5);
    gravityY *= 2;
    //最大的便宜量是maxoffset,所以gravityY最大为1
    gravityY = MIN(1, MAX(-1, gravityY));
    
    gravityX *= 2;
    gravityX = MIN(1, MAX(-1, gravityX));
    
    double timeInterval = sqrt(pow((gravityX - lastGravigyX),2) + pow((gravityY - lastGravityY), 2)) * deviceMotionUpdateInterval;
    NSString *animationKey = @"positionAnimation";
    CGPoint newBackImageViewCenter = self.backImageView.center;
    newBackImageViewCenter.x = (newBackImageViewCenter.x - gravityX * maxOffset);
    newBackImageViewCenter.y = (newBackImageViewCenter.y + gravityY * maxOffset);
    
    CABasicAnimation *backImageViewAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    backImageViewAnimation.fromValue = [NSValue valueWithCGPoint:backImageViewCenter];
    backImageViewAnimation.toValue = [NSValue valueWithCGPoint:newBackImageViewCenter];
    backImageViewAnimation.duration = timeInterval;
    backImageViewAnimation.fillMode = kCAFillModeForwards;
    backImageViewAnimation.removedOnCompletion = NO;
    
    [self.backImageView.layer removeAnimationForKey:animationKey];
    [self.backImageView.layer addAnimation:backImageViewAnimation forKey:animationKey];
    
    CGPoint newFrontImageViewCenter = self.frontImageView.center;
    newFrontImageViewCenter.x += gravityX * maxOffset;
    newFrontImageViewCenter.y -= gravityY * maxOffset;
    
    CABasicAnimation *frontImageViewAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    frontImageViewAnimation.fromValue = [NSValue valueWithCGPoint:frontImageViewCenter];
    frontImageViewAnimation.toValue = [NSValue valueWithCGPoint:newFrontImageViewCenter];
    frontImageViewAnimation.duration = timeInterval;
    frontImageViewAnimation.fillMode = kCAFillModeForwards;
    frontImageViewAnimation.removedOnCompletion = NO;
    [self.frontImageView.layer removeAnimationForKey:animationKey];
    [self.frontImageView.layer addAnimation:frontImageViewAnimation forKey:animationKey];
    
    CGPoint newSecondFrontImageViewCenter = self.smallMovementView.center;
    if (self.smallMovementView == self.secondFrontImageView) {
        newSecondFrontImageViewCenter.x += gravityX * maxOffset/3;
        newSecondFrontImageViewCenter.y -= gravityY * maxOffset/3;
    } else if (self.smallMovementView == self.middleImageView) {
        newSecondFrontImageViewCenter.x -= gravityX * maxOffset/3;
        newSecondFrontImageViewCenter.y += gravityY * maxOffset/3;
    }

    CABasicAnimation *secondfrontImageViewAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    secondfrontImageViewAnimation.fromValue = [NSValue valueWithCGPoint:secondFrontImageViewCenter];
    secondfrontImageViewAnimation.toValue = [NSValue valueWithCGPoint:newSecondFrontImageViewCenter];
    secondfrontImageViewAnimation.duration = timeInterval;
    secondfrontImageViewAnimation.fillMode = kCAFillModeForwards;
    secondfrontImageViewAnimation.removedOnCompletion = NO;
    [self.smallMovementView.layer removeAnimationForKey:animationKey];
    [self.smallMovementView.layer addAnimation:secondfrontImageViewAnimation forKey:animationKey];
    
    backImageViewCenter = newBackImageViewCenter;
    frontImageViewCenter = newFrontImageViewCenter;
    secondFrontImageViewCenter = newSecondFrontImageViewCenter;
}

From the above code, we can know that the jitter of our picture is caused by the mutation of the position of the picture,
and there is a mutation when our scrollview is scrolling, but there is no mutation when it is not scrolling.
We printed the changes in position and found that printing was too frequent, so we changed the time 1/40 to 1.
We found that if we did not drag, there would be no mutation in the position change. But time
printing is still relatively frequent, so I changed the time to 10. At this time, I discovered a problem,
that is, regardless of whether we drag or not, the size of each change is very large and exceeds 16.
I found the following imagination
Please add image description

It can be inferred from this that the update frequency of the gyroscope we set is not high enough, which causes
us to move a long distance before updating the position, resulting in a mutation phenomenon.
The updated position is implemented in the callback method of the gyroscope, that is Say, we
moved a large position before the gyroscope made a callback, which caused jitter.
If the gyroscope's callback is very frequent, then if we move a small distance, the gyroscope will
call back, and there will be no jitter effect at this time.
From this, we can think of the time to modify the gyroscope.
Since the latest Apple mobile phone update frequency is 120hz,
it is set to 1/120 here.

    deviceMotionUpdateInterval = 1 / 120.0;

- (CMMotionManager *)motionManager
{
    if (!_motionManager) {
        _motionManager = [[CMMotionManager alloc] init];
        _motionManager.deviceMotionUpdateInterval = deviceMotionUpdateInterval;
    }
    return _motionManager;
}

From this we can also draw a conclusion. If we find jitter,
we can infer that there may be a sudden change in position.

Guess you like

Origin blog.csdn.net/LIUXIAOXIAOBO/article/details/132892734