2012-06-22 17 views
6

Tôi có vấn đề để triển khai "Hiệu ứng đổ bóng/đổ bóng" trong bản vẽ của tôi. chức năng sơn ngón tay hiện đang làm việc tốt với tùy chỉnh của tôi UIView và dưới đây là mã drawRect phương pháp của tôi:Cách tạo hiệu ứng nổi hoặc bóng bằng cách sử dụng Đồ họa lõi (để vẽ bằng ngón tay)

Chỉnh sửa mã với tất cả các phương pháp:

- (void)drawRect:(CGRect)rect 
{ 
    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); 
    CGContextSaveGState(context); 

    // for shadow effects 
    CGContextSetShadowWithColor(context, CGSizeMake(0, 2),3, self.lineColor.CGColor); 
    CGContextStrokePath(context); 
    [super drawRect:rect]; 
} 

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]; 
} 

-(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]; 

} 

khi tôi đã thực hiện điều này tôi đang nhận được hiệu ứng sơn với dấu chấm dot dot ...

Xem hình ảnh bên dưới (không có bất kỳ hiệu ứng đổ bóng hoặc dập nổi nào). Nếu bạn có bất kỳ ý tưởng làm thế nào để thêm các hiệu ứng này, xin vui lòng cho tôi một số gợi ý. Làm thế nào tôi có thể giải quyết điều này?

enter image description here

Trả lời

4

Có vẻ như bạn đang tạo hàng trăm, thậm chí hàng ngàn con đường riêng biệt, một ngày mỗi drawRect. Bạn làm phẳng những cái này bằng cách sử dụng [self.layer renderInContext] nhưng tôi không nghĩ đó là một cách tốt để đi về nó. Thay vào đó, tôi nghĩ rằng những gì bạn muốn làm là tạo một UIBezierPath để theo dõi ngón tay, nối thêm đường dẫn đến đó và vẽ UIBezierPath vào màn hình. Nếu bạn tạo hai lớp (hoặc xem), bạn có thể thiết lập một lớp (trong suốt) để "vẽ" lên. Khi người dùng nhấc ngón tay của họ lên, sau đó bạn đưa toàn bộ UIBezierPath lên lớp thứ hai (cùng với dữ liệu đã vẽ trước đó) và tạo một UIBezierPath mới để vẽ theo dõi ngón tay tiếp theo. Bằng cách này, bạn chỉ cập nhật một lớp (lớp trên cùng) khi bạn đang theo dõi ngón tay của ai đó. Điều này sẽ giúp ngăn thiết bị làm chậm quá trình vẽ quá nhiều đường dẫn.

Mặc dù, tôi sẽ nói, phương pháp hiện tại của bạn tạo ra hiệu ứng "3D" thú vị.

+0

tôi đánh giá cao đề xuất của bạn. tôi đã sử dụng UIBezierPath và thực hiện nó nhưng chúng tôi phải đối mặt với một số vấn đề như xóa chức năng và chọn màu sắc khác nhau của sơn .. vì vậy cuối cùng tất cả tôi đã thay đổi chức năng và sử dụng CGContext. Bây giờ tất cả các chức năng như Erase, thay đổi màu sắc của bàn chải đang làm việc tốt. Phát hành chỉ là để tạo ra hiệu ứng Emboss hoặc bóng tối. mà hiệu ứng không hoạt động đúng cách .. straigh dòng làm việc tốt với hiệu ứng bóng. nhưng hiệu ứng đường cong (mịn) không làm việc tốt. plz cho tôi biết một số suggeetion bằng cách sử dụng CGContext. – Hitarth

+0

Câu hỏi nhanh: Bạn muốn Erase hoạt động như thế nào? Hầu hết các chương trình 'vẽ' sẽ xóa từng 'đường dẫn' riêng biệt (như được định nghĩa là sự kiện chạm/kéo/kết thúc bằng một ngón tay). Điều này làm việc với đề xuất/câu trả lời của tôi. Tuy nhiên, nếu bạn đang cố gắng xóa từng điểm của đường dẫn hoặc thậm chí mỗi pixel .... sẽ khó thực hiện hơn nhiều. –

+0

i m xoá bằng ngữ cảnh hiện tại. và nó hoạt động tốt. – Hitarth

0

Tôi không chắc chắn về dập nổi, nhưng nếu những gì bạn muốn là áp dụng bóng đổ cho bản vẽ được cập nhật dần dần, thì cách tiếp cận tốt đẹp sẽ là sử dụng CALayers (link to a tutorial). Về cơ bản, bản vẽ tiến bộ của bạn sẽ cập nhật hình ảnh trong suốt (không cố vẽ bất kỳ bóng nào trong hình ảnh này) và hình ảnh này sẽ được định cấu hình để hiển thị với bóng đổ qua CALayer của nó.

0

Bóng được tạo trên đường viền và bạn đang vẽ các đoạn đường nhỏ và điều này tạo ra hiệu ứng này. Bạn cần phải tạo ra một con đường và sau đó đột quỵ nó một lần. Mã này có thể giúp bạn :)

for (int i=0; i<[currentPath count]; i++) 
{ 
    CGPoint mid1 = [[self midPoint:[currentPath objectAtIndex:i+1] :[currentPath objectAtIndex:i]] CGPointValue]; 
    CGPoint mid2 = [[self midPoint:[currentPath objectAtIndex:i+2] :[currentPath objectAtIndex:i+1]] CGPointValue]; 
    CGContextMoveToPoint(context, mid1.x, mid1.y); 
    CGContextAddQuadCurveToPoint(context, [[currentPath objectAtIndex:i+1] CGPointValue].x, [[currentPath objectAtIndex:i+1] CGPointValue].y, mid2.x, mid2.y); 
    CGContextSetShadow(context, CGSizeMake(-2, -2), 3); 

    CGContextSetLineCap(context, kCGLineCapRound); 
    CGContextSetStrokeColorWithColor(context,[color CGColor]);    
    CGContextSetLineWidth(context, linewidth);    

    i+=2; 
} 
CGContextStrokePath(context); 

Hãy thử cách này .. Cách giải quyết này có thể giải quyết vấn đề của bạn .. Đầu tiên tạo đường dẫn ur và sau khi được tạo xong, hãy vuốt nó. Điều này xảy ra kể từ khi ở mỗi dòng nhỏ bạn đột quỵ và do đó bóng tạo ra làm cho một dấu chấm trên giới hạn của nó, vì vậy bạn sẽ có được hiệu ứng này.

+0

CurrntPath trong mã của bạn là gì và tại sao bạn sử dụng vòng lặp? không nhận được .. plz xem mã nguồn đầy đủ của tôi (chỉnh sửa). – Hitarth

+0

Tôi đang tạo một mảng các điểm, đường dẫn hiện tại là mảng đó. Mảng này được tạo ra với các điểm, nhìn chằm chằm từ chạm bắt đầu để kết thúc :) – DivineDesert