如何实现单指旋转手势识别器?

发布于 2024-09-16 04:49:58 字数 133 浏览 9 评论 0原文

我知道 UIRotateGestureRecognizer 已经成为 iOS 的一部分。但这个手势需要两根手指。如何实现仅需要一根手指的类似手势识别器? AppStore 中有一款游戏 - Gyrotate 很好地实现了这一点。任何线索表示赞赏。谢谢。

I'm aware that there's the UIRotateGestureRecognizer already part of the iOS. But this gesture required two fingers. How I can implement a similar gesture recognizer requiring only one finger? There's a game in the AppStore - Gyrotate with a pretty good implementation of this. Any clues are appreciated. Thx.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

裂开嘴轻声笑有多痛 2024-09-23 04:49:58

Kirby Turner 在此处有一个完整的单指旋转手势识别器。

Kirby Turner has a complete one finger rotation gesture recognizer here.

莫言歌 2024-09-23 04:49:58

这是代码 - 它可以在我的模拟器上运行。马克回答说,如果这就是您所寻找的。

    // On new touch, start a new array of points
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event
{
    self.points = [NSMutableArray array];
    CGPoint pt = [[touches anyObject] locationInView:self];
    [self.points addObject:[NSValue valueWithCGPoint:pt]];
}

// Add each point to the array
- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event
{
    CGPoint pt = [[touches anyObject] locationInView:self];
    [self.points addObject:[NSValue valueWithCGPoint:pt]];
    [self setNeedsDisplay];
}

// At the end of touches, determine whether a circle was drawn
- (void) touchesEnded:(NSSet *) touches withEvent:(UIEvent *) event
{
    if (!self.points) return;
    if (self.points.count < 3) return;

    // Test 1: The start and end points must be between 60 pixels of each other
    CGRect tcircle;
    if (distance(POINT(0), POINT(self.points.count - 1)) < 60.0f)
        tcircle = [self centeredRectangle];

    // Test 2: Count the distance traveled in degrees. Must fall within 45 degrees of 2 PI
    CGPoint center = CGPointMake(CGRectGetMidX(tcircle), CGRectGetMidY(tcircle));
    float distance = ABS(acos(dotproduct(centerPoint(POINT(0), center), centerPoint(POINT(1), center))));
    for (int i = 1; i < (self.points.count - 1); i++)
        distance += ABS(acos(dotproduct(centerPoint(POINT(i), center), centerPoint(POINT(i+1), center))));
    if ((ABS(distance - 2 * M_PI) < (M_PI / 4.0f))) circle = tcircle;

    [self setNeedsDisplay];
}

Here's the code - it works on my simulator. Mark answered if that is what you were looking for.

    // On new touch, start a new array of points
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event
{
    self.points = [NSMutableArray array];
    CGPoint pt = [[touches anyObject] locationInView:self];
    [self.points addObject:[NSValue valueWithCGPoint:pt]];
}

// Add each point to the array
- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event
{
    CGPoint pt = [[touches anyObject] locationInView:self];
    [self.points addObject:[NSValue valueWithCGPoint:pt]];
    [self setNeedsDisplay];
}

// At the end of touches, determine whether a circle was drawn
- (void) touchesEnded:(NSSet *) touches withEvent:(UIEvent *) event
{
    if (!self.points) return;
    if (self.points.count < 3) return;

    // Test 1: The start and end points must be between 60 pixels of each other
    CGRect tcircle;
    if (distance(POINT(0), POINT(self.points.count - 1)) < 60.0f)
        tcircle = [self centeredRectangle];

    // Test 2: Count the distance traveled in degrees. Must fall within 45 degrees of 2 PI
    CGPoint center = CGPointMake(CGRectGetMidX(tcircle), CGRectGetMidY(tcircle));
    float distance = ABS(acos(dotproduct(centerPoint(POINT(0), center), centerPoint(POINT(1), center))));
    for (int i = 1; i < (self.points.count - 1); i++)
        distance += ABS(acos(dotproduct(centerPoint(POINT(i), center), centerPoint(POINT(i+1), center))));
    if ((ABS(distance - 2 * M_PI) < (M_PI / 4.0f))) circle = tcircle;

    [self setNeedsDisplay];
}
猫瑾少女 2024-09-23 04:49:58

