1

사용자가 내 애니메이션 속도를 변경할 수있게하려고합니다. 베 지어 경로를 사용하여 CAKeyframeAnimation을 만들고 있는데 올바르게 표시하고 실행할 수 있습니다. 다른 기간으로 새 애니메이션 경로를 만들어 속도를 변경하려고합니다. 비행기는 처음으로 되돌아갑니다 (나는 아직 고치려고하지 않았습니다). 애니메이션이 속도를 전혀 변경하지 않았을 때 그들이 그려지는 길은 사라집니다. 비행기가 끝나면 다른 곳에서 애니메이션이 일시 중지 된 지점에 나타납니다. 나는 내가 뭘 잘못하고 있는지 전혀 모른다. 내 질문은이 하나의 modifying dynamically the duration of CAKeyframeAnimation과 비슷하지만, OP가 블록을 사용하여 마침내 말하는 것에 대해 이해하지 못합니다. (내가 말할 수있는까지) 목표 위치로 현재 위치에서 애니메이션을 기본 애니메이션과 달리iOS에서 CAKeyframeAnimation 중반 애니메이션의 속도 변경하기

//The first two methods are in a class subclassing UIView 
/** Pause each plane's animation */ 
- (void)pauseAnimation 
{  
    CFTimeInterval pausedTime = [[self layer] convertTime:CACurrentMediaTime() fromLayer:nil]; 
    [self layer].speed = 0.0; 
    [self layer].timeOffset = pausedTime; 
} 

/** Resume each plane's animation */ 
- (void)resumeAnimation 
{ 
    CFTimeInterval pausedTime = [[self layer] timeOffset]; 
    [self layer].speed = 1.0; 
    [self layer].timeOffset = 0.0; 
    CFTimeInterval timeSincePause = [[self layer] convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; 

    for(SEPlane *plane in planes){ 
     plane.planeAnimationPath.speedMultiplier = 5; 
     [plane.planeAnimationPath beginAnimation:self]; 
    } 
    //[self layer].beginTime = timeSincePause; 
} 

//This method is in the class of planeAnimationPath 
/** Begin animating plane along given path */ 
- (void)beginAnimation:(UIView *) view 
{ 
    planeAnimation = nil; 
    // Create animation layer for animating plane 
    planeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];  
    planeAnimation.path = [bezierPath CGPath]; 
    planeAnimation.duration = approximateLength/(ANIMATION_SPEED * self.speedMultiplier); 
    planeAnimation.calculationMode = kCAAnimationPaced; 
    planeAnimation.fillMode = kCAFillModeForwards; 
    planeAnimation.rotationMode = kCAAnimationRotateAuto; 
    planeAnimation.removedOnCompletion = YES; 
    [planeAnimation setDelegate:self];  

    // Add animation to image-layer 
    [imageLayer addAnimation:planeAnimation forKey:animationKey]; 

    // Add image-layer to view 
    [[view layer] addSublayer:imageLayer]; 
} 

답변

2

, CAKeyframeAnimations하지 않습니다. 현재 위치가 경로에없는 애니메이션을 어떻게 해석할까요? 내가 생각할 수있는

가장 간단한 방법은 speedMultiplier의 세터에서 다음을 수행하는 것입니다

  1. 가 원하는 경로로 새로운 애니메이션을 만듭니다. speedMultiplier이 *
  2. "이미 완전히 새로운 애니메이션 %가"레이어에 애니메이션을 추가 기간에
  3. 설정 타임 오프셋을 speedMultiplier하는 속도를 설정 한
  4. 것처럼
  5. 는 시간을 설정합니다.

단순한 경로의 경우이 경로는 쉽지만 임의 경로의 경우 약간 더 복잡해집니다. 시작점으로는 베 지어 이차 곡선 및 3 차 곡선에 대한 수식이 필요합니다. "베 지어 커브의 거리 매개 변수화"를 검색하면 수많은 물건을 찾을 수 있습니다.

다음은 간단한 직사각형 패스의 코드 샘플입니다. 이 창에는 단순히 MPView와 슬라이더가 있습니다.

@implementation MPView { 

    IBOutlet NSSlider *_slider; // Min=0.0, Max=5.0 

    CALayer *_hostLayer; 
    CALayer *_ballLayer; 

    CAKeyframeAnimation *_ballPositionAnimation; 

    double _speed; 
} 

