2012-06-20 29 views
10

Sử dụng đồ họa lõi, tôi đang cố gắng vẽ một đường, trong đó khi tôi cố gắng thêm bóng được tạo ra lin và bong bóng bên trong dòng, xem hình ảnh, tôi không có thể giải quyết vấn đề. vui lòng tìm mã của tôi bên dướivấn đề trong dòng vẽ bằng cách sử dụng đồ họa cốt lõi: bong bóng được hiển thị

-(void)drawRect:(CGRect)rect 
{ 

    [curImage drawAtPoint:CGPointMake(0, 0)]; 
    CGPoint mid1 = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2 = midPoint(currentPoint, previousPoint1); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    [self.layer renderInContext:context]; 

    CGContextMoveToPoint(context, mid1.x, mid1.y); 
    CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
    CGContextSetLineCap(context, kCGLineCapRound); 
    CGContextSetLineWidth(context, self.lineWidth); 
    CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 

    CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f); 

    CGContextStrokePath(context); 

    [super drawRect:rect]; 

    [curImage release]; 

} 

Dưới đây là phương pháp touchesMoved.

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

    UITouch *touch = [touches anyObject]; 

    previousPoint2 = previousPoint1; 
    previousPoint1 = [touch previousLocationInView:self]; 
    currentPoint = [touch locationInView:self]; 

    // calculate mid point 
    CGPoint mid1 = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2 = midPoint(currentPoint, previousPoint1); 

    CGMutablePathRef path = CGPathCreateMutable(); 
    CGPathMoveToPoint(path, NULL, mid1.x, mid1.y); 
    CGPathAddQuadCurveToPoint(path, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
    CGRect bounds = CGPathGetBoundingBox(path); 
    CGPathRelease(path); 

    CGRect drawBox = bounds; 

    //Pad our values so the bounding box respects our line width 
    drawBox.origin.x  -= self.lineWidth * 2; 
    drawBox.origin.y  -= self.lineWidth * 2; 
    drawBox.size.width  += self.lineWidth * 4; 
    drawBox.size.height  += self.lineWidth * 4; 

    UIGraphicsBeginImageContext(drawBox.size); 
    [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    curImage = UIGraphicsGetImageFromCurrentImageContext(); 
    [curImage retain]; 
    UIGraphicsEndImageContext(); 
    [self setNeedsDisplayInRect:drawBox]; 

} 

CGPoint midPoint(CGPoint p1, CGPoint p2) 
{ 
    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); 
} 


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

    UITouch *touch = [touches anyObject]; 

    previousPoint1 = [touch previousLocationInView:self]; 
    previousPoint2 = [touch previousLocationInView:self]; 
    currentPoint = [touch locationInView:self]; 

    [self touchesMoved:touches withEvent:event]; 
} 

Ở đây vấn đề này đến khi tôi cố gắng thêm dòng

CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f); 

Issue image

Xin hãy giúp tôi ra khỏi vấn đề này, cảm ơn trước. vui lòng xem câu hỏi chỉnh sửa bằng các phương pháp.

Trả lời

8

Có vẻ như bạn đang vẽ một loạt phân đoạn dưới dạng đường cong bốn chiều. Các bong bóng sẽ là nơi phân khúc trước đó và phân đoạn hiện tại trùng lặp. Vì đường phân đoạn của bạn là một màu đỏ đặc, bạn không nhận thấy sự chồng chéo, nhưng nó xuất hiện trong bóng tối như các vùng tối hơn.

Thử đặt màu stroke của bạn thành alpha và 0,5 (hoặc một số độ mờ như vậy). Tôi nghĩ (biết) bạn sẽ thấy các phân đoạn chồng chéo cũng sẽ hiển thị một hiệu ứng tương tự như bóng đổ.

Để giải quyết vấn đề này, bạn sẽ muốn vẽ phân khúc đó dưới dạng đường dẫn liên tục cho mỗi dòng. Tôi đoán bạn đang sử dụng touchesBegan:withEvent:/touchesMoved:withEvent/touchesEnded:withEvent: để có được điểm của các đường?

Trong trường hợp đó, khi touchesBegan:withEvent: được gọi, hãy bắt đầu đường dẫn mới của bạn. Trong khi touchesMoved:withEvent hiển thị đường dẫn mới trên hình ảnh hiện tại. Cam kết đường dẫn đến số UIImage trong touchesEnded:withEvent:. Tại thời điểm này, bạn có thể hủy đường dẫn cho đến khi touchesBegan:withEvent: được gọi lại với đột quỵ tiếp theo.