我实现了带有 OneFingerRotation缩放调整大小关闭功能的IQStickerView

特点:-

1) 一指旋转刻度。

2) 一指调整大小。

3) 使用属性启用/禁用旋转、缩放、调整大小。

4) 自动管理多个IQStickerView。

5) 也可以与 UIScrollView 一起使用。

6)快速响应。

github 存储库在这里:- https://github.com/hackiftekhar/IQStickerView

I implemented IQStickerView with OneFingerRotation, Scale, Resize and Close feature.

Features:-

1) One Finger Rotation Scale.

2) One Finger Resize.

3) Enable/Desable Rotation, Scale, Resize with properties.

4) Auto manage Multiple IQStickerView.

5) Can work with UIScrollView also.

6) Fast Responsiveness.

github repositor is here:- https://github.com/hackiftekhar/IQStickerView

℡寂寞咖啡 2024-09-23 04:49:58

尝试探索 UIGestureRecognizer 类。您应该能够使用 UIGestureRecognizerDelegate 自定义它

Try exploring UIGestureRecognizer Class. You should be able to customize it using UIGestureRecognizerDelegate

粉红×色少女 2024-09-23 04:49:58

使用平移手势识别器实现,这是使用手势识别器附加到的另一个 UIView,但它应该与附加到您想要旋转的视图一起使用。

- (void) gestureRotateButtonPan:(UIPanGestureRecognizer*) gestureRecognizer {

    switch (gestureRecognizer.state) {
        case UIGestureRecognizerStatePossible:
            break;
        case UIGestureRecognizerStateBegan:
        {
            CGPoint location = [gestureRecognizer translationInView:[gestureRecognizer view]];
            _touchRotateStartPoint = [self convertPoint:location fromView:[gestureRecognizer view]];
        }
            break;
        case UIGestureRecognizerStateChanged:
        {
            CGPoint imageLocation = CGPointMake(self.mainImageView.transform.tx + self.mainImageView.center.x
                                                , self.mainImageView.transform.ty + self.mainImageView.center.y);
            CGPoint buttonLocation = [gestureRecognizer translationInView:self];
            buttonLocation.x += _touchRotateStartPoint.x;
            buttonLocation.y += _touchRotateStartPoint.y;

            CGFloat currentRotation = atan2(buttonLocation.y - imageLocation.y, buttonLocation.x - imageLocation.x)
                                        - atan2(_touchRotateStartPoint.y - imageLocation.y, _touchRotateStartPoint.x - imageLocation.x);

            CGFloat rotation = -(_lastRotation - currentRotation);
            CGAffineTransform currentTransform = self.mainImageView.transform;
            CGAffineTransform rotatedTransform = CGAffineTransformRotate(currentTransform, rotation);
            self.mainImageView.transform = rotatedTransform;

            [self setNeedsDisplay];
        }
            break;
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateEnded:
            _lastRotation = 0.0;
            break;
        case UIGestureRecognizerStateFailed:
            break;
        default:
            break;
    }
}

Implemented with pan gesture recogniser, this is using another UIView that the gesture recogniser is attached to but it should work with it attached to the view you want to rotate.

- (void) gestureRotateButtonPan:(UIPanGestureRecognizer*) gestureRecognizer {

    switch (gestureRecognizer.state) {
        case UIGestureRecognizerStatePossible:
            break;
        case UIGestureRecognizerStateBegan:
        {
            CGPoint location = [gestureRecognizer translationInView:[gestureRecognizer view]];
            _touchRotateStartPoint = [self convertPoint:location fromView:[gestureRecognizer view]];
        }
            break;
        case UIGestureRecognizerStateChanged:
        {
            CGPoint imageLocation = CGPointMake(self.mainImageView.transform.tx + self.mainImageView.center.x
                                                , self.mainImageView.transform.ty + self.mainImageView.center.y);
            CGPoint buttonLocation = [gestureRecognizer translationInView:self];
            buttonLocation.x += _touchRotateStartPoint.x;
            buttonLocation.y += _touchRotateStartPoint.y;

            CGFloat currentRotation = atan2(buttonLocation.y - imageLocation.y, buttonLocation.x - imageLocation.x)
                                        - atan2(_touchRotateStartPoint.y - imageLocation.y, _touchRotateStartPoint.x - imageLocation.x);

            CGFloat rotation = -(_lastRotation - currentRotation);
            CGAffineTransform currentTransform = self.mainImageView.transform;
            CGAffineTransform rotatedTransform = CGAffineTransformRotate(currentTransform, rotation);
            self.mainImageView.transform = rotatedTransform;

            [self setNeedsDisplay];
        }
            break;
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateEnded:
            _lastRotation = 0.0;
            break;
        case UIGestureRecognizerStateFailed:
            break;
        default:
            break;
    }
}
苍风燃霜 2024-09-23 04:49:58