- (void) awakeFromNib 
{ 
    CGRect bounds = self.bounds; 

    [CATransaction begin]; 
    [CATransaction setDisableActions:YES]; 

    _speed = 1.0; 

    _hostLayer = [CALayer layer]; 
    _hostLayer.backgroundColor = CGColorGetConstantColor(kCGColorBlack); 
    self.layer = _hostLayer; 
    self.wantsLayer = YES; 

    _ballLayer = [CALayer layer]; 
    _ballLayer.bounds = CGRectMake(0, 0, 32, 32); 
    _ballLayer.position = CGPointMake(40, 40); 
    _ballLayer.backgroundColor = CGColorGetConstantColor(kCGColorWhite); 
    _ballLayer.cornerRadius = 16; 

    _hostLayer.sublayers = @[_ballLayer]; 


    CGMutablePathRef path = CGPathCreateMutable(); 
    CGPathMoveToPoint(path, NULL, _ballLayer.position.x, _ballLayer.position.y); 
    CGPathAddRect(path, NULL, CGRectInset(bounds, 40, 40)); 
    CGPathCloseSubpath(path); 

    _ballPositionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 
    _ballPositionAnimation.path = path; 
    _ballPositionAnimation.duration = 6; 
    _ballPositionAnimation.repeatCount = HUGE_VALF; 

    CGPathRelease(path); 

    [_ballLayer addAnimation:_ballPositionAnimation forKey:_ballPositionAnimation.keyPath]; 

    [CATransaction commit]; 

    [_slider bind:NSValueBinding toObject:self withKeyPath:@"speed" options:@{NSContinuouslyUpdatesValueBindingOption:@YES}]; 
} 

- (double) speed 
{ 
    return _speed; 
} 

- (void) setSpeed:(double)speed 
{ 
    _speed = speed; 

    CGPoint pos = [(CALayer*)_ballLayer.presentationLayer position]; 

    [CATransaction begin]; 
    [CATransaction setDisableActions:YES]; 

    _ballPositionAnimation.speed = _speed; 
    _ballPositionAnimation.duration = 5.0; 
    _ballPositionAnimation.timeOffset = _ballPositionAnimation.duration * [self percentOfPathCompleted:pos]; 
    [_ballLayer addAnimation:_ballPositionAnimation forKey:_ballPositionAnimation.keyPath]; 

    [CATransaction commit]; 
} 

- (double) percentOfPathCompleted:(CGPoint)p 
{ 
    CGRect rect = CGRectInset(self.bounds, 40, 40); 
    double minX = NSMinX(rect); 
    double minY = NSMinY(rect); 
    double maxX = NSMaxX(rect); 
    double maxY = NSMaxY(rect); 
    double offset = 0.0; 

    if (p.x == minX && p.y == minY) 
     return 0.0; 
    else if (p.x > minX && p.y == minY) 
     offset = (p.x - minX)/rect.size.width * 0.25; 
    else if (p.x == maxX && p.y < maxY) 
     offset = (p.y - minY)/rect.size.height * 0.25 + 0.25; 
    else if (p.x > minX && p.y == maxY) 
     offset = (1.0 - (p.x - minX)/rect.size.width) * 0.25 + 0.50; 
    else 
     offset = (1.0 - (p.y - minY)/rect.size.height) * 0.25 + 0.75; 

    NSLog(@"Offset = %f",offset); 
    return offset; 
} 

@end 
+0

오프셋 문제는 수정되었지만 애니메이션이 완료된 후에도 평면은 계속 그려집니다. 나는 그것을 반복하고 싶지 않다. 한 번 그려라. 내가 한 번만 말해달라고 말하면, 그 비행기가 한 번 반복되고 뒤로 향하는 비행기가 나타난다. 정말 이상합니다. – LunaEques

+0

오류를 발견했습니다. animationKey를 설정하는 것을 잊었습니다. 정말 고맙습니다! – LunaEques

+0

@LunaEques 어떻게 애니메이션 반복 문제를 해결 했습니까? 나도 똑같은 문제를 겪고있어. 감사 – Atrash

관련 문제