模拟物体的惯性滚动

Posted

技术标签:

【中文标题】模拟物体的惯性滚动【英文标题】:Simulating Inertial Scrolling for an object 【发布时间】:2013-09-17 10:07:24 【问题描述】:

我有一个需要拖动和模拟惯性滚动的对象。

这是我迄今为止工作缓慢的情况。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self];

    self.lastTouch = touchLocation;
    self.lastTimestamp = event.timestamp;


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

    UITouch *touch = [touches anyObject];
    CGPoint currentLocation = [touch locationInNode:self];

    // how much it scrolled vertically (it is a table view, no need to scroll horizontally)
    CGFloat deltaY = currentLocation.y - self.lastTouch.y;

    // move the container (that is the object I want to implement the inertial movement)
    // to the correct position
    CGPoint posActual = self.container.position; 
    posActual.y = posActual.y + deltaY;
    [self.container setPosition:posActual];


    // calculate the movement speed
    NSTimeInterval deltaTime = event.timestamp - self.lastTimestamp;
    self.speedY = deltaY / deltaTime;

    self.lastTouch = currentLocation;
    self.lastTimestamp = event.timestamp;



- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

    CGFloat tempoDecay = 0.4f;

    CGPoint finalPosition = self.container.position;
    finalPosition.y = finalPosition.y + (self.speedY * tempoDecay);

    // move the object to the final position using easeOut timing...


这就是我所看到的:我滑动它。当我抬起手指时,它会加速,然后突然停止。我已经记录了 speedY 值,这些值非常大,比如 720! (每秒 720 像素?)

我无法使用 UIScrollView 或 Apple 提供的其他方法。它是一个必须靠自身惯性滚动的对象。谢谢。

【问题讨论】:

你在老问题上有几个很好的问题。不要只是删除它并重新开始。 我已经要求人们检查我的代码,而不是提供我可以用来创建可以通过可疑方式使其工作的蹩脚代码的黑客攻击的建议。显然我所问的是合理的并且可以做到。因此,您可以尝试回答我的问题,而不是拒绝投票问题并制作像您最新的那样没有帮助的 cmets。如果您没有知识或不想提供帮助,请让其他更专业的人尝试。谢谢。 我否决了您删除旧问题以摆脱您认为没有用的 cmets 然后创建一个新问题的事实。建议的内容根本不是 hack,如果您遵循给出的建议并观看相关的 WWDC 视频,您会发现 Apple 开发团队实际上使用了相同的技术。 我过去看过那两个 spritekit 视频,但不记得看过。根据您的建议,我已经清理了两个视频(因为我现在没有时间花 2 个小时观看它们),但一无所获。 【参考方案1】:

我通过在场景的更新方法中添加“惯性制动”来实现这种惯性滚动(垂直填充许多精灵以模拟垂直滚动选择的 SKSpriteNode 对象)

// add the variables as member variables to your class , setup with initial values on your init 
  SKSpriteNode *mList // this is the sprite node that will be our scroll object
  mTouching = NO;         // BOOL
  mLastScrollDist = 0.0f; // float

在您的 touchesBegan 中,将 mTouching 更改为 YES ,表示触摸有效..

在您的 touchesMoved 中,计算 mLastScrollDist = previousLocation.y - currentlocation.y ,然后将其添加到 mList 的 y 位置 (mList.y += mLastScrollDist)

在您的 touchesEnded 中,将 mTouching 更改为 NO

最后在场景的更新方法中,计算刹车惯性效果

- (void)update:(NSTimeInterval)currentTime

    if (!mTouching)
    
        float slowDown = 0.98f;

        if (fabsf(mLastScrollDist) < 0.5f)
            slowDown = 0;

        mLastScrollDist *= slowDown;
        mList.y += mLastScrollDist; // mList is the SKSpriteNode list object
    

【讨论】:

【参考方案2】:

touchesMoved 在您滑动期间多次调用。并且每次调用的两点之间的距离为15-30像素。让滑动持续 0.5 秒,该方法被调用 10 次。速度Y = 30/0.05 = 600。

还只考虑了最后的“touchesMoved 速度”。也许您需要计算平均速度?

【讨论】:

我添加了一个平均计算,但速度降低可以忽略不计。正在发生的事情是,应该减速的事情却没有。事实上,当我抬起手指时,物体会加速然后减速并突然停止。

以上是关于模拟物体的惯性滚动的主要内容,如果未能解决你的问题,请参考以下文章

当我无法使用 UIScrollView 时,如何在自定义 UIView 中模拟惯性滚动?

WinRT,C#,画布和子级惯性滚动

物体的惯性旋转

科氏力与地球自转产生的惯性离心力差别

如何更改网页的默认滚动速度、滚动量、滚动惯性

css CSS:移动滚动惯性的.css