使用 PanGestureRecogniser 在 UIView 上进行一指旋转

使用 Swift5 实现全功能代码

import UIKit

class ViewController: UIViewController {
    
    //Variable for rotating
    private var deltaAngle:CGFloat = 0
    
    let squareView : UIView = {
        let anyView = UIView()
        anyView.backgroundColor = .red
        anyView.isUserInteractionEnabled = true
        anyView.isMultipleTouchEnabled = true
        return anyView
        
    }()
    
    let rotateButton : UIButton = {
        let button = UIButton()
        button.backgroundColor = .black
        button.setImage(UIImage(systemName: "rotate.right"), for: .normal)
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        squareView.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
        rotateButton.frame = CGRect(x: 0, y: squareView.frame.height-30, width: 30, height: 30)
        squareView.center = view.center
        view.addSubview(squareView)
        squareView.addSubview(rotateButton)
        
        let PanToRotate = UIPanGestureRecognizer(target: self, action: #selector(handleRotateGesture(_:)))
        rotateButton.addGestureRecognizer(PanToRotate)
        
    }
    
    
    
    
    @objc func handleRotateGesture(_ recognizer : UIPanGestureRecognizer){
        let touchLocation = recognizer.location(in: squareView.superview)
        
        let center = squareView.center
        
        switch recognizer.state{
            
        case .began :
            self.deltaAngle = atan2(touchLocation.y - center.y, touchLocation.x - center.x) - atan2(squareView.transform.b, squareView.transform.a)
            
        case .changed:
            let angle = atan2(touchLocation.y - center.y, touchLocation.x - center.x)
            
            let angleDiff = self.deltaAngle - angle
            
            squareView.transform = CGAffineTransform(rotationAngle: -angleDiff)
                        
        default: break
            
        }
        
    }
    
}

One Finger Rotation on UIView using PanGestureRecogniser

Fully Functional code with Swift5

import UIKit

class ViewController: UIViewController {
    
    //Variable for rotating
    private var deltaAngle:CGFloat = 0
    
    let squareView : UIView = {
        let anyView = UIView()
        anyView.backgroundColor = .red
        anyView.isUserInteractionEnabled = true
        anyView.isMultipleTouchEnabled = true
        return anyView
        
    }()
    
    let rotateButton : UIButton = {
        let button = UIButton()
        button.backgroundColor = .black
        button.setImage(UIImage(systemName: "rotate.right"), for: .normal)
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        squareView.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
        rotateButton.frame = CGRect(x: 0, y: squareView.frame.height-30, width: 30, height: 30)
        squareView.center = view.center
        view.addSubview(squareView)
        squareView.addSubview(rotateButton)
        
        let PanToRotate = UIPanGestureRecognizer(target: self, action: #selector(handleRotateGesture(_:)))
        rotateButton.addGestureRecognizer(PanToRotate)
        
    }
    
    
    
    
    @objc func handleRotateGesture(_ recognizer : UIPanGestureRecognizer){
        let touchLocation = recognizer.location(in: squareView.superview)
        
        let center = squareView.center
        
        switch recognizer.state{
            
        case .began :
            self.deltaAngle = atan2(touchLocation.y - center.y, touchLocation.x - center.x) - atan2(squareView.transform.b, squareView.transform.a)
            
        case .changed:
            let angle = atan2(touchLocation.y - center.y, touchLocation.x - center.x)
            
            let angleDiff = self.deltaAngle - angle
            
            squareView.transform = CGAffineTransform(rotationAngle: -angleDiff)
                        
        default: break
            
        }
        
    }
    
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文