Базовая анимация и трансформация, например zoomRectToVisible - PullRequest
1 голос
/ 23 июня 2010

Я пытаюсь получить эффект, подобный zoomRectToVisible -методу UIScrollview. Но мой метод должен иметь возможность центрировать конкретный прямоугольник в слое при масштабировании, и он должен иметь возможность перенастройки после изменения ориентации устройства.

Я пытаюсь написать программное обеспечение, такое как приложение Marvel-Comic, и мне нужно представление, которое представляет каждую панель на странице.

Для моей реализации я использую CALayer и Core Animation, чтобы получить желаемый эффект с помощью CATransform3D-преобразований. Моя проблема в том, что я не могу центрировать увеличенный прямоугольник / панель.

структура моей реализации выглядит следующим образом: у меня есть подкласс UIScrollview с UIView, добавленным в качестве subview. 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. он должен иметь возможность масштабировать и центрировать прямоугольник / панель слоя / вида в зависимости от текущей ориентации устройства. (zoomRectToVisible для UIScrollview не центрирует прямоугольник)
  2. если необходимо (либо изменена ориентация устройства, либо панель требует поворота), увеличенная панель / прямоугольник должны вращаться
  3. продолжительность анимации зависит от предпочтений пользователя. (Я не знаю, могу ли я изменить продолжительность анимации по умолчанию для zoomRectToVisible для UIScrollView?)

Именно по этим причинам я перезаписываю метод zoomRectToVisible в UIScrollView.

Поэтому я должен знать, как правильно рассчитать параметры перевода для преобразования.

Я надеюсь, что кто-нибудь поможет мне получить правильные параметры.

1 Ответ

0 голосов
/ 13 июля 2010

Просто пролистав код, и эта строка, вероятно, не рассчитывается, как вы думаете:

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)));

Скорее всего, вы получите 0 из-за 1 / в начале.C выполнит ваше умножение до этого деления, в результате чего значения <1 - вероятно, не то, что вы после.См. <a href="http://en.wikipedia.org/wiki/Order_of_operations#Programming_languages" rel="nofollow noreferrer"> this

. Возможно, вам будет удобнее разбить ваши расчеты, чтобы вы знали, что они работают в правильном порядке (просто используйте некоторые временные переменные) - поверьте мне, это очень поможет вкод легче читать (и отлаживать) позже.Или вы можете просто использовать больше скобок ...

Надеюсь, это поможет.

...