2013-01-07 40 views
2

我想用我的手指畫出一條直線,並根據我離原點的距離自動調整大小。拉伸UIBezierPath線?

因此,如果我在中間觸摸屏幕並將手指滑出,則會出現「伸展」線條,並隨着手指在屏幕上移動而圍繞orgin點旋轉。當我擡起我的手指。目標點應完成並創建一條線。我可以將手指拖過屏幕並在屏幕上「繪製」,但這不是我想要做的。

我以爲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

這應該證明的基本思想:

​​

或者,斯威夫特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爲零? – JasonBourne

+0

爲什麼這麼複雜? – JasonBourne

+1

@Rob修正了我的錯字。 – benzado