How do you translate and scale the view without turning into conflicts with each other?

I need to translate and scale the UIView from the center of the screen to the upper right corner.

 _____________________________
|                            |
|                            |
|         _________          |
|        |         |         |    START
|        |         |         |
|        |_________|         |
|                            |
|                            |
|____________________________|


 _____________________________
|                       __   |
|                      |__|  |
|                            |
|                            |    END
|                            |
|                            |
|                            |
|                            |
|____________________________|

I confirmed that my individual calculations for scale and translation were accurate. But as soon as they unite, they conflict with each other. The following code makes the view too close to the center.

CGFloat finalPadding = 10.0f;
CGFloat finalScale = 46.0f / 170.0f;
CGFloat finalX = self.view.frame.size.width 
    - self.platformProgressView.frame.size.width * finalScale 
    - finalPadding;
CGFloat finalY = finalPadding;
CGFloat deltaX = finalX - self.platformProgressView.frame.origin.x;
CGFloat deltaY = finalY - self.platformProgressView.frame.origin.y;

[UIView
    animateWithDuration:1.0
    delay:1.0
    options:UIViewAnimationOptionCurveEaseOut
    animations:^(void){
        self.platformProgressView.transform = CGAffineTransformConcat(
            CGAffineTransformMakeTranslation(deltaX, deltaY),
            CGAffineTransformMakeScale(finalScale, finalScale)
        );            
    }
    completion:^(BOOL finished) {
    }
];

The final effect:

 _____________________________
|                            |
|                            |
|                __          |
|               |__|         |
|                            |
|                            |
|                            |
|                            |
|____________________________|

Changing the order of multiplication causes the view to deviate from the right edge of the screen.

self.platformProgressView.transform = CGAffineTransformConcat(
     CGAffineTransformMakeScale(finalScale, finalScale),
    CGAffineTransformMakeTranslation(deltaX, deltaY)
);

Final effect (projected):

 _____________________________
|                            |
|                            |    __
|                            |   |__|
|                            |
|                            |
|                            |
|                            |
|                            |
|____________________________|

Using them individually causes a sharp jump, and the final position is even worse.

self.platformProgressView.transform = CGAffineTransformMakeTranslation(deltaX, deltaY);
self.platformProgressView.transform = CGAffineTransformMakeScale(finalScale, finalScale);

The final effect:

 _____________________________
|                            |
|                            | 
|                            |  
|                            |
|       __                   |
|      |__|                  |
|                            |
|                            |
|____________________________|
+4
source share
3 answers

Understanding Transformations

, , . .

. v1 - , v2 - . p - , (finalPadding ). c .

+--------------------------------+
|                        ^       |
|                        | p     |
|                        v       |
|              +- v2 --------+   |
|              |             |   |
|              |      c      |<->|
|              |             | p |
|              +-------------+   |
|                                |
|                                |
|    +- v1 --------+             |
|    |             |             |
|    |      c      |             |
|    |             |             |
|    +-------------+             |
|                                |
+--------------------------------+

. v3 - . , v3 , . , p '.

+--------------------------------+
|                       ^        |
|                       | p'     |
|                       |        |
|                       v        |
|                 +- v3 --+      |
|                 |   c   |<---->|
|                 +-------+  p'  |
|                                |
|                                |
|    +- v1 --------+             |
|    |             |             |
|    |      c      |             |
|    |             |             |
|    +-------------+             |
|                                |
+--------------------------------+

-

, , , , . :

CGRect windowFrame = self.window.frame;
CGRect viewFrame = self.platformProgressView.frame;
CGPoint finalCenter = CGPointZero;
finalCenter.x = (windowFrame.size.width
                 - (viewFrame.size.width * finalScale) / 2.0f
                 - finalPadding);
finalCenter.y = (finalPadding
                 + (viewFrame.size.height * finalScale) / 2.0f);
CGPoint viewCenter = self.platformProgressView.center;
CGFloat deltaX = finalCenter.x - viewCenter.x;
CGFloat deltaY = finalCenter.y - viewCenter.y;

, , , CGAffineTransformConcat, . 1) transform + 2). , , , .

2 : , , 1) scale + 2). , . ,

self.platformProgressView.transform = CGAffineTransformConcat(
    CGAffineTransformMakeScale(finalScale, finalScale),
    CGAffineTransformMakeTranslation(deltaX, deltaY)
);

CGAffineTransform CGAffineTransformMakeScaleTranslate(CGFloat sx, CGFloat sy, CGFloat dx, CGFloat dy)
{
  return CGAffineTransformMake(sx, 0.0f, 0.0f, sy, dx, dy);
}

self.platformProgressView.transform = CGAffineTransformMakeScaleTranslate(finalScale, finalScale, deltaX, deltaY);

:

, , , anchorPoint CALayer . 0,5/0,5, . , - , .

deltas , , . ,

self.platformProgressView.layer.anchorPoint = CGPointMake(0.0f, 0.0f)

.

, , , WWDC 2011 UIKit Rendering - , , , , .

, CALayer anchorPoint, , , CALayer.

+10

. .

- , , .

0

, Swift 4

 let containerFrame: CGRect  = self.view.frame
    let viewFrame: CGRect  = self.containerView.frame
    var finalCenter: CGPoint  = CGPoint.zero
    let finalPadding: CGFloat  = 0
    let finalScale: CGFloat  = 2.0 //whatever scale that you want

    finalCenter.x = (containerFrame.size.width - (viewFrame.size.width * finalScale) / 2.0 - finalPadding)
    finalCenter.y = (finalPadding + (viewFrame.size.height * finalScale) / 2.0);

    let containerCenter: CGPoint  = self.containerView.center
    let deltaX: CGFloat  = finalCenter.x - containerCenter.x
    let deltaY: CGFloat  = finalCenter.y - containerCenter.y

    let scale = CGAffineTransform(scaleX: finalScale, y: finalScale)
    //MARK: changing the deltas for positive to negative values will change the origin x and y of the transformed view
    let translation = CGAffineTransform(translationX: -deltaX, y: deltaY)

    self.containerView.transform = scale.concatenating(translation)
0
source

Source: https://habr.com/ru/post/1545142/


All Articles