1

zoomRectToVisibleUIScrollviewのメソッドのような効果を得ようとしています。しかし、私の方法は、ズーム中にレイヤー内の特定の四角形を中央に配置できるはずであり、デバイスの向きが変更された後に再調整できるはずです。

marvel-comic アプリのようなソフトウェアを作成しようとしていますが、各パネルをページに表示するビューが必要です。

私の実装では、CALayer と Core Animation を使用して、CATransform3D 変換で目的の効果を得ています。私の問題は、ズームされた四角形/パネルを中央に配置できないことです。

私の実装の構造は次のようになります。サブビューとして UIView が追加された UIScrollview のサブクラスがあります。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 に答える