gpt4 book ai didi

ios - 您如何平移和缩放 View 而不会发生相互冲突的变换?

转载 作者:可可西里 更新时间:2023-11-01 04:09:52 25 4
gpt4 key购买 nike

我需要将 UIView 从屏幕中心平移并缩放到右上角。

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


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

我验证了我对比例和平移的个人计算是准确的。但是一旦它们放在一起,它们就会相互冲突。以下代码使 View 最终离中心太近。

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) {
}
];

最终效果:

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

更改乘法的顺序会导致 View 偏离屏幕的右边缘。

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

最终效果(预计):

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

单独应用它们会导致突然跳跃,最终位置甚至更糟。

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

最终效果:

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

最佳答案

理解转换

要认识到的主要事情是变换的原点是 View 矩形的中心点。最好用一个例子来说明这一点。

首先我们翻译 View 。 v1 是其原始位置的 View ,v2 是其平移位置的 View 。 p 是您想要的填充(代码中的 finalPadding)。 c 标记 View 的中心点。

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

接下来我们缩放 View 。 v3 是在其缩放位置的 View 。请注意 v3 的中心点如何保持不变,而它周围的 View 尺寸会缩小。尽管尺寸正确,但 View 的定位和生成的填充 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) 变换 + 2) 缩放。结果是缩放变换 - 在序列中稍后出现 - 影响为平移变换指定的增量。

这里有 2 种解决方案:您自己的第二次尝试,您可以在其中反转序列,使其变为 1) scale + 2) transform。或者您使用我在我的答案的第一次修订中建议的辅助函数。所以这个

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);

另一种解决方案:设置 anchor

如果您对中心点作为 View 转换的原点不满意,您可以通过设置 View CALayer 的 anchorPoint 属性来更改它。默认 anchor 位于 0.5/0.5,代 TableView 矩形的中心。显然, anchor 不是一个坐标,而是一种倍增因子。

如果我们假设 anchor 位于 View 的左上角,那么您对平移增量的原始计算是正确的。所以如果你这样做

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

您可以保留原始计算结果。

引用

那里可能有更多的信息 Material ,但是 WWDC 2011 视频 Understanding UIKit Rendering是我最近看的东西,它极大地帮助我提高了对边界、中心、变换和框架之间关系的理解。

此外,如果您要更改 CALayer anchorPoint 属性,您可能应该阅读 CALayer class reference 中的属性文档。首先。

关于ios - 您如何平移和缩放 View 而不会发生相互冲突的变换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24295882/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com