2013-01-07 9 views
2

원점에서 얼마나 멀리 떨어져 있는지에 따라 자동으로 크기가 조정되는 손가락으로 직선을 그려야합니다.스트레치 UIBezierPath 라인?

중간에 화면을 터치하고 손가락을 밀어 내면 화면에서 손가락이 움직이면서 선이 '늘어나고'피벗 (orgin) 지점을 중심으로 선회합니다. 내가 손가락을 들어 올렸을 때. Destination Point는 완성되어 라인을 만들어야합니다. 화면에서 손가락을 드래그하여 화면에 '그리기'할 수는 있지만 원하는 것은 아닙니다.

UIBeizerPath moveToPoint 도움이 될 것이라고 생각하지만 그냥 물건을 망칠.

내가 뭘 잘못하고 있니?

- (id)initWithFrame:(CGRect)frame 
{ 
    //default line properties 
    myPath=[[UIBezierPath alloc]init]; 
    myPath.lineCapStyle=kCGLineCapRound; 
    myPath.miterLimit=0; 
    myPath.lineWidth=lineWidth; 
    brushPattern=[UIColor blackColor]; 
} 



-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    CGPoint curPoint = [[touches anyObject] locationInView:self]; 

    lastPoint = curPoint; 

    [myPath moveToPoint:lastPoint]; 
    [pathArray addObject:myPath]; 
    [self setNeedsDisplay]; 
} 

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

    CGPoint curPoint = [[touches anyObject] locationInView:self]; 

    myPath.lineWidth=lineWidth; 
    brushPattern=[UIColor redColor]; //red to show it hasn't been added yet. 
    [myPath moveToPoint:tempPoint]; 
    [self setNeedsDisplay]; 
} 

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

    CGPoint curPoint = [[touches anyObject] locationInView:self]; 

    myPath.lineWidth=lineWidth; 

    brushPattern=[UIColor blackColor]; //finalize the line with black color 
    [myPath addLineToPoint:curPoint]; 
    [self setNeedsDisplay]; 
} 

답변

3

하나의 개념이 있습니다. 손가락을 드래그하여 시작하는 위치에서부터 손가락을 드래그 할 때까지 움직이는 위치까지 선을 그립니다. CAShapeLayer을 작성하고 손가락을 움직일 때 path을 재설정하면됩니다.

이것은 기본 개념 증명해야합니다

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; 
    [self.view addGestureRecognizer:gesture]; 
} 

- (CAShapeLayer *)createShapeLayer:(UIView *)view { 
    CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init]; 

    shapeLayer.fillColor = [UIColor clearColor].CGColor; 
    shapeLayer.strokeColor = [UIColor redColor].CGColor; 
    shapeLayer.lineWidth = 3.0; 

    [view.layer addSublayer:shapeLayer]; 

    return shapeLayer; 
} 

- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture { 
    static CAShapeLayer *shapeLayer; 
    static CGPoint origin; 

    if (gesture.state == UIGestureRecognizerStateBegan) { 
     shapeLayer = [self createShapeLayer:gesture.view]; 
     origin = [gesture locationInView:gesture.view]; 
    } else if (gesture.state == UIGestureRecognizerStateChanged) { 
     UIBezierPath *path = [UIBezierPath bezierPath]; 
     [path moveToPoint:origin]; 
     CGPoint location = [gesture locationInView:gesture.view]; 
     [path addLineToPoint:location]; 
     shapeLayer.path = path.CGPath; 
    } else if (gesture.state == UIGestureRecognizerStateEnded || 
       gesture.state == UIGestureRecognizerStateFailed || 
       gesture.state == UIGestureRecognizerStateCancelled) { 
     shapeLayer = nil; 
    } 
} 

을 또는 스위프트 3 :

override func viewDidLoad() { 
    super.viewDidLoad() 

    let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) 
    view.addGestureRecognizer(pan) 
} 

private func createShapeLayer(for view: UIView) -> CAShapeLayer { 
    let shapeLayer = CAShapeLayer() 
    shapeLayer.fillColor = UIColor.clear.cgColor 
    shapeLayer.strokeColor = UIColor.red.cgColor 
    shapeLayer.lineWidth = 3.0 

    view.layer.addSublayer(shapeLayer) 

    return shapeLayer 
} 

private var shapeLayer: CAShapeLayer! 
private var origin: CGPoint! 

