2016-07-25 36 views
8

Próbuję utworzyć niestandardowy wskaźnik aktywności podobny do wskaźnika okólnego nieokreślonego działania w systemie Android. Zasadniczo chcę narysować okrąg dwa razy i usunąć go, ale wymazywanie i rysowanie nie odbywa się w tym samym czasie lub z prędkością. Oto, co mam do tej pory:Łączenie dwóch animacji z wyprzedzeniem

let progressLayer = CAShapeLayer() 
progressLayer.strokeColor = UIColor.red().cgColor 
progressLayer.fillColor = nil 
progressLayer.lineWidth = 2 

let drawAnimation = CABasicAnimation(keyPath: "strokeEnd") 
drawAnimation.duration = duration/2 
drawAnimation.fromValue = 0 
drawAnimation.toValue = 1 
drawAnimation.isRemovedOnCompletion = false 
drawAnimation.fillMode = kCAFillModeForwards 

let eraseAnimation = CABasicAnimation(keyPath: "strokeStart") 
eraseAnimation.duration = duration/2 
eraseAnimation.beginTime = 0.2 
eraseAnimation.fromValue = 0 
eraseAnimation.toValue = 0.4 
eraseAnimation.isRemovedOnCompletion = false 
eraseAnimation.fillMode = kCAFillModeForwards 

let endDrawAnimation = CABasicAnimation(keyPath: "strokeEnd") 
endDrawAnimation.beginTime = duration/2 
endDrawAnimation.duration = duration/2 
endDrawAnimation.fromValue = 0 
endDrawAnimation.toValue = 1 
endDrawAnimation.isRemovedOnCompletion = false 
endDrawAnimation.fillMode = kCAFillModeForwards 

let endEraseAnimation = CABasicAnimation(keyPath: "strokeStart") 
endEraseAnimation.beginTime = duration/2 
endEraseAnimation.duration = duration/4 
endEraseAnimation.fromValue = 0.4 
endEraseAnimation.toValue = 1 
endEraseAnimation.isRemovedOnCompletion = false 
endEraseAnimation.fillMode = kCAFillModeForwards 

let endEraseAnimation2 = CABasicAnimation(keyPath: "strokeStart") 
endEraseAnimation2.beginTime = duration * 3/4 
endEraseAnimation2.duration = duration/4 
endEraseAnimation2.fromValue = 0 
endEraseAnimation2.toValue = 1 
endEraseAnimation2.isRemovedOnCompletion = false 
endEraseAnimation2.fillMode = kCAFillModeForwards 


let animations = CAAnimationGroup() 
animations.duration = duration 
animations.animations = [drawAnimation, eraseAnimation, endDrawAnimation, endEraseAnimation, endEraseAnimation2] 
animations.isRemovedOnCompletion = false 
animations.fillMode = kCAFillModeForwards 
progressLayer.add(animations, forKey: "stroke") 

Kod wykonuje wszystko zgodnie z oczekiwaniami, z wyjątkiem jednego wydania. Kiedy pierwsza animacja strokeEnd jest wykonana, a druga zaczyna się, pojawia się rodzaj flash oznaczający część koła, która została narysowana do momentu zniknięcia tego rysunku, a następnie rysowanie rozpoczyna się ponownie od 0. Czy ktoś ma jakieś pomysły, jak to naprawić?

+0

kodzie pokazują błędy przy próbie kompilacji, proszę umieścić swój prawdziwy kod, aby pomóc ty –

+0

@ReinierMelian to kod Swift 3, upewnij się, że używasz Xcode 8 lub przetłumaczyć go na Swift 2. @ Banana, co to jest 'progressLayer'? – JAL

+0

'progressLayer' jest' CAShapeLayer', dodałem to do powyższego pytania. – Banana

Odpowiedz

0

Kiedy pierwsza animacja strokeEnd odbywa, a drugi zaczyna istnieje rodzaj błysku oznaczającego część okręgu, który został sporządzony do tego punktu, a następnie znika rysunku rozpoczyna się od 0.

Jeśli porównać konfigurację zarówno drawAnimation, jak i endDrawAnimation, zobaczysz, że są one identyczne, z wyjątkiem właściwości beginTime. To właśnie powoduje twoje migotanie. Oboje zaczynają się od 0 i oboje koniec z 1. Ponieważ nie określono pożądanego rezultatu mogę tylko przypuszczać, że chcesz endDrawAnimation mieć fromValue z 1.

let drawAnimation = CABasicAnimation(keyPath: "strokeEnd") 
drawAnimation.duration = duration/2 
drawAnimation.fromValue = 0 
drawAnimation.toValue = 1 
drawAnimation.isRemovedOnCompletion = false 
drawAnimation.fillMode = kCAFillModeForwards 

let endDrawAnimation = CABasicAnimation(keyPath: "strokeEnd") 
endDrawAnimation.beginTime = duration/2 // Starts after the first animation and starts with 0 again. 
endDrawAnimation.duration = duration/2 
endDrawAnimation.fromValue = 0 
endDrawAnimation.toValue = 1 
endDrawAnimation.isRemovedOnCompletion = false 
endDrawAnimation.fillMode = kCAFillModeForwards 

propozycja dla poprawy

O ile widzę, chcesz utworzyć animację klatek kluczowych, co oznacza, że ​​masz predefiniowane przesunięcia, w których zmienia się zachowanie animacji (prędkość, wartość itp.). Możesz zamiast tego rozważyć użycie CAKeyframeAnimation.

jestem pewien, czy jesteś tego świadomy, ale w tym momencie masz dwie animacje uruchomione jednocześnie na strokeStart:

  • eraseAnimation że rozpoczyna się 0.2 o czasie trwania 0.5 * duration
  • endEraseAnimation który zaczyna się 0.5 * duration .

Oznacza to, że koniec eraseAnimation (0.2 + 0.5 * duration) jest zawsze większa niż na początku endEraseAnimation (0.5 * duration)