记录一个iOS使用陀螺仪3d效果的抖动问题

使用陀螺仪的时候,遇到一个问题,就是在拖动scrollView滚动的时候,3d效果的图片会抖动

实现3d效果的代码

复制代码
- (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;
}

由 以上代码可以知道,我们的图片抖动就是图片的位置突变造成的,

而我们scrollview滚动的时候有突变,不滚动的时候没有突变。

我们打印位置的变化,发现打印太频繁,就修改了时间1/40 为 1 ,

发现我们我们如果不拖动,执行的位置改变没有突变的。但是时候

打印仍然比较频繁,我就讲时间改为10 ,这时候发现了一个问题,

就是不管我们拖动不拖动,每次改变的大小都很大超过了16,

发现如下想象

由此可以推断,是我们设置的陀螺仪更新频率不够大,导致

我们移动了很大距离之后,才更新位置,导致发生了突变现象,

而更新位置就是在陀螺仪的回调方法中实现的,就是说,我们

移动了很大的位置,陀螺仪才进行了回调,这才导致抖动。

如果陀螺仪的回调很频繁,那么我们移动了很小的距离,陀螺仪就会

回调,这个时候就不会有抖动的效果。

由此可以想到修改陀螺仪的时间

由于最新的苹果手机更新频率是120hz,

所以这里设置成了1/120

复制代码
    deviceMotionUpdateInterval = 1 / 120.0;

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

由此我们还可以得出一个结论,如果我们发现了抖动显现,

就可以推推测有可能 是位置发生了突变

相关推荐
星释21 分钟前
鸿蒙Flutter三方库适配指南-04.使用MacOS搭建开发环境
flutter·macos·harmonyos
mixboot2 小时前
VoxCPM macOS 安装部署
macos·voxcpm
游戏开发爱好者83 小时前
iOS 26 iPhone 使用记录分析 多工具组合构建全方位设备行为洞察体系
android·ios·小程序·uni-app·cocoa·iphone·webview
黑夜路人12 小时前
Claude Code + 国产模型GLM-4.6 安装指南 (for Windows/Mac)
windows·macos
索西引擎12 小时前
MacOS 若要启用系统扩展,你需要在 “恢复” 环境中修改安全性设置
macos
绒绒毛毛雨12 小时前
爬虫前奏--基于macos的ip代理池构建
爬虫·tcp/ip·macos
二流小码农14 小时前
鸿蒙开发:web页面如何适配深色模式
android·ios·harmonyos
yuec18 小时前
iOS 26 你的 property 崩了吗?
ios·客户端
jiangmiao202420 小时前
IOS开发 Runloop机制
ios·objective-c
從南走到北20 小时前
JAVA国际版任务悬赏发布接单系统源码支持IOS+Android+H5
android·java·ios·微信·微信小程序·小程序