Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
225 views
in Technique[技术] by (71.8m points)

ios - Restricting pan gesture to move to 90 degree

If I have created a line for ex. shown in the figure as connecting A and B through CAShapeLayer and in that line's centre I have a UIView which has pan gesture integrated in it.

How to make that UIView to move to a certain direction that creates 90 degrees to that line as shown in the figure the red line indicated the direction that the UIView can be moved?

The mid-point should start moving from the centre of the line, in the direction that shown in the figure that I have updated.

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I assume you can handle the pan, and you are able to get the touch point. What you want is to calculate the projection of the touch point to the red line and place the UIView there.

The red line is perpendicular to AB and consist the midpoint of 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

UPDATE:

Your comment reveals, that the utilization of this soulution is not clear enough for you. Therefore I have embedded this idea into a working example.

@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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...