2011-01-12 36 views
8

Hey, tôi đang cố gắng tìm ra cách để tạo ra các đường cong bezier trong iOS dựa trên đầu vào của người dùng. Có bất kỳ lớp học hiện tại cho điều này? Ai đó có thể cho tôi một bản tóm tắt chung về những gì sẽ được yêu cầu? Tôi chỉ cần giúp đỡ để bắt đầu trên chân phải.Vẽ đường cong bezier bằng ngón tay của tôi trong iOS?

+0

Thats những gì bạn cần. Chỉ cần xem hướng dẫn này có tên [Cách xây dựng một ứng dụng vẽ đơn giản cho iOS] (http://blog.effectiveui.com/?p=8105) – fyasar

+2

Có toàn bộ nội dung viết trên blog này của Mike Nachbaur. [Bạn có thể tìm thấy bài đăng ở đây] (http://nachbaur.com/blog/core-animation-part-4), và tất cả là về các đối tượng hoạt hình trên các đường cong bezier do người dùng vẽ. –

+0

Sau đây là bản sao câu trả lời của tôi [về một câu hỏi liên quan] (http://stackoverflow.com/questions/7345251/bezier-path-with-dynamic-change-of-width/11091956#11091956). Tôi đã viết một số chức năng sẽ giúp bạn làm chính xác điều đó. Đọc [thêm về bài đăng của tôi] (http://www.wiggler.gr/2012/06/17/bezier-curves-control-points-calculation-not-only-in-ios/). Mã trên [repo của tôi tại github] (https://github.com/Petrakeas/outlineDEMO). Trong bài đăng của tôi, bạn cũng sẽ tìm thấy [video] (http://www.youtube.com/watch?v=iOHvIiryfaQ) minh họa cách sử dụng các chức năng. – Petrakeas

Trả lời

4

Được rồi, cách dễ nhất để làm điều đó có thể là phân lớp UIView và sử dụng CoreGraphics để vẽ. Kiểm tra mã mẫu từ QuarzDemo. Triển khai drawInRect -method cho lớp xem tùy chỉnh của bạn. Và phát hiện chạm của người dùng với touchesBegan, touchesMoved, vv

Dưới đây là một ví dụ mã (lấy từ QuarzDemo) để vẽ một đường cong Bezier:

// Drawing with a white stroke color 
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); 
// Draw them with a 2.0 stroke width so they are a bit more visible. 
CGContextSetLineWidth(context, 2.0); 

// Draw a bezier curve with end points s,e and control points cp1,cp2 
CGPoint s = CGPointMake(30.0, 120.0); 
CGPoint e = CGPointMake(300.0, 120.0); 
CGPoint cp1 = CGPointMake(120.0, 30.0); 
CGPoint cp2 = CGPointMake(210.0, 210.0); 
CGContextMoveToPoint(context, s.x, s.y); 
CGContextAddCurveToPoint(context, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y); 
CGContextStrokePath(context); 

Hy vọng rằng sẽ giúp bạn bắt đầu;)

+1

phix23: cảm ơn vì câu trả lời cực kỳ hữu ích. Nếu tôi muốn có một đường cong nội suy trơn tru, liệu tôi có cần phát triển một thuật toán cho chính bản thân mình không? Tôi muốn các đường cong được tạo ra bằng cách sử dụng càng ít đỉnh càng tốt. – Brendan

+0

Xin chào @ phix23 vui lòng xem http://stackoverflow.com/questions/20881721/calculate-controlpoints-while-drawing-in-ios và vui lòng cho chuyên gia của bạn tư vấn – Ranjit

10

Nếu bạn muốn ở trong mục tiêu-c, bạn có thể sử dụng phương thức addCurveToPoint: controlPoint1: controlPoint2: của UIBezierPath. Bạn cũng có thể sử dụng chức năng được đặt tên tương tự với CGPath. Khi sử dụng đường cong bezier, bạn cần 4 điểm: điểm bắt đầu, điểm kết thúc và điểm điều khiển ở mỗi đầu để xác định đường cong.

Một cách để xác định điều này là yêu cầu người dùng kéo ngón tay để xác định điểm bắt đầu và điểm kết thúc, sau đó nhấn vào màn hình tại các điểm điều khiển. Đây là một khung nhìn ví dụ để xử lý điều này.

BezierView.h

enum { 
    BezierStateNone = 0, 
    BezierStateDefiningLine, 
    BezierStateDefiningCP1, 
    BezierStateDefiningCP2 
}; 
@interface BezierView : UIView { 
    CGPoint startPt, endPt, cPt1, cPt2; 
    UInt8 state; 
    UIBezierPath *curvePath; 
    @private 
    UITouch *currentTouch; 
} 
@property (nonatomic, retain) UIBezierPath *curvePath; 
@end 

BezierView.m

@interface BezierView 
@dynamic curvePath; 
- (UIBezierPath *)curvePath { 
    return [[curvePath retain] autorelease]; 
} 
- (void)setCurvePath:(UIBezierPath *)newPath { 
    id tmp = curvePath; 
    curvePath = [newPath retain]; 
    [tmp release]; 
    state = BezierStateNone; 
    [self setNeedsDisplay]; 
} 
- (void)_updateCurve { 
    UIBezierPath *path = [UIBezierPath bezierPath]; 
    [path moveToPoint:startPt]; 
    [path addCurveToPoint:endPt controlPoint1:cPt1 controlPoint2:cPt2]; 
} 
- (void)_calcDefaultControls { 
    if(ABS(startPt.x - endPt.x) > ABS(startPt.y - endPt.y)) { 
     cPt1 = (CGPoint){(startPt.x + endPt.x)/2, startPt.y}; 
     cPt2 = (CGPoint){cPt1.x, endPt.y}; 
    } else { 
     cPt1 = (CGPoint){startPt.x, (startPt.y + endPt.y)/2}; 
     cPt2 = (CGPoint){endPt.x, cPt1.y}; 
    } 
} 
- (void)drawRect:(CGRect)rect { 
    UIBezierPath *path = self.curvePath; 
    if(path) [path stroke]; 
} 
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    if(currentTouch) return; 
    if(state == BezierStateNone) { 
     state = BezierStateDefiningLine; 
     currentTouch = [touches anyObject]; 
     startPt = [currentTouch locationInView:self]; 
    } else if(state == BezierStateDefiningCP1) { 
     currentTouch = [touches anyObject]; 
     cPt1 = [currentTouch locationInView:self]; 
     [self _updateCurve]; 
    } else if(state == BezierStateDefiningCP2) { 
     currentTouch = [touches anyObject]; 
     cPt2 = [currentTouch locationInView:self]; 
     [self _updateCurve]; 
    } 
} 
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    if(!currentTouch) return; 
    if(state == BezierStateDefiningLine) { 
     endPt = [currentTouch locationInView:self]; 
     [self _calcDefaultControls]; 
     [self _updateCurve]; 
    } else if(state == BezierStateDefiningCP1) { 
     cPt1 = [currentTouch locationInView:self]; 
     [self _updateCurve]; 
    } else if(state == BezierStateDefiningCP2) { 
     cPt2 = [currentTouch locationInView:self]; 
     [self _updateCurve]; 
    } 
} 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    if(!currentTouch) return; 
    if(state == BezierStateDefiningLine) { 
     state = BezierStateDefiningCP1; 
    } else if(state == BezierStateDefiningCP1) { 
     state = BezierStateDefiningCP2; 
    } else if(state == BezierStateDefiningCP2) { 
     state = BezierStateNone; 
    } 
    currentTouch = nil; 
} 
- (void)touchesCanceled:(NSSet *)touches withEvent:(UIEvent *)event { 
    if(state == BezierStateDefiningLine) { 
     self.curvePath = nil; 
     self.state = BezierStateNone; 
    } 
    self.currentTouch = nil; 
} 
+0

nó không vẽ bất kỳ điều gì :( – ColdSteel

Các vấn đề liên quan