1

J'essaie d'obtenir un effet comme le zoomRectToVisible -method de UIScrollview. Mais ma méthode devrait être capable de centrer le rect particulier dans le calque pendant le zoom et il devrait être capable de réajuster après que l'orientation du périphérique ait changé. J'essaye d'écrire un logiciel comme l'application de marvel-comic et ai besoin d'une vue qui présente chaque panneau dans une page.Core Animation et Transformation comme zoomRectToVisible

Pour ma mise en œuvre, j'utilise CALayer et Core Animation pour obtenir l'effet désiré avec les transformations CATransform3D. Mon problème est, je ne suis pas en mesure d'obtenir le rect/panneau zoomé centré.

La structure de mon implémentation ressemble à ceci: J'ai une sous-classe de UIScrollview avec un UIView ajouté comme sous-vue. L'UIView contient l'image/page dans son CALayer.contents et j'utilise des animations de base pour obtenir l'effet de zoom et de centrage. L'effet de zoom sur chaque panneau fonctionne correctement, mais le centrage est désactivé. Je ne suis pas en mesure de calculer la translocation-transformation correcte pour le centrage.

Mon code pour la mise en œuvre de l'effet est comme ceci:

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

Ainsi, la vue nécessite les points suivants:

  1. il devrait pouvoir zoomer et centre rect/panneau de la couche/vue en fonction de l'orientation actuelle du périphérique. (ZoomRectToVisible de UIScrollView ne centre pas rect)
  2. si nessesary (soit l'orientation de l'appareil modifié ou panneau nécessite une rotation) du panneau zoomée/rect doit pouvoir tourner
  3. la durée de l'animation dépend de la préférence de l'utilisateur. (Je ne sais pas si je peux changer la durée de l'animation par défaut de zoomRectToVisible de UIScrollView?)

Ces points sont la raison pour laquelle j'écrasent les zoomRectToVisible méthode de UIScrollView. Donc, je dois savoir comment je peux calculer correctement les paramètres de traduction pour la transformation.

J'espère que quelqu'un peut me guider pour obtenir les paramètres corrects.

Répondre

-1

survolaient votre code et cette ligne est probablement pas calculé que vous pensez:

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

Vous êtes susceptible d'obtenir 0 en raison du 1/au début. C fera votre multiplication avant cette division, résultant en des valeurs < 1 - probablement pas ce que vous recherchez. Vous trouverez peut-être plus utile de décomposer votre calcul pour savoir qu'il fonctionne dans le bon ordre (utilisez simplement des variables temporaires) - croyez-moi, cela aidera énormément à rendre votre code plus facile à lire (et à déboguer) plus tard. Ou vous pourriez simplement utiliser plus de parenthèses ...

Espérons que cela aide.

+0

'' '' 'et'/'ont la même priorité d'opérateur (voir votre lien). Cela signifie en fait qu'ils seront (logiquement) exécutés de gauche à droite. –

Questions connexes