1

我試圖得到像zoomRectToVisible-UIScrollview方法的效果。 但是我的方法應該能夠在縮放時在圖層中居中放置特定的矩形,並且在設備方向改變後它應該能夠重新調整。Core Animation and Transformation like zoomRectToVisible

我正在嘗試編寫一個像marvel-comic app這樣的軟件,並且需要一個呈現頁面中每個面板的視圖。

對於我的實現,我使用CALayer和Core Animation通過CATransform3D轉換獲得所需的效果。我的問題是,我無法將放大的矩形/面板居中。

我的實現結構如下所示:我有一個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不居中RECT)
  2. 如果所必要的(或者設備的方向改變或面板需要旋轉)縮放面板/ RECT應該能夠
  3. 動畫的持續時間取決於用戶偏好旋轉。 (我不知道是否可以更改UIScrollView的zoomRectToVisible的默認動畫持續時間?)

這些點是我覆蓋UIScrollView的zoomRectToVisible方法的原因。

所以我必須知道如何正確計算轉換的轉換參數。

我希望有人能指導我得到正確的參數。

回答

-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 - 可能不是你所追求的。請參閱this

您可能會發現將計算細分爲更有用,因此您知道它的運行順序正確(只是使用一些臨時變量) - 相信我會極大地幫助您的代碼更易於讀取(和調試)後來。或者你可以使用更多的支架...

希望這會有所幫助。

+0

'*'和'/'具有相同的運算符優先級(請參閱您的鏈接)。這實際上意味着它們將從(從邏輯上)從左到右執行。 – 2017-04-03 10:49:28