Mam problem podczas tworzenia wyraźnej animacji, aby zmienić wartość ścieżki CAShapeLayer z elipsy na prostokąt.

W moim kontrolerze canvas ustawiam podstawowy CAShapeLayer i dodaję go do warstwy widoku głównego:

CAShapeLayer *aLayer;
aLayer = [CAShapeLayer layer];
aLayer.frame = CGRectMake(100, 100, 100, 100);
aLayer.path = CGPathCreateWithEllipseInRect(aLayer.frame, nil);
aLayer.lineWidth = 10.0f;
aLayer.strokeColor = [UIColor blackColor].CGColor;
aLayer.fillColor = [UIColor clearColor].CGColor;
[self.view.layer addSublayer:aLayer];

Następnie, kiedy animuję ścieżkę, dostaję dziwną usterkę/migotanie w ostatnich kilku klatkach animacji, gdy kształt staje się prostokątem, oraz w pierwszych kilku klatkach, gdy animacja nie jest prostokątem. Animacja jest skonfigurowana w następujący sposób:

CGPathRef newPath = CGPathCreateWithRect(aLayer.frame, nil);
[CATransaction lock];
[CATransaction begin];
[CATransaction setAnimationDuration:5.0f];
CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"path"];
ba.autoreverses = YES;
ba.fillMode = kCAFillModeForwards;
ba.repeatCount = HUGE_VALF;
ba.fromValue = (id)aLayer.path;
ba.toValue = (__bridge id)newPath;
[aLayer addAnimation:ba forKey:@"animatePath"];
[CATransaction commit];
[CATransaction unlock];

Próbowałem wielu różnych rzeczy, takich jak blokowanie / odblokowywanie CATransaction, granie z różnymi trybami wypełniania itp.

Oto obraz usterki: http://www.postfl.com/outgoing/renderingglitch.png

Film z tego, czego doświadczam, można znaleźć tutaj: http://vimeo.com/37720876

8
C4 - Travis 1 marzec 2012, 12:43

2 odpowiedzi

Najlepsza odpowiedź

Niestety jest to ograniczenie skądinąd niesamowitej właściwości ścieżki animowanej CAShapeLayers.

Zasadniczo próbuje interpolować między dwiema ścieżkami. Problemy pojawiają się, gdy ścieżka docelowa i ścieżka początkowa mają różną liczbę punktów kontrolnych - a krzywe i proste krawędzie będą miały ten problem.

Możesz spróbować zminimalizować efekt, rysując elipsę jako 4 krzywe zamiast pojedynczej elipsy, ale nadal nie jest to prawidłowe. Nie znalazłem sposobu na płynne przejście od krzywych do wielokątów.

Możesz być w stanie przejść większość drogi, a następnie przejść do animacji zanikania w ostatniej części - jednak nie będzie to wyglądać tak ładnie.

5
jrturton 1 marzec 2012, 12:50

Otrzymałem tę informację zwrotną z listy quartz-dev:

David Duncan napisał:

Animowanie ścieżki warstwy kształtu jest gwarantowane tylko wtedy, gdy animujesz od polubienia do polubienia. Prostokąt to sekwencja linii, podczas gdy elipsa to sekwencja łuków (możesz zobaczyć sekwencję wygenerowaną za pomocą CGPathApply), więc animacja między nimi nie gwarantuje, że będzie wyglądać bardzo dobrze ani w ogóle działać dobrze.

Aby to zrobić, musisz zasadniczo utworzyć analog do prostokąta, używając tych samych krzywych, których użyłbyś do utworzenia elipsy, ale z parametrami, które sprawią, że renderowanie będzie wyglądać jak prostokąt. Nie powinno to być zbyt trudne (i znowu możesz użyć tego, co otrzymujesz z CGPathApply na ścieżce utworzonej za pomocą CGPathAddEllipseInRect jako przewodnika), ale prawdopodobnie będzie wymagało pewnych poprawek, aby uzyskać prawidłowe.

8
C4 - Travis 1 marzec 2012, 23:40