Cập nhật

Trong đoạn mã của bạn, bạn kết thúc render toàn bộ xem ba lần mỗi chạy vòng lặp. Đó là rất nhiều chi phí vẽ. Tôi nhanh chóng tập hợp một số mã để chứng minh những gì tôi đang nói ở trên. Nó không phải là kiểm tra mã, nhưng nó phải là chủ yếu phải:

Cập nhật 2

Tôi đã có một chút thời gian để viết và kiểm tra một số mã mà sẽ làm những gì bạn đang tìm kiếm dựa trên mới nhất hai ý kiến ​​của tôi . Mã này là từ trình điều khiển chế độ xem thay vì chính chế độ xem, nhưng với một chút sửa đổi, bạn có thể di chuyển trong chế độ xem nếu muốn. Như vậy, tôi đã thêm UIImageView làm chế độ xem phụ vào số UIView chung để giữ và hiển thị hình ảnh (và duy trì tham chiếu đến trong trình điều khiển chế độ xem) và đặt bộ điều khiển chế độ xem trả lời đầu tiên để nhận sự kiện chạm. Rất nhiều giá trị được mã hóa cứng mà bạn có thể dọn sạch khi tích hợp vào dự án của riêng mình:

static 
UIImage *CreateImage(CGRect rect, NSArray *paths) 
{ 
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1.0); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGFloat colorComponents[4] = {0.0,0.0,0.0,0.0}; 
    CGContextSetFillColor(context, colorComponents); 
    CGContextFillRect(context, rect); 

    for (id obj in paths) { 
     CGPathRef path = (CGPathRef)obj; 
     CGContextAddPath(context, path); 
    }  
    CGContextSetStrokeColorWithColor(context, [[UIColor redColor] CGColor]); 
    CGContextSetLineCap(context, kCGLineCapRound); 
    CGContextSetLineWidth(context, 5.0); 
    CGContextSetShadow(context, (CGSize){-8.0,40}, 5.0); 
    CGContextBeginTransparencyLayer(context, NULL); 

    CGContextDrawPath(context, kCGPathStroke); 

    CGContextEndTransparencyLayer(context); 

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return image; 
} 

static 
CGPoint MidPoint(CGPoint pt1, CGPoint pt2) 
{ 
    return (CGPoint){(pt1.x+pt2.x)/2.0,(pt1.y+pt2.y)/2.0}; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesBegan:touches withEvent:event]; 
    CGPoint location = [[touches anyObject] locationInView:self.view]; 
    myPath = CGPathCreateMutable(); 
    CGPathMoveToPoint(myPath, NULL, location.x, location.y); 

    [self.paths addObject:(id)myPath]; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesMoved:touches withEvent:event]; 
    UITouch *touch = [touches anyObject]; 
    CGPoint previousLocation = [touch previousLocationInView:self.view]; 
    CGPoint location = [touch locationInView:self.view]; 
    CGPoint midPoint = MidPoint(previousLocation, location); 
    CGPathAddQuadCurveToPoint(myPath, NULL, midPoint.x, midPoint.y, location.x, location.y); 

    self.imageView.image = CreateImage(self.view.bounds, self.paths); 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesEnded:touches withEvent:event]; 
    UITouch *touch = [touches anyObject]; 
    CGPoint previousLocation = [touch previousLocationInView:self.view]; 
    CGPoint location = [touch locationInView:self.view]; 
    CGPoint midPoint = MidPoint(previousLocation, location); 
    CGPathAddQuadCurveToPoint(myPath, NULL, midPoint.x, midPoint.y, location.x, location.y); 

    self.imageView.image = CreateImage(self.view.bounds, self.paths); 

    CGPathRelease(myPath); 
    myPath = nil; 
} 
+0

cảm ơn sự giúp đỡ, nhưng tôi không thể xác định chính xác điểm của bạn. vì đây là chủ đề hoàn toàn mới đối với tôi. –

+1

