Pwn*_*ner 5 cocoa-touch matrix linear-algebra ios
我需要将UIView从屏幕中心翻译并缩放到右上角.
_____________________________
| |
| |
| _________ |
| | | | START
| | | |
| |_________| |
| |
| |
|____________________________|
_____________________________
| __ |
| |__| |
| |
| | END
| |
| |
| |
| |
|____________________________|
Run Code Online (Sandbox Code Playgroud)
我验证了我对比例和翻译的个人计算是准确的.但是一旦它们组合在一起,它们就会相互冲突.以下代码使视图最终太靠近中心.
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) {
}
];
Run Code Online (Sandbox Code Playgroud)
最终效果:
_____________________________
| |
| |
| __ |
| |__| |
| |
| |
| |
| |
|____________________________|
Run Code Online (Sandbox Code Playgroud)
更改乘法的顺序会导致视图偏离屏幕的右边缘.
self.platformProgressView.transform = CGAffineTransformConcat(
CGAffineTransformMakeScale(finalScale, finalScale),
CGAffineTransformMakeTranslation(deltaX, deltaY)
);
Run Code Online (Sandbox Code Playgroud)
最终效果(预计):
_____________________________
| |
| | __
| | |__|
| |
| |
| |
| |
| |
|____________________________|
Run Code Online (Sandbox Code Playgroud)
单独使用它们会导致突然跳跃,最终位置更加糟糕.
self.platformProgressView.transform = CGAffineTransformMakeTranslation(deltaX, deltaY);
self.platformProgressView.transform = CGAffineTransformMakeScale(finalScale, finalScale);
Run Code Online (Sandbox Code Playgroud)
最终效果:
_____________________________
| |
| |
| |
| |
| __ |
| |__| |
| |
| |
|____________________________|
Run Code Online (Sandbox Code Playgroud)
her*_*ube 17
要实现的主要是变换的原点是视图矩形的中心点.最好用一个例子来说明.
首先,我们翻译视图.v1是原始位置的视图,v2是其平移位置的视图.p是你想要的填充(finalPadding
在你的代码中).c标记视图的中心点.
+--------------------------------+
| ^ |
| | p |
| v |
| +- v2 --------+ |
| | | |
| | c |<->|
| | | p |
| +-------------+ |
| |
| |
| +- v1 --------+ |
| | | |
| | c | |
| | | |
| +-------------+ |
| |
+--------------------------------+
Run Code Online (Sandbox Code Playgroud)
接下来我们缩放视图.v3是其缩放位置的视图.请注意v3的中心点如何保持不变,而周围视图的尺寸缩小.虽然尺寸是正确的,但视图的定位和产生的填充p'是错误的.
+--------------------------------+
| ^ |
| | p' |
| | |
| v |
| +- v3 --+ |
| | c |<---->|
| +-------+ p' |
| |
| |
| +- v1 --------+ |
| | | |
| | c | |
| | | |
| +-------------+ |
| |
+--------------------------------+
Run Code Online (Sandbox Code Playgroud)
现在我们知道缩放是如何工作的,我们需要修改计算翻译增量的代码.以下是如何做到正确的:
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;
Run Code Online (Sandbox Code Playgroud)
最后,正如您已经注意到的那样,转换与CGAffineTransformConcat
事物连接的顺序.在你的第一次尝试中你有序列1)变换+ 2)比例.结果是,缩放变换(后面出现在序列中)会影响为translate变换指定的增量.
这里有两个解决方案:您自己的第二次尝试,在这里您可以反转序列,使其变为1)缩放+ 2)变换.或者您使用我在答案的第一个修订版中建议的辅助函数.所以这
self.platformProgressView.transform = CGAffineTransformConcat(
CGAffineTransformMakeScale(finalScale, finalScale),
CGAffineTransformMakeTranslation(deltaX, deltaY)
);
Run Code Online (Sandbox Code Playgroud)
相当于
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);
Run Code Online (Sandbox Code Playgroud)
如果您对中心点是视图变换的原点感到不满意,可以通过设置anchorPoint
视图CALayer 的属性来更改它.默认锚点为0.5/0.5,表示视图矩形的中心.显然,锚点不是坐标而是一种倍增因子.
如果我们假设锚点位于视图的左上角,则您对翻译增量的原始计算是正确的.所以,如果你这样做
self.platformProgressView.layer.anchorPoint = CGPointMake(0.0f, 0.0f)
Run Code Online (Sandbox Code Playgroud)
你可以保留原来的计算.
可能有更多的信息材料,但WWDC 2011视频理解UIKit渲染是我最近观看的内容,这极大地帮助我提高了我对边界,中心,变换和框架之间关系的理解.
此外,如果要更改CALayer anchorPoint
属性,则应首先阅读CALayer类引用中的属性文档.
归档时间: |
|
查看次数: |
3855 次 |
最近记录: |