【问题标题】:Restricting pan gesture to move to 90 degree限制平移手势移动到 90 度
【发布时间】:2016-05-19 13:33:29
【问题描述】:

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

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

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

【问题讨论】:

    标签: ios objective-c line uibezierpath cashapelayer


    【解决方案1】:

    我假设您可以处理平底锅,并且您能够获得接触点。您想要的是计算触摸点到红线的投影并将 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
    

    【讨论】:

    • 可能你误解了我的担心,重点应该是从行的中间开始移动,你可以在更新的问题中看到。
    • 当用户将中点放在某个点并再次开始重新定位然后从那里开始而不是从中点的中心开始。
    猜你喜欢
    • 1970-01-01
    • 2012-08-16
    • 2017-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-27
    • 2018-02-09
    • 1970-01-01
    相关资源
    最近更新 更多