2014-04-10 17 views
5

Próbuję realizować kolejną dziwną rzecz: Mam kilka kropek i chciałbym, aby połączyć je z sinusoidalnychSine CAShapeLayer jako maską CALayer

Następny metoda zwraca tablicę punktów dla podejmowania działki:

- (NSArray *)plotPointsBetweenPoint:(CGPoint)pointA andPoint:(CGPoint)pointB { 
    double H = fabs(pointB.y - pointA.y); 
    double L = fabs(pointB.x - pointA.x); 

    NSInteger granularity = 40; 
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:granularity + 1]; 
    for (int i = 0; i <= granularity; ++i) { 
    CGFloat x = M_PI*(float)i/(granularity); 
    CGFloat y = -cosf(x); 
    CGFloat multiplier = pointA.y > pointB.y ? 1 : -1; 
    CGPoint newPoint = CGPointMake(pointA.x + L*(float)i/granularity, pointA.y - multiplier*H*(1.0 + y)/2.0); 
    [array addObject:[NSValue valueWithCGPoint:newPoint]]; 
    } 
    return array; 
} 

Po nim utworzyć specjalny UIBezierPath:

- (UIBezierPath *)sineWaveWithPoints:(NSArray *)points { 
    UIBezierPath *path = [[UIBezierPath alloc] init]; 
    NSMutableArray *array = [NSMutableArray array]; 

    for (int i = 0; i < points.count - 1; ++i) { 
    [array addObjectsFromArray:[self plotPointsBetweenPoint:[points[i] CGPointValue] andPoint:[points[i+1] CGPointValue]]]; 
    } 
    [path moveToPoint:[array[0] CGPointValue]]; 
    for (NSValue *value in array) { 
    CGPoint point = [value CGPointValue]; 
    [path addLineToPoint:point]; 
    } 
    [path closePath]; 
    path.lineWidth = 2.0; 
    [path stroke]; 
    return path; 
} 

Następny Dodaję tę ścieżkę przy użyciu CAShapeLayer:

CAGradientLayer *gradientLayer = [self gradientLayer]; 
CAShapeLayer *maskLine = [CAShapeLayer layer]; 
maskLine.path = [self sineWaveWithPoints:pointsArray].CGPath; 
maskLine.lineWidth = self.plotWidth; 
gradientLayer.mask = maskLine; 
[self.view.layer addSublayer:gradientLayer]; 

this is what I have in the end

Więc chciałbym mieć gradientu sinusoidę między tych punktach. Co dokładnie jest nie tak w moich działaniach?

Idealny: enter image description here

+1

Przykro mi, ale nie rozumiem, co masz na myśli mówiąc "Chciałbym mieć falę sinusoidalną pomiędzy tymi punktami". Czy możesz wyjaśnić, co masz na myśli, a może nawet pokazać makietę (przykład w edytorze obrazów) tego, co próbujesz zrobić? –

+0

Pewnie. Zadanie polega na utworzeniu wykresu, kolor punktu y zależy od wysokości wartości (np. Z fioletowego na żółty). Zdecydowałem, że najlepszym sposobem na wypełnienie linii takim gradientem jest stworzenie warstwy gradientowej z odpowiednimi kolorami i wykonanie metody setMask przy użyciu utworzonego sinusu CAShapeLayer. P.S. Przypisałem render z głównym celem. – x401om

+0

Ukryj gradient za pomocą obrysowanej ścieżki? –

Odpowiedz

2

Program zachowuje się prawidłowo - to znaczy, że robi dokładnie to, co mówisz to zrobić. Problem polega na tym, że to, co mówisz, aby to zrobić (w twoim kodzie), nie jest tym, co mówisz, że chcesz (w twoich słowach i obrazie w twoim pytaniu).

Pierwsza rzecz, którą robisz źle: powiedziałeś closePath. Więc zamyka ścieżkę! Oznacza to, że po narysowaniu fali łączy ostatni punkt z pierwszym punktem z linią prostą, podając kształt, który pokazujesz.

Druga rzecz, którą robisz źle: nie możesz manipulować warstwą kształtu. Tworzysz wanilię CAShapeLayer i pozostawiasz ją domyślnie. Domyślnie jest to, że fillColor jest czarny (i nie ma strokeColor). Nie zmieniacie tego. Tak więc otrzymujesz swój (nieprawidłowy) kształt wypełniony kolorem czarnym i bez obrysu, a zatem wynikowa maska ​​jest kształtem wnętrza twojego (niewłaściwego) kształtu, podając kształt maski gradientu, który pokazujesz.