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