我已经在这方面工作了一段时间并彻底搜索了一个解决方案,但无济于事。这是我想要做的。
我有一个UIScrollView,用户可以在其上放大和平移5秒钟。我有一个单独的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];
}
对上面的图层进行动画处理时,内容会正确缩放,但定位不正确。内容似乎是x
,y
移动的次数超出了我的预期,因此无法完全回溯用户在UIScrollView上完成的缩放/平移。
任何想法我可能做错了什么?
好的,我弄清楚我做错了什么。它与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 :(得分:0)
您将翻译矩阵与缩放矩阵连接起来。位移偏移的最终值将为偏移(X,Y)=(scaleX * Tx,scaleY * Ty)。
如果你想用(Tx,Ty)偏移移动UIView,而不是连接翻译和缩放矩阵,如下所示:
CATransform3D scale = CATransform3DMakeScale(zoomScale, zoomScale, 1);
CATransform3D translate = CATransform3DMakeTranslation(-scrollViewContentOffset.x,
-scrollViewContentOffset.y, 0);
CATransform3D concat = CATransform3DConcat(translate, scale);
试试这个并告诉我它是否有效。