【问题标题】:Scale UIView with the top center as the anchor point?以顶部中心为锚点缩放 UIView?
【发布时间】:2012-12-10 02:05:21
【问题描述】:

我正在使用 CGAffineTransformMakeScale 缩放 UIView,但我希望在缩放时将其固定在当前的顶部中心点。

我已经研究过设置 view.layer.anchorPoint,但我认为我需要将其与设置 view.layer.position 结合使用,以解决锚点的变化。

如果有人能指出我正确的方向,我将不胜感激!

【问题讨论】:

  • myView.layer.anchorPoint = CGPointMake(0.5, 0); 这不适合你吗?
  • 我最初认为它会,但它只是将视图的顶部向下移动到它的中心位置。

标签: objective-c uiview calayer


【解决方案1】:

在此处查看我的回答,以了解更改锚点时视图为何会移动:https://stackoverflow.com/a/12208587/77567

所以,从您的视图转换设置为身份开始。当视图未变换时,找到其上边缘的中心:

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;

现在图层保持在屏幕上的相同位置,但其锚点位于其顶部边缘的中心,因此缩放和旋转将保持该点固定。

【讨论】:

    【解决方案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))
    

    【讨论】:

      【解决方案3】:

      这是一个老问题,但我遇到了同样的问题,花了很多时间来达到预期的行为,扩展了@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
                                                 }];
                           }];
                       }];
      

      就是这样。如您所见,主要是正确设置视图的位置和锚点。 然后,这一切都是小菜一碟! 问候,让代码与您同在!

      【讨论】:

        猜你喜欢
        • 2011-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-16
        • 1970-01-01
        • 2014-03-12
        • 1970-01-01
        相关资源
        最近更新 更多