gpt4 book ai didi

iphone - 减速移动 UIView

转载 作者:太空狗 更新时间:2023-10-30 03:49:44 24 4
gpt4 key购买 nike

我需要在屏幕上减速点击并拖动一个 UIView。我已经很好地编写了用于通过触摸移动 View 的代码,但是需要对象以一定的惯性(一旦达到某个加速度阈值)继续移动,减速直到它停止,或者遇到屏幕的边界。这不是用于游戏,而是使用一些标准的 UIView 控件。我面临的最大问题是加速。

您是否编写了任何好的算法来实现相同的目标?

编辑:

我在 touchesEnded: 方法上使用了一个动画 block ,但是在一个人松开手指和动画开始之间存在明显的延迟:

[UIView transitionWithView:self 
duration:UI_USER_INTERFACE_IDIOM() ==
UIUserInterfaceIdiomPhone ? 0.33f : 0.33f * 2.0f
options:UIViewAnimationCurveEaseOut
animations:^(void){
if (dir == 1) // Flicked left
{
self.center = CGPointMake(self.frame.size.width * 0.5f,
self.center.y);
}
else { // Flicked right
self.center = CGPointMake(
self.superview.bounds.size.width -
(self.frame.size.width * 0.5f), self.center.y);
}
}
completion:^(BOOL finished){
// Do nothing
}];

最佳答案

问题出在用于动画的计时函数中。动画首先应该和用户拖动一样快,然后迅速减速。以下代码显示了实现此行为的一个非常简单的示例。

首先,在我的 touchesBegan:withEvent: 方法中,我将第一个触摸位置记录到我的点缓冲区中。我正在缓冲两个触摸位置以获取 View 的移动向量,并且可能有不同的方法来获取向量。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
ivar_lastPoint[0] = [[touches anyObject] locationInView:self];
ivar_lastPoint[1] = ivar_lastPoint[0];
ivar_touchOffset.x = ivar_lastPoint[0].x - self.sprite.position.x;
ivar_touchOffset.y = ivar_lastPoint[0].y - self.sprite.position.y;
self.lastTime = [NSDate date];
}

然后,在 touchesMoved:withEvent: 方法中,我更新了 View 的位置。实际上,我使用了 CALayer 而不是 View ,因为我想为其动画使用自定义计时功能。因此,我根据用户更新图层的位置,并在给定的时间间隔内更新位置缓冲区。

#define kSampleInterval 0.02f

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

[CATransaction begin];
[CATransaction setDisableActions:YES];
/* First of all, move the object */
CGPoint currentPoint = [[touches anyObject] locationInView:self];
CGPoint center = self.sprite.position;
center.x = currentPoint.x - ivar_touchOffset.x;
center.y = currentPoint.y - ivar_touchOffset.y;
self.sprite.position = center;

/* Sample locations */
NSDate *currentTime = [NSDate date];
NSTimeInterval interval = [currentTime timeIntervalSinceDate:self.lastTime];
if (interval > kSampleInterval) {
ivar_lastPoint[0] = ivar_lastPoint[1];
ivar_lastPoint[1] = currentPoint;
self.lastTime = currentTime;
self.lastInterval = interval;

}
[CATransaction commit];
}

self.sprite 是对我 View 中 CALayer 对象的引用。我不需要拖动动画,所以我使用 CATransaction 类对象禁用了它。

最后,我计算向量并在 touchesEnded:withEvent: 方法中应用动画。在这里,我创建了一个自定义的 CAMediaTimingFunction,所以它真的是“快进快出”。

#define kDecelerationDuration 1.0f
#define kDamping 5.0f

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint targetPoint;
NSDate *currentTime = [NSDate date];
NSTimeInterval interval = self.lastInterval + [currentTime timeIntervalSinceDate:self.lastTime];
targetPoint.x = self.sprite.position.x + (ivar_lastPoint[1].x - ivar_lastPoint[0].x)/interval*kDecelerationDuration/kDamping;
targetPoint.y = self.sprite.position.y + (ivar_lastPoint[1].y - ivar_lastPoint[0].y)/interval*kDecelerationDuration/kDamping;
if (targetPoint.x < 0) {
targetPoint.x = 0;
} else if (targetPoint.x > self.bounds.size.width) {
targetPoint.x = self.bounds.size.width;
}
if (targetPoint.y < 0) {
targetPoint.y = 0;
} else if (targetPoint.y > self.bounds.size.height) {
targetPoint.y = self.bounds.size.height;
}
CAMediaTimingFunction *timingFunction = [CAMediaTimingFunction functionWithControlPoints:
0.1f : 0.9f :0.2f :1.0f];

[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:kDecelerationDuration] forKey:kCATransactionAnimationDuration];
[CATransaction setAnimationTimingFunction:timingFunction];

self.sprite.position = targetPoint;
[CATransaction commit];

}

这是一个非常简单的例子。您可能需要更好的矢量获取机制。此外,这只会移动一个可视组件 (CALayer)。您可能需要一个 UIView 对象来处理来自该对象的事件。在这种情况下,您可能希望通过 CALayer 设置动画,并单独移动实际的 UIView 对象。可以有多种方式一起处理 CALayer 动画和 UIView 重定位。

关于iphone - 减速移动 UIView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5131383/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com