为CGAffineTransformMakeRotation Swift设置旋转点

8
我正在使用以下代码将UIImageView旋转到不同的角度。
self.imageOne.transform = CGAffineTransformMakeRotation(CGFloat(-rotation))
self.imageTwo.transform = CGAffineTransformMakeRotation(CGFloat(-rotation-0.1))
self.imageThree.transform = CGAffineTransformMakeRotation(CGFloat(-change+0.1))

有没有办法让图片从顶部旋转而不是中间? 我想避免使用精灵图,因为我从来没有用过它们,也不知道如何在单视图应用程序中使用它们。 感谢您的时间。

2个回答

25
你需要寻找的是视图层中的anchorPoint属性。该属性表示在移动视图时使用的手柄

默认情况下,该属性为视图的中心点,因此你总是看到视图从中心旋转。

你可以使用我在SO上发现的这个很棒的方法来将视图的锚点更改为顶部(使用CGPointMake(0,0.5f))。

// Swift version
// Place this before you set the transform property
setAnchorPoint(CGPointMake(0, 0.5), view: imageOne)
setAnchorPoint(CGPointMake(0, 0.5), view: imageTwo)
setAnchorPoint(CGPointMake(0, 0.5), view: imageThree)

func setAnchorPoint(anchorPoint: CGPoint, view: UIView) {
    var newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x, view.bounds.size.height * anchorPoint.y)
    var oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x, view.bounds.size.height * view.layer.anchorPoint.y)

    newPoint = CGPointApplyAffineTransform(newPoint, view.transform)
    oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform)

    var position : CGPoint = view.layer.position

    position.x -= oldPoint.x
    position.x += newPoint.x;

    position.y -= oldPoint.y;
    position.y += newPoint.y;

    view.layer.position = position;
    view.layer.anchorPoint = anchorPoint;
}

这是相同代码的Objective-C版本

// Obj-c version
// Place this before you set the transform property
[self setAnchorPoint:CGPointMake(0, 0.5f) forView:imageOne];
[self setAnchorPoint:CGPointMake(0, 0.5f) forView:imageTwo];
[self setAnchorPoint:CGPointMake(0, 0.5f) forView:imageThree];

-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
    CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x,
                                   view.bounds.size.height * anchorPoint.y);
    CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x,
                                   view.bounds.size.height * view.layer.anchorPoint.y);

    newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
    oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);

    CGPoint position = view.layer.position;

    position.x -= oldPoint.x;
    position.x += newPoint.x;

    position.y -= oldPoint.y;
    position.y += newPoint.y;

    view.layer.position = position;
    view.layer.anchorPoint = anchorPoint;
}

一旦您了解了anchorPoint属性的含义,我鼓励您尝试理解此代码的作用。(该方法由用户Anand K编写)


你的代码不工作,图像旋转方式仍然和以前一样,你测试过吗?@mttcrsp - CarveDrone
3
当然,我已经测试过了。我为测试它而创建了一个项目。如果你想的话,可以在这里下载它:链接。只需在模拟器上运行它,我放置了一个按钮来旋转不同的视图,如果你连续按几次,就会看到它的工作原理。 - mttcrsp
谢谢,我搞定了,只需要交换点的x和y坐标即可,例如:setAnchorPoint(CGPointMake(0.5, 0), view: imageOne)。感谢您的时间! - CarveDrone
如果视图使用自动布局,在 view.layer.position = position 之前,我们需要添加 view.translatesAutoresizingMaskIntoConstraints = true - Adi Nugroho

5

这是一个基于mttcrp答案的Swift 3扩展。我花了一些时间才弄清楚CGPoint不是视图中的坐标,而是比例。例如,如果您围绕点CGPoint(x:0.5,y:1)旋转视图,则会围绕视图底部中心旋转。希望这能帮到你!

extension UIView{
    func setAnchorPoint(anchorPoint: CGPoint) {

        var newPoint = CGPoint(x: self.bounds.size.width * anchorPoint.x, y: self.bounds.size.height * anchorPoint.y)
        var oldPoint = CGPoint(x: self.bounds.size.width * self.layer.anchorPoint.x, y: self.bounds.size.height * self.layer.anchorPoint.y)

        newPoint = newPoint.applying(self.transform)
        oldPoint = oldPoint.applying(self.transform)

        var position : CGPoint = self.layer.position

        position.x -= oldPoint.x
        position.x += newPoint.x;

        position.y -= oldPoint.y;
        position.y += newPoint.y;

        self.layer.position = position;
        self.layer.anchorPoint = anchorPoint;
    }
}

而你可以这样使用它:

let view = UIView() //This could be anything that inherits from UIView
view.setAnchorPoint(anchorPoint: CGPoint(x: 0.5, y: 1))

1
使用此函数会将整个视图沿着新的锚点相反方向偏移其一半维度。(对于CGPoint(x: 0, y: 1),视图向上偏移一半高度)。 - Skwiggs
@Skwiggs 你说得对。你找到了让它按预期工作的解决方案吗? - Vetuka
1
self.layer.position = position; 之前添加 self.translatesAutoresizingMaskIntoConstraints = true 对我有用。 - Oscar Yuandinata
你应该欣赏Paul Hudson如何更改视图的锚点而不移动它: https://www.hackingwithswift.com/example-code/calayer/how-to-change-a-views-anchor-point-without-moving-it - Rashid Latif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接