gpt4 book ai didi

iphone - 在 cocoa touch 中实现基于触摸的旋转

转载 作者:搜寻专家 更新时间:2023-10-30 19:45:22 24 4
gpt4 key购买 nike

我想知道在我的 iPhone 应用程序中实现基于旋转的拖动 Action 的最佳方式是什么。

我有一个 UIView,当用户手指触摸 View 并移动它时,我希望围绕它的中心旋转。可以把它想象成一个需要用手指调整的刻度盘。

基本问题归结为:

1) 我是否应该记住调用 touchesBegan 时的初始角度和变换,然后每次调用 touchesMoved 时都根据手指的当前位置对 View 应用新的变换,例如:

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

UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self]; //current position of touch

if (([touch view] == self)
&& [Utility getDistance:currentPoint toPoint:self.middle] <= ROTATE_RADIUS //middle is centre of view
&& [Utility getDistance:currentPoint toPoint:self.middle] >= MOVE_RADIUS) { //will be rotation gesture

//remember state of view at beginning of touch
CGPoint top = CGPointMake(self.middle.x, 0);
self.initialTouch = currentPoint;
self.initialAngle = angleBetweenLines(self.middle, top, self.middle, currentPoint);
self.initialTransform = self.transform;
}
}

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

UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self]; //current position of touch

if (([touch view] == self)
&& [Utility getDistance:currentPoint toPoint:self.middle] <= ROTATE_RADIUS
&& [Utility getDistance:currentPoint toPoint:self.middle] >= MOVE_RADIUS) { //a rotation gesture

//rotate tile
float newAngle = angleBetweenLines(self.middle, CGPointMake(self.middle.x, 0), self.middle, currentPoint); //touch angle
float angleDif = newAngle - self.initialAngle; //work out dif between angle at beginning of touch and now.
CGAffineTransform newTransform = CGAffineTransformRotate(self.initialTransform, angleDif); //create new transform
self.transform = newTransform; //apply transform.
}

2) 我是否应该只记住最后一个已知的位置/角度,并根据那个位置和现在的角度差旋转 View ,例如:

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

UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self]; //current position of touch

if (([touch view] == self)
&& [Utility getDistance:currentPoint toPoint:self.middle] <= ROTATE_RADIUS
&& [Utility getDistance:currentPoint toPoint:self.middle] >= MOVE_RADIUS) { //will be rotation gesture

//remember state of view at beginning of touch
CGPoint top = CGPointMake(self.middle.x, 0);
self.lastTouch = currentPoint;
self.lastAngle = angleBetweenLines(self.middle, top, self.middle, currentPoint);
}
}

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

UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self]; //current position of touch

if (([touch view] == self)
&& [Utility getDistance:currentPoint toPoint:middle] <= ROTATE_RADIUS
&& [Utility getDistance:currentPoint toPoint:middle] >= MOVE_RADIUS) { //a rotation gesture

//rotate tile
float newAngle = angleBetweenLines(self.middle, CGPointMake(self.middle.x, 0), self.middle, currentPoint); //touch angle
float angleDif = newAngle - self.lastAngle; //work out dif between angle at beginning of touch and now.
CGAffineTransform newTransform = CGAffineTransformRotate(self.transform, angleDif); //create new transform

self.transform = newTransform; //apply transform.
self.lastTouch = currentPoint;
self.lastAngle = newAngle;
}

第二个选项对我来说更有意义,但它并没有给出非常令人满意的结果(锯齿状更新和非平滑旋转)。就性能而言,哪种方式最好(如果有的话)?

干杯!

最佳答案

它实际上比您尝试过的要简单得多。

您需要三个数据点:

  • 你的观点的来源。
  • 当前触摸的位置
  • 上次触摸的位置

传递给您的 Touch 对象实际上包含最后一个触摸位置。因此您无需跟踪它。

您所要做的就是计算两条线之间的角度:

  • 当前触摸的起源
  • 上次触摸的起点

然后将其转换为弧度并在您的 CGAffineTransformRotate() 中使用它。在您的 touchesMoved 处理程序中完成这一切。

这是一个计算你所需要的函数:

static inline CGFloat angleBetweenLinesInRadians(CGPoint line1Start, CGPoint line1End, CGPoint line2Start, CGPoint line2End) {

CGFloat a = line1End.x - line1Start.x;
CGFloat b = line1End.y - line1Start.y;
CGFloat c = line2End.x - line2Start.x;
CGFloat d = line2End.y - line2Start.y;

CGFloat line1Slope = (line1End.y - line1Start.y) / (line1End.x - line1Start.x);
CGFloat line2Slope = (line2End.y - line2Start.y) / (line2End.x - line2Start.x);

CGFloat degs = acosf(((a*c) + (b*d)) / ((sqrt(a*a + b*b)) * (sqrt(c*c + d*d))));


return (line2Slope > line1Slope) ? degs : -degs;
}

由 Jeff LaMarche 提供:

http://iphonedevelopment.blogspot.com/2009/12/better-two-finger-rotate-gesture.html

例子:

UITouch *touch = [touches anyObject];
CGPoint origin = [view center];
CGFloat angle = angleBetweenLinesInRadians(origin, [touch previousLocationInView:self.superview.superview], origin, [touch locationInView:self.superview.superview]);

关于iphone - 在 cocoa touch 中实现基于触摸的旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2780536/

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