CAAnimation은 표준 "animationDidStart :"/ "animationDidStop :"메서드 이외의 콜백 함수를 할당하는 메커니즘을 제공하지 않습니다.CABasicAnimation 콜백 대신 사용할 수 있습니까?
중복되는 2 개의 CALayers를 사용하는 맞춤 UIControl이 있습니다. 이 컨트롤의 목적은 구식 수중 음파 탐지기와 비슷합니다. 최상위 레이어의 내용에는 끊임없이 회전하는 이미지가 포함됩니다 (이 레이어를 "지팡이"라고 함). 그 레이어 아래에는 지팡이가 지평선을지나 감에 따라 화면을 렌더링하는 "spriteControl"레이어가 있습니다.
blip이 나타내는 개체는 pre-fetched이며 spriteControl에 의해 보이지 않는 CAShapeLayers로 구성됩니다. CABasicAnimation을 사용하여 한 번에 10 도씩 막대를 회전 한 다음 "animationDidStop :"메서드를 사용하여 spriteControl에서 막대 레이어의 현재 회전 값 (일명 표제)을 가져 와서 알파 설정을 애니메이션합니다. blip in 및 fade out 효과를 시뮬레이트하기 위해 1.0에서 0.0. 마지막으로 프로세스가 무한정 다시 시작됩니다.
CAAnimation 콜백을 사용하는이 방법은 지팡이가 "ping"위치 (즉, 10deg, 20deg, 270deg 등)에 도달하는 타이밍이 다른 레이어의 blips 조명과 항상 일치하도록합니다. 애니메이션을 10도 간격으로 멈추고 재 계산하고 시작하는이 문제.
막대 값을 얻기 위해 지팡이의 프리젠 테이션 레이어의 각도를 쿼리하는 메소드를 실행하는 NSTimer를 생성 할 수 있습니다. 그러나 막대와 지주 강조 표시를 동기화 상태로 유지하거나 일부를 건너 뛰는 것이 더 어려워집니다. 이 접근법은 조금 여기에 설명되어 있습니다 : How can I callback as a CABasicAnimation is animating?
제 질문은 내가 OpenGL ES를 사용하여 컨트롤을 reimplementing하지 않고 지팡이 레이어 회전의 성능을 향상시키기 위해 할 수있는 일이 있는지 여부입니다. (OpenGL 환경에서 쉽게 해결할 수 있다는 것을 알고 있지만, 여기서 사용하려면 단순히 가치가없는 광범위한 재 설계가 필요할 것입니다.) 성능 문제는 미미하지만, 존재하는 느낌을 떨칠 수는 없습니다. 내가 할 수있는 간단하고 명백한 무언가는 완드가 중간에 비싼 회전 계산을 수행하기 위해 멈추지 않고 무기한으로 움직일 수있게 해줍니다.
- (void)rotateWandByIncrement
{
if (wandShouldStop)
return;
CGFloat newRotationDegree = (wandRotationDegree + WAND_INCREMENT_DEGREES);
if (newRotationDegree >= 360)
newRotationDegree = 0;
CATransform3D rotationTransform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(newRotationDegree), 0, 0, 1);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:rotationTransform];
animation.duration = WAND_INCREMENT_DURATION;
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = FALSE;
animation.delegate = self;
[wandLayer addAnimation:animation forKey:@"transform"];
}
- (void)animationDidStart:(CAAnimation *)theAnimation
{
if (wandShouldStop)
return;
NSInteger prevWandRotationDegree = wandRotationDegree - WAND_INCREMENT_DEGREES;
if (prevWandRotationDegree < 0)
prevWandRotationDegree += 360;
// Pulse the spriteControl
[[self spriteControl] pulseRayAtHeading:prevWandRotationDegree];
}
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
// update the rotation var
wandRotationDegree += WAND_INCREMENT_DEGREES;
if (wandRotationDegree >= 360)
wandRotationDegree = 0;
// This applies the rotation value to the model layer so that
// subsequent animations start where the previous one left off
CATransform3D rotationTransform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(wandRotationDegree), 0, 0, 1);
[CATransaction begin];
[CATransaction setDisableActions:TRUE];
[wandLayer setTransform:rotationTransform];
[CATransaction commit];
//[wandLayer removeAnimationForKey:@"transform"];
[self rotateWandByIncrement];
}
업데이트 : 나는 사전 계산 된 값의 정적 배열을 만들어 모든 불필요한 계산을 제거했습니다. 이제는 성능 병목 현상이 값 비싼 수학 연산으로 인해 발생하지 않는다는 것을 확신했습니다. 그런 다음 지팡이 레이어에서 키 프레임 애니메이션을 구현했지만 약간 더 부드럽게 회전하지는 못합니다. 실제로 CAAnimation 대신 UIView 애니메이션으로 전환하면이 상황에서보다 부드러운 애니메이션이 제공된다는 사실을 발견했습니다. 지금까지 CAAnimation에서 실제 성능 향상을 얻으려는 것 같습니다. 콜백을 사용하지 말고 GPU가 그 일을하도록하십시오. – quickthyme