2012-06-22 16 views
6

Mam problem z zaimplementowaniem "Efektów wytłoczeń/cieni" na moim rysunku. Funkcjonalność farba palec obecnie pracuje w porządku z moim zwyczajem UIView i poniżej jest mój kod drawRect metoda:Tworzenie wytłoczonych lub cieniowanych efektów za pomocą grafiki głównej (do malowania palcami)

Edycja kodu ze wszystkich metod:

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

} 

kiedy wdrożyły ten otrzymuję efektów malarskich z kropką kropka kropka ...

Zobacz poniżej zdjęcie (które nie ma cienia ani efektów wytłaczanych). Jeśli masz pojęcie, jak dodać te efekty, daj mi trochę sugestii. Jak mogę to rozwiązać?

enter image description here

Odpowiedz

4

Wydaje się, że tworzysz setki, może nawet tysiące oddzielnych ścieżek, po jednej na każdym drawRect. Spłaszczasz je przy użyciu [self.layer renderInContext], ale nie sądzę, że to dobry sposób, aby to osiągnąć. Zamiast tego, myślę, że chcesz utworzyć jedną ścieżkę UIBezierPath, aby śledzić palec, dołączać do niej ścieżki i narysować UIBezierPath na ekranie. Jeśli utworzysz dwie warstwy (lub widoki), możesz ustawić górny (przezroczysty) na "rysuj". Kiedy użytkownik podnosi palec, renderujesz całą ścieżkę UIBezierPath do drugiej warstwy (wraz z poprzednio narysowanymi danymi) i tworzysz nową ścieżkę UIBezierPath, aby narysować następne śledzenie palcem. W ten sposób aktualizujesz tylko jedną warstwę (górną) podczas śledzenia czyjegoś palca. Pomoże to zapobiec spowolnieniu urządzenia, rysując zbyt wiele ścieżek.

Chociaż, powiem, twoja obecna metoda daje fajnie wyglądający efekt "3D".

+0

Doceniłem twoją sugestię. użyłem UIBezierPath i zaimplementowałem go, ale napotykamy na pewne problemy, takie jak wymazywanie funkcjonalności i wybieranie innego koloru farby ... więc w końcu zmieniłem funkcjonalność i użyłem CGContext. teraz wszystkie funkcje, takie jak Erase, zmiana koloru pędzla działa dobrze. tkwi tylko do tworzenia efektów wytłoczenia lub cienia. że efekty nie działają prawidłowo. linia prosta działa dobrze z efektami cieni. ale efekty krzywych (gładkie) nie działają dobrze. plz powiedz mi trochę sugestii używając CGContext. – Hitarth

+0

Szybkie pytanie: Jak chcesz, aby Erase działał? Większość programów "rysujących" usunie każdą oddzielną "ścieżkę" (zdefiniowaną jako jedno dotknięcie/przeciągnięcie/zakończenie zdarzenia). Działa to z moją sugestią/odpowiedzią. Jednakże, jeśli próbujesz usunąć każdy punkt ścieżki lub nawet każdy piksel ... który będzie znacznie trudniejszy do osiągnięcia. –

+0

Wymazywanie przy użyciu bieżącego kontekstu. i działa dobrze. – Hitarth

0

Nie jestem pewien co do tłoczenia, ale jeśli to, co chcesz, to zastosowanie cienia do rysunku, który jest aktualizowany progresywnie, to miłym podejściem byłoby użycie CALayers (link to a tutorial). Zasadniczo twoje progresywne rysowanie aktualizowałoby przezroczysty obraz (bez próby rysowania cienia na tym obrazie), a ten obraz byłby skonfigurowany tak, aby był wyświetlany z cieniem przez jego CALayer.

0

Cień jest tworzony na obrzeżach, a rysujesz małe segmenty linii, co tworzy ten efekt. Musisz utworzyć ścieżkę, a następnie przesuwać ją raz. Ten kod może pomóc :)

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); 

Spróbuj rozwiązać ten sposób .. może rozwiązać problem .. Najpierw utwórz ur ścieżkę i po to jest całkowicie stworzony, udar go. Dzieje się tak, ponieważ na każdej małej linii poruszasz się i dlatego stworzony cień tworzy kropkę na swoich granicach, więc uzyskujesz ten efekt.

+0

Co to jest CurrntPath w twoim kodzie i dlaczego używasz pętli? nie dostaję .. plz zobacz mój pełny kod źródłowy (edytowany). – Hitarth

+0

Tworzę tablicę punktów, bieżącą ścieżką jest ta tablica. Ta tablica jest tworzona z punktów, patrzenie z dotyku zaczyna się dotykać koniec :) – DivineDesert