1

저는 잠시 동안이 작업을 해왔으므로 솔루션을 위해 철저히 조사했지만 아무 소용이 없습니다. 여기 내가하려는 일이 있습니다.CALayer에서 변환 속성의 CAKeyFrameAnimation이 예상대로 작동하지 않습니다.

사용자가 확대/축소하고 5 초 동안 초점 이동이 가능한 UIScrollView가 있습니다. UIScrollView 위에 레이어되지 않은 별도의 CALayer가 있습니다. 이 CALayer의 내용을 확장하고 변환하여 UIScrollView에서 발생하는 확대/축소 및 팬을 반영하고 싶습니다. 키 프레임 애니메이션 CAKeyFrameAnimation을 통해이를 수행하고 싶습니다. 이 코드를 코드에 넣으면 예상대로 확대/축소가 발생하지만 내용의 위치는 잘못 상쇄됩니다.

다음은 코드에서 수행하는 방법입니다. 상기 층이 움직이는 경우

// Remember all zoom params for late recreation via a CAKeyFrameAnimation 
- (void) didZoomOrScroll:(float)zoomScale 
      contentOffset:(CGPoint)scrollViewContentOffset { 

    CATransform3D scale = CATransform3DMakeScale(zoomScale, zoomScale, 1); 
    CATransform3D translate = CATransform3DMakeTranslation(-scrollViewContentOffset.x, 
                  -scrollViewContentOffset.y, 0); 
    CATransform3D concat = CATransform3DConcat(scale, translate); 

    // _zoomScrollTransforms and _zoomScrollTimes below are of type NSMutableArray 
    [_zoomScrollTransforms addObject:[NSValue valueWithCATransform3D:concat]]; 

    // secondsElapsed below keeps track of time 
    [_zoomScrollTimes addObject:[NSNumber numberWithFloat:secondsElapsed]]; 
} 

// Construct layer animation 
- (void) constructLayerWithAnimation:(CALayer *)layer { 

    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; 
    animation.duration = 5.0; 
    animation.values = _zoomScrollTransforms; 

    // Adjust key frame times to contain fractional durations 
    NSMutableArray *keyTimes = [[NSMutableArray alloc] init]; 
    for(int i = 0; i < [_zoomScrollTimes count]; i++) { 
      NSNumber *number = (NSNumber *)[_zoomScrollTimes objectAtIndex:i]; 
      NSNumber *fractionalDuration = [NSNumber numberWithFloat:[number   floatValue]/animation.duration]; 
     [keyTimes addObject:fractionalDuration]; 
    } 
    animation.keyTimes = keyTimes; 

    animation.removedOnCompletion = YES; 
    animation.beginTime = 0; 
    animation.calculationMode = kCAAnimationDiscrete; 
    animation.fillMode = kCAFillModeForwards; 
    [layer addAnimation:animation forKey:nil]; 
} 

은 콘텐츠가 적절하게 확대되지만 잘못 위치 : UIScrollView 대리자는 이하의 방법으로 크게 오프셋 스케일과 콘텐츠를 전달한다고 가정한다. 콘텐츠가 x이고 y이 예상보다 많이 이동하여 결과적으로 UIScrollView에서 사용자가 수행 한 줌/팬을 정확하게 되돌아 가지 않습니다.

내가 잘못 생각한 아이디어가 있습니까?

Answer

좋아, 내가 뭘 잘못하고 있는지 알았어. CALayer의 앵커 포인트와 관련이있었습니다. CALayers의 변형은 항상 고정 점에 적용됩니다. CALayers의 경우 앵커 포인트는 기본적으로 (0.5, 0.5)입니다. 그래서 스케일링과 번역이 중심점을 따라 진행되었습니다. UIScrollViews는 뷰의 왼쪽 상단 모서리에서 오프셋을 제공합니다. 기본적으로 UIScrollView의 앵커 포인트는 CGPoint 오프셋 값을 (0.0, 0.0)으로 생각할 때 생각할 수 있습니다.

그래서 해결 방법은 CALayer의 고정 점을 (0.0, 0.0)으로 설정하는 것입니다. 그리고 모든 것이 예상대로 작동합니다.

더 좋은 방법으로이 정보를 제공하는 다른 리소스가 있습니다. Stackoverflow에 대한 다른 질문 인 similar을 참조하십시오. 위치, 앵커 포인트 및 지오메트리의 일반 레이어에 대해 자세히 설명하는 Apple의 설명서에서 this article을 참조하십시오.

답변

0

번역 매트릭스를 스케일 된 매트릭스와 연결합니다. 변위 오프셋의 최종 값은 Offset (X, Y) = (scaleX * Tx, scaleY * Ty)입니다.

CATransform3D scale = CATransform3DMakeScale(zoomScale, zoomScale, 1); 
CATransform3D translate = CATransform3DMakeTranslation(-scrollViewContentOffset.x, 
                 -scrollViewContentOffset.y, 0); 
CATransform3D concat = CATransform3DConcat(translate, scale); 

이 시도하고 작동하는지 알려주세요 :

아래로 번역하고 규모 행렬을 연결하여보다 오프셋 (TX, 타이)와 UIView의를 이동하려면

.

+0

감사합니다. @mak. 나는 그 글을 보내기 전에 그것을 시도했다. 나는 그것을 다시 시도하고'CATransform3DConcat (scale, translate)'보다 더 멀리 옮겼다. 불행히도 작동하지 않습니다. – krissb