func handlePan(_ gesture: UIPanGestureRecognizer) { 
    if gesture.state == .began { 
     shapeLayer = createShapeLayer(for: gesture.view!) 
     origin = gesture.location(in: gesture.view) 
    } else if gesture.state == .changed { 
     let path = UIBezierPath() 
     path.move(to: origin) 
     path.addLine(to: gesture.location(in: gesture.view)) 
     shapeLayer.path = path.cgPath 
    } else if gesture.state == .ended || gesture.state == .failed || gesture.state == .cancelled { 
     shapeLayer = nil 
    } 
} 

당신이 CAShapeLayer를 사용하지 않는 경우,하지만 당신은 이전의 트랙을 유지하려면 경로를 만들려면 이전 경로에 대한 배열을 유지해야하며 다음과 같은 이전 경로로 구성된 경로를 작성해야합니다.

@interface CustomView() 

@property (nonatomic) CGPoint originPoint; 
@property (nonatomic) CGPoint currentPoint; 
@property (nonatomic) NSMutableArray *previousPaths; 

@end 

@implementation CustomView 

- (id)initWithFrame:(CGRect)frame { 
    self = [super initWithFrame:frame]; 
    if (self) { 
     [self configure]; 
    } 
    return self; 
} 

- (id)init { 
    return [self initWithFrame:CGRectZero]; 
} 

- (id)initWithCoder:(NSCoder *)aDecoder { 
    self = [super initWithCoder:aDecoder]; 
    if (self) { 
     [self configure]; 
    } 
    return self; 
} 

- (void)configure { 
    _previousPaths = [[NSMutableArray alloc] init]; 
} 

- (void)drawRect:(CGRect)rect { 
    [[UIColor redColor] setStroke]; 

    UIBezierPath *drawPath = [UIBezierPath bezierPath]; 

    drawPath.lineCapStyle = kCGLineCapRound; 
    drawPath.miterLimit = 0; 
    drawPath.lineWidth = 3.0; 

    for (UIBezierPath *path in self.previousPaths) 
     [drawPath appendPath:path]; 

    UIBezierPath *path = [self pathForCurrentLine]; 
    if (path) 
     [drawPath appendPath:path]; 

    [drawPath stroke]; 
} 

- (UIBezierPath *)pathForCurrentLine { 
    if (CGPointEqualToPoint(self.originPoint, CGPointZero) && CGPointEqualToPoint(self.currentPoint, CGPointZero)) 
     return nil; 

    UIBezierPath *path = [UIBezierPath bezierPath]; 
    [path moveToPoint:self.originPoint]; 
    [path addLineToPoint:self.currentPoint]; 

    return path; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    self.originPoint = [[touches anyObject] locationInView:self]; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    if ([event respondsToSelector:@selector(predictedTouchesForTouch:)]) { 
     touch = [[event predictedTouchesForTouch:touch] lastObject] ?: touch; 
    } 
    self.currentPoint = [touch locationInView:self]; 

    [self setNeedsDisplay]; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    self.currentPoint = [[touches anyObject] locationInView:self]; 
    [self.previousPaths addObject:[self pathForCurrentLine]]; 
    self.originPoint = self.currentPoint = CGPointZero; 

    [self setNeedsDisplay]; 
} 

@end 
+0

고마워요. 배열에 저장하고 다시 그립니다. 미래에 나올 수있는 기회가 언제 생길까요? – JasonBourne

+0

나는 어떤 이슈도 상상할 수 없다. 거기에별로 없습니다! 그러나 당신은 기본적인 문제를 가지고 있습니다. 그래서 미래의 다른 구현을 추구해야한다면, 당신은 잘 무장하고 있습니다. – Rob

+0

귀하의 모든 도움에 감사드립니다! 그것은 나를 미치게했다! – JasonBourne

2

UIBezierPath가 지침에 따라 경로를 작성 중입니다. 펜을 상상해보십시오. "moveToPoint :"라고 말하면 펜이 그 지점으로 이동합니다. "lineToPoint :"라고 말하면 펜을 내려 놓고 현재 위치에서 새 지점으로 펜을 이동합니다. 등등.

원하는 효과를 얻으려면 터치가 움직일 때마다 원본 경로에서 현재 터치 위치까지 선을 그릴 때마다 새 경로를 만들어야합니다.

+0

그래서 touchesEnded에서 myPath를 nil로 설정해야합니까? – JasonBourne

+0

왜 이렇게 복잡한가요? – JasonBourne

+1

@Rob 오타가 수정되었습니다. – benzado