web-dev-qa-db-ja.com

上部中央をアンカーポイントとしてUIViewをスケーリングしますか?

UIViewをCGAffineTransformMakeScaleでスケーリングしていますが、スケーリング時に現在の上部の中心点に固定したままにしておきたいです。

view.layer.anchorPointの設定を検討しましたが、アンカーポイントの変更を考慮して、これをview.layer.positionの設定と組み合わせて使用​​する必要があると思います。

誰かが私を正しい方向に向けることができれば、私はとても感謝しています!

19
Alistair Holt

ここで私の答えを見て、アンカーポイントを変更したときにビューが移動する理由を理解してください: https://stackoverflow.com/a/12208587/77567

したがって、ビューの変換をIDに設定することから始めます。ビューが変換されていないときに、その上端の中心を見つけます。

CGRect frame = view.frame;
CGPoint topCenter = CGPointMake(CGRectGetMidX(frame), CGRectGetMinY(frame));

次に、上部エッジの中央へのアンカーポイント:

view.layer.anchorPoint = CGPointMake(0.5, 0);

これで、レイヤーのposition(またはビューのcenter)がレイヤーの上端の中心の位置になります。ここで停止すると、アンカーポイントを変更する前に、その上端の中心が真の中心であった場所になるようにレイヤーが移動します。したがって、レイヤーのpositionを少し前からそのトップエッジの中央に変更します。

view.layer.position = topCenter;

これで、レイヤーは画面上の同じ場所にとどまりますが、アンカーポイントはその上端の中心であるため、スケールと回転によってそのポイントは固定されたままになります。

38
rob mayoff

Swift 4.2

置き忘れを避けながら、特定のアンカーポイントを使用してUIViewをスケーリングします。

extension UIView {
    func applyTransform(withScale scale: CGFloat, anchorPoint: CGPoint) {
        layer.anchorPoint = anchorPoint
        let scale = scale != 0 ? scale : CGFloat.leastNonzeroMagnitude
        let xPadding = 1/scale * (anchorPoint.x - 0.5)*bounds.width
        let yPadding = 1/scale * (anchorPoint.y - 0.5)*bounds.height
        transform = CGAffineTransform(scaleX: scale, y: scale).translatedBy(x: xPadding, y: yPadding)
    }
}

したがって、ビューの上部中央をアンカーポイントとして、ビューをそのサイズの半分に縮小するには、次のようにします。

view.applyTransform(withScale: 0.5, anchorPoint: CGPoint(x: 0.5, y: 0))
4
Lausbert

これは古い質問ですが、同じ問題に直面し、@ Rob Mayoffからの回答を少し拡大して目的の動作に到達するまでに多くの時間を要しました(彼の説明のおかげで解決策を見つけました)。ユーザーが触れたポイントからフローティングビューのスケーリングを表示する必要がありました。画面の座標に応じて、縮小、右、左、上、または中央から縮小できます。

最初に行うことは、フローティングビューの中心を設定するタッチポイントで行うことです(Robの説明として、中心である必要があります):

-(void)onTouchInView:(CGPoint)theTouchPosition
{
self.floatingView.center = theTouchPosition;
....
}

次の問題は、実行する内容に応じて、レイヤーのアンカーポイントを設定することです(画面フレームを基準にしてポイントを測定し、スケーリングする場所を決定しました)。

switch (desiredScallingDirection) {
    case kScaleFromCenter:
    {
        //SCALE FROM THE CENTER, SO
        //SET ANCHOR POINT IN THE VIEW'S CENTER
        self.floatingView.layer.anchorPoint=CGPointMake(.5, .5);
    }
        break;
    case kScaleFromLeft:
        //SCALE FROM THE LEFT, SO
        //SET ANCHOR POINT IN THE VIEW'S LEFT-CENTER
        self.floatingView.layer.anchorPoint=CGPointMake(0, .5);
        break;
    case kScaleFromBottom:
        //SCALE FROM BOTTOM, SO
        //SET ANCHOR POINT IN THE VIEW'S CENTER-BOTTOM
        self.floatingView.layer.anchorPoint=CGPointMake(.5, 1);
        break;
    case kScaleFromRight:
        //SCALE FROM THE RIGHT, SO
        //SET ANCHOR POINT IN THE VIEW'S RIGHT-CENTER
        self.floatingView.layer.anchorPoint=CGPointMake(1, .5);
        break;
    case kScallingFromTop:
        //SCALE FROM TOP, SO
        //SET ANCHOR POINT IN THE VIEW'S CENTER-TOP
        self.floatingView.layer.anchorPoint=CGPointMake(.5, 0);
        break;
    default:
        break;

}

今、それはすべて簡単です。アニメーションに与えたい効果に応じて(アイデアは0から100%までのバウンススケーリングでした):

//SETUP INITIAL SCALING TO (ALMOST) 0%
CGAffineTransform t=CGAffineTransformIdentity;
t=CGAffineTransformScale(t, .001, .001);
self.floatingView.transform=t;
[UIView animateWithDuration:.2
                      delay:0
                    options:UIViewAnimationOptionCurveEaseInOut
                 animations:^{
                     //BOUNCE A LITLE UP!
                     CGAffineTransform t = CGAffineTransformMakeScale(1.1,1.1);
                     self.floatingView.transform=t;
                 } completion:^(BOOL finished) {
                     [UIView animateWithDuration:.1
                                      animations:^{
                                          //JUST A LITTLE DOWN
                                          CGAffineTransform t = CGAffineTransformMakeScale(.9,.9);
                                          self.floatingView.transform = t;
                                      } completion:^(BOOL finished) {
                                          [UIView animateWithDuration:.05
                                                           animations:^{
                                                               //AND ALL SET
                                                               self.floatingView.transform  = CGAffineTransformIdentity;
                                                           }
                                           completion:^(BOOL finished) {
                                               //ALL SET
                                           }];
                     }];
                 }];

それでおしまい。ご覧のとおり、主なことはビューの位置とアンカーポイントを正しく設定することです。これで、すべてが簡単になります。よろしく、そしてコードをあなたと一緒にしましょう!

2
Anibal Itriago

Swift 4.2

これは私のために働きます:

public extension UIView {

    func applyTransform(withScale scale: CGFloat, anchorPoint: CGPoint) {
        let xPadding = (scale - 1) * (anchorPoint.x - 0.5) * bounds.width
        let yPadding = (scale - 1) * (anchorPoint.y - 0.5) * bounds.height
        transform = CGAffineTransform(scaleX: scale, y: scale).translatedBy(x: xPadding, y: yPadding)
    }
}
0
gogoslab