限制平移手势移动到 90 度

Restricting pan gesture to move to 90 degree

如果我为 ex 创建了一条线。如图所示,通过 CAShapeLayer 连接 A 和 B,在那条线的中心我有一个 UIView,其中集成了平移手势。

如何使UIView移动到与该线成90度的某个方向,如图所示,红线表示UIView可以移动的方向?

中点应该从线的中心开始移动,按照我更新的图中所示的方向。

我假设你能拿得动盘子,而且你能得到接触点。您想要的是计算触摸点到红线的投影并将 UIView 放在那里。

红线垂直于AB,是AB的中点

//
//when the pan gesture recognizer reports state change event

/*you have 
    CGPoint A;
    CGPoint B;
    CGPoint T; //touch point
*/

//midpoint
CGPoint M = {(A.x+B.x)/2, (A.y+B.y)/2}; 

//AB distance
CGFloat distAB = sqrtf(powf(B.x-A.x, 2) + powf(B.y-A.y, 2));

//direction of the red line with unit length
CGVector v = {(B.y-A.y)/distAB, -(B.x-A.x)/distAB};

// vector from midpoint to touch point
CGVector MT = {T.x-M.x, T.y-M.y};

// dot product of v and MT
// which is the signed distance of the projected point from M
CGFloat c = v.dx*MT.dx + v.dy*MT.dy;

// projected point is M + c*v
CGPoint projectedPoint = {M.x + c*v.dx, M.y + c*v.dy};

//TODO: set the center of the moving UIView to projectedPoint

更新:

您的评论表明,您对这个解决方案的使用还不够清楚。因此,我将这个想法嵌入到一个工作示例中。

@interface ViewController ()

@end

@implementation ViewController {
    CGPoint A;
    CGPoint B;
    CGPoint M; //midpoint of AB
    CGVector v; //direction of the red line with unit length

    UIView* pointMover;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    A = CGPointMake(50,50);
    B = CGPointMake(300,200);

    M = CGPointMake((A.x+B.x)/2, (A.y+B.y)/2);
    CGFloat distAB = sqrtf(powf(B.x-A.x, 2) + powf(B.y-A.y, 2));
    v = CGVectorMake((B.y-A.y)/distAB, -(B.x-A.x)/distAB);

    pointMover = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
    pointMover.center = M;
    pointMover.backgroundColor = [UIColor blueColor];
    pointMover.layer.cornerRadius = 22.0f;
    [self.view addSubview:pointMover];

    UIPanGestureRecognizer* panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [pointMover addGestureRecognizer:panRecognizer];

    UIBezierPath* blackLinePath = [UIBezierPath bezierPath];
    [blackLinePath moveToPoint:A];
    [blackLinePath addLineToPoint:B];
    CAShapeLayer *blackLineLayer = [CAShapeLayer layer];
    blackLineLayer.path = [blackLinePath CGPath];
    blackLineLayer.strokeColor = [[UIColor blackColor] CGColor];
    blackLineLayer.lineWidth = 2.0;
    [self.view.layer addSublayer:blackLineLayer];


}

- (void)handlePan:(UIPanGestureRecognizer*)recognizer {

    //touch point
    CGPoint T = [recognizer locationInView:self.view];

    // vector from midpoint to touch point
    CGVector MT = {T.x-M.x, T.y-M.y};

    // dot product of v and MT
    CGFloat c = v.dx*MT.dx + v.dy*MT.dy;

    // projected point is M + c*v
    CGPoint projectedPoint = {M.x + c*v.dx, M.y + c*v.dy};

    pointMover.center = projectedPoint;
}


@end