1

我一直在這裏工作了一段時間,並徹底搜索了一個解決方案,但無濟於事。這是我想要做的。CALayer上CAlleFrameAnimation的變換屬性不能按預期工作

我有一個用戶可以縮放和平移5秒的UIScrollView。我有一個單獨的CALayer,它不在UIScrollView的頂層。我想縮放和翻譯此CALayer的內容以反映在UIScrollView上發生的縮放和平移。我想通過關鍵幀動畫CAKeyFrameAnimation實現此目的。當我把它放到代碼中時,縮放按預期發生,但內容的位置被錯誤地偏移。

這是我如何在代碼中做到這一點。假設UIScrollView代表經過縮放比例和含量偏移下面的方法:

// 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]; 
} 

當上述層是動畫,其內容被適當地縮放,但它被不正確地定位。內容似乎是xy,移位超出我的預期,因此不會完全回溯用戶在UIScrollView上完成的縮放/平鋪。

任何想法我可能做錯了什麼?

答案

好吧,我想清楚我做錯了什麼。它必須與CALayer的錨點有關。 CALayers上的轉換始終應用於定位點。對於CALayers,默認情況下,定位點爲(0.5,0.5)。因此正在沿着中心點進行縮放和翻譯。另一方面,UIScrollViews從視圖的左上角給出偏移量。基本上,您可以考慮UIScrollView的錨點,以便考慮CGPoint偏移值,爲(0.0,0.0)。

所以解決方法是將CALayer的錨點設置爲(0.0,0.0)。然後一切按預期工作。

還有其他資源以更好的方式呈現此信息。看到這個在Stackoverflow上的另一個問題是similar。另請參閱蘋果文檔中的this article,該文檔詳細討論幾何中的位置,定位點和常規層。

回答

0

您將翻譯矩陣與縮放矩陣連接起來。位移偏移的最終值將爲偏移量(X,Y)=(scaleX * Tx,scaleY * Ty)。

如果你想用(TX,泰)移動UIView的偏移,比拼接的轉換和調整矩陣如下:

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

試試這個,讓我知道,如果它的工作原理。

+0

謝謝@mak。我在提交帖子之前嘗試過。我再次嘗試了它,並且比'CATransform3DConcat(scale,translate)'更加替代它。它不幸的工作。 – krissb