1

我正在尝试获得类似于zoomRectToVisibleUIScrollview 的 -method 的效果。但是我的方法应该能够在缩放时将特定矩形居中在图层中,并且它应该能够在设备方向改变后重新调整。

我正在尝试编写一个类似 marvel-comic 应用程序的软件,并且需要一个在页面中显示每个面板的视图。

对于我的实现,我使用 CALayer 和 Core Animation 来通过 CATransform3D-transformations 获得所需的效果。我的问题是,我无法使缩放的矩形/面板居中。

我的实现结构如下所示:我有一个 UIScrollview 的子类,其中添加了一个 UIView 作为子视图。UIView 在它的 CALayer.contents 中包含图像/页面,我使用核心动画来获得缩放和居中效果。每个面板上的缩放效果都可以正常工作,但居中已关闭。我无法计算正确的中心转换转换。

我的效果实现代码是这样的:

- (void) zoomToRect:(CGRect)rect animated:(BOOL)animated {
    CGSize scrollViewSize = self.bounds.size;

    // get the current panel boundingbox
    CGRect panelboundingBox = CGPathGetBoundingBox([comicPage panelAtIndex:currentPanel]);

    // compute zoomfactor depending on the longer dimension of the panelboundingBox size
    CGFloat zoomFactor = (panelboundingBox.size.height > panelboundingBox.size.width) ? scrollViewSize.height/panelboundingBox.size.height : scrollViewSize.width/panelboundingBox.size.width;

    CGFloat translateX = scrollViewSize.width/2 - (panelboundingBox.origin.x/2 + panelboundingBox.size.width/2);
    CGFloat translateY = scrollViewSize.height/2 - (panelboundingBox.size.height/2 - panelboundingBox.origin.y);

    // move anchorPoint to panelboundingBox center
    CGPoint anchor = CGPointMake(1/contentViewLayer.bounds.size.width * (panelboundingBox.origin.x + panelboundingBox.size.width/2), 1/contentViewLayer.bounds.size.height * (contentViewLayer.bounds.size.height - (panelboundingBox.origin.y + panelboundingBox.size.height/2)));


    // create the nessesary transformations
    CATransform3D translateMatrix = CATransform3DMakeTranslation(translateX, -translateY, 1);
    CATransform3D scaleMatrix = CATransform3DMakeScale(zoomFactor, zoomFactor, 1);

    // create respective core animation for transformation
    CABasicAnimation *zoomAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    zoomAnimation.fromValue =  (id) [NSValue valueWithCATransform3D:contentViewLayer.transform];
    zoomAnimation.toValue = (id) [NSValue valueWithCATransform3D:CATransform3DConcat(scaleMatrix, translateMatrix)];
    zoomAnimation.removedOnCompletion = YES;
    zoomAnimation.duration = duration;

    // create respective core animation for anchorpoint movement
    CABasicAnimation *anchorAnimatione = [CABasicAnimation animationWithKeyPath:@"anchorPoint"];
    anchorAnimatione.fromValue = (id)[NSValue valueWithCGPoint:contentViewLayer.anchorPoint];
    anchorAnimatione.toValue = (id) [NSValue valueWithCGPoint:anchor];
    anchorAnimatione.removedOnCompletion = YES;
    anchorAnimatione.duration = duration;

    // put them into an animation group
    CAAnimationGroup *group = [CAAnimationGroup animation];
    group.animations = [NSArray arrayWithObjects:zoomAnimation, anchorAnimatione, nil] ;

    /////////////

    NSLog(@"scrollViewBounds (w = %f, h = %f)", self.frame.size.width, self.frame.size.height);
    NSLog(@"panelBounds (x = %f, y = %f, w = %f, h = %f)", panelboundingBox.origin.x, panelboundingBox.origin.y, panelboundingBox.size.width, panelboundingBox.size.height);
    NSLog(@"zoomfactor: %f", zoomFactor);
    NSLog(@"translateX: %f, translateY: %f", translateX, translateY);
    NSLog(@"anchorPoint (x = %f, y = %f)", anchor.x, anchor.y);

    /////////////

    // add animation group to layer 
    [contentViewLayer addAnimation:group forKey:@"zoomAnimation"];

    // trigger respective animations
    contentViewLayer.anchorPoint = anchor;
    contentViewLayer.transform = CATransform3DConcat(scaleMatrix, translateMatrix);
}

所以视图需要以下几点:

  1. 它应该能够根据当前设备方向缩放和居中图层/视图的矩形/面板。(UIScrollview 的 zoomRectToVisible 不居中矩形)
  2. 如果需要(设备方向更改或面板需要旋转),则缩放的面板/矩形应该能够旋转
  3. 动画的持续时间取决于用户偏好。(不知道能否更改 UIScrollView 的 zoomRectToVisible 默认动画时长?)

这些点是我覆盖 UIScrollView 的 zoomRectToVisible 方法的原因。

所以我必须知道如何正确计算转换的转换参数。

我希望有人可以指导我获得正确的参数。

4

1 回答 1

-1

只是浏览了您的代码,这条线可能没有像您想象的那样计算:

CGPoint anchor = CGPointMake(1/contentViewLayer.bounds.size.width * (panelboundingBox.origin.x + panelboundingBox.size.width/2), 1/contentViewLayer.bounds.size.height * (contentViewLayer.bounds.size.height - (panelboundingBox.origin.y + panelboundingBox.size.height/2)));

由于开始时的 1/,您可能会得到 0。C 将在此除法之前进行乘法运算,导致值 <1 - 可能不是您所追求的。看到这个

您可能会发现分解计算更有用,以便您知道它以正确的顺序工作(只需使用一些临时变量) - 相信我这将极大地帮助您的代码在以后更易于阅读(和调试)。或者你可以使用更多的括号......

希望这可以帮助。

于 2010-07-13T07:43:42.150 回答