Đủ công bằng. Khi người dùng di chuyển ngón tay của họ tạo ra đột quỵ tổng thể, một loạt các điểm được ghi lại (một trong mỗi chu kỳ vòng lặp chạy). Bạn dường như chỉ ghi lại điểm trước đó và hiện tại để ghi lại vào 'UIImage' mới của bạn. Thay vào đó, hợp nhất tất cả các điểm được tạo ra giữa thông điệp 'touchesBegan: withEvent:' và 'touchesEnded: withEvent:', chuyển đổi chúng thành đường dẫn (hoặc CGPath hoặc UIBezierPath) ** sau ** người dùng đã nhấc ngón tay của họ lên ('touchesEnded: withEvent:'), và thực hiện cú đánh đầy đủ tới 'UIImage' mới của bạn. Các nhận xét của @ relikd về các lớp trong suốt cũng tốt. – gschandler

+0

Cảm ơn bạn đã giúp mã, mã của bạn là thích hợp nhưng nó sẽ tạo ra các bản vẽ ở cuối cảm ứng, Và tôi cần phải vẽ đường với chuyển động của người dùng của ngón tay, Vì vậy, tôi đang cố gắng để thay đổi mã den cho u biết những gì là kết quả. –

4

vấn đề là bạn có nhiều dòng nằm trên nhau. Vì vậy, các bóng của cả hai chồng lên nhau và bạn sẽ có được một màu tối hơn.

Đối với những thứ dễ dàng như bản vẽ đường, bạn có thể chỉ cần sao chép toàn bộ mã vẽ và vẽ lại với màu khác và bù pixel điểm ảnh (thay vì bóng). Ví dụ. bạn lưu các đường cong vào một mảng và vẽ chúng một cách riêng biệt sau đó.

CHỈNH SỬA:
ok @gschandler cũng mô tả sự cố tuyệt vời.

Nhưng bạn cũng có thể muốn xem tài liệu Transparency Layer. Nhóm các phần tử lại với nhau và áp dụng một bóng cho nhóm.

2

Một cách khác để vòng này là tạo ra một loạt các điểm trên các sự kiện liên lạc di chuyển, và sau đó lôi kéo họ ..

Tạo một mảng các điểm:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
[pointArray release]; pointArray = nil; 
pointArray=[[NSMutableArray alloc] init]; 
UITouch *touch = [touches anyObject]; 
[bufferArray removeAllObjects]; 

previousPoint1 = [touch previousLocationInView:self]; 
previousPoint2 = [touch previousLocationInView:self]; 
currentPoint = [touch locationInView:self]; 

} 


-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
UITouch *touch = [touches anyObject]; 
previousPoint2 = previousPoint1; 
previousPoint1 = [touch previousLocationInView:self]; 
currentPoint = [touch locationInView:self]; 
[pointArray addObject: [NSValue valueWithCGPoint:previousPoint2]]; 
[pointArray addObject:[NSValue valueWithCGPoint:previousPoint1]]; 
[pointArray addObject:[NSValue valueWithCGPoint:currentPoint]]; 
[self setNeedsDisplay]; 
} 

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

} 


-(void)drawRect:(CGRect)rect 
{ 
CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextSetLineCap(context, kCGLineCapRound); 
CGContextSetLineWidth(context, self.lineWidth); 
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 

CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f); 

for(int i = 1 ; i < [pointArray count]-1;i++) 
{ 
CGPoint mid1 = midPoint([pointArray objectAtIndex:i+1], [pointArray objectAtIndex:i]); 
CGPoint mid2 = midPoint([pointArray objectAtIndex:i+2], [pointArray objectAtIndex:i+1]); 


CGContextMoveToPoint(context, mid1.x, mid1.y); 
CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
i+=2; 
} 
CGContextStrokePath(context); 

} 

Bạn có thể quản lý nhiều dòng với mảng nhiều chiều :)

+0

Hi Dimple, Cảm ơn bạn đã trả lời nhưng mã đang bị lỗi tại vòng lặp, điểm mid2, giá trị chỉ mục âm thanh có vấn đề logic. Khi tôi đã thử với gỡ lỗi, nó đã bị rơi tại [pointArray objectAtIndex: i + 2] vì không có đối tượng tại chỉ mục đó, xin vui lòng chia sẻ như thế nào phần này là làm việc !! –

+0

xin vui lòng thêm i + = 2 trong vòng lặp, vì chúng tôi đang sử dụng 4 điểm tại một thời điểm, chúng tôi cần điều này. – DivineDesert

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