【问题标题】:Rotate a view from its origin towards another view将视图从其原点旋转到另一个视图
【发布时间】:2019-01-29 17:22:43
【问题描述】:

我正在尝试将视图旋转到另一个视图中心点(记住不是围绕,而是朝向)。

假设我有 2 个这样放置的视图

现在我想像这样旋转顶视图以指向底视图

这就是我所做的

  • 将顶视图锚点更改为其原点。这样它就可以旋转并将其边缘指向底部视图
  • 计算第一个视图原点与底部视图中心之间的角度
  • 并将计算出的变换应用于顶视图。

    下面是我正在使用的代码

    let rect = CGRect(x: 70, y: 200, width: 300, height: 100)
    let rectView = UIView(frame: rect)
    rectView.layer.borderColor = UIColor.green.cgColor;
    rectView.layer.borderWidth = 2;
    
    let endView = UIView(frame: CGRect(x: 250, y: 450, width: 70, height: 70))
    endView.layer.borderColor = UIColor.green.cgColor;
    endView.layer.borderWidth = 2;
    let end = endView.center;
    
    self.view.addSubview(endView)
    self.view.addSubview(rectView!)
    rectView.setAnchorPoint(CGPoint.zero)
    
    let angle = rectView.bounds.origin.angle(to: end);
    UIView.animate(withDuration: 3) {
        rectView.transform = rectView.transform.rotated(by: angle)
    }   
    

我正在使用Get angle from 2 positions 的这个扩展来计算两点之间的角度

extension CGPoint {
  func angle(to comparisonPoint: CGPoint) -> CGFloat {
    let originX = comparisonPoint.x - self.x
    let originY = comparisonPoint.y - self.y
    let bearingRadians = atan2f(Float(originY), Float(originX))
    var bearingDegrees = CGFloat(bearingRadians).degrees
    while bearingDegrees < 0 {
        bearingDegrees += 360
    }
    return bearingDegrees
  }
}

extension CGFloat {
    var degrees: CGFloat {
        return self * CGFloat(180.0 / M_PI)
    }
}

extension UIView {
    func setAnchorPoint(_ point: CGPoint) {
        var newPoint = CGPoint(x: bounds.size.width * point.x, y: bounds.size.height * point.y)
        var oldPoint = CGPoint(x: bounds.size.width * layer.anchorPoint.x, y: bounds.size.height * layer.anchorPoint.y);

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

        var position = layer.position

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

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

        layer.position = position
        layer.anchorPoint = point
    }
}

但这并没有按预期工作,轮换太远了。检查以下问题的屏幕截图

我认为这个问题与角度的计算方式有关,但我不知道是什么?

非常感谢任何帮助。

【问题讨论】:

  • UIView 没有setAnchorPoint 方法?这是怎么定义的?
  • @vacawama,它是 uiview 的扩展。我现在已经添加了。请检查已编辑的问题

标签: ios swift rotation transform


【解决方案1】:

角度必须是弧度

旋转角度需要指定弧度:

变化:

rectView.transform = rectView.transform.rotated(by: angle)

到:

rectView.transform = rectView.transform.rotated(by: angle / 180.0 * .pi)

或更改您的 angle(to:) 方法以返回弧度而不是度数。


使用frame 而不是bounds

另外,在计算角度时,您需要使用rectViewframe。视图的bounds 是它的内部坐标空间,这意味着它的原点总是(0, 0)。您需要frame,它是视图在其父坐标系中的坐标。

变化:

let angle = rectView.bounds.origin.angle(to: end)

到:

let angle = rectView.frame.origin.angle(to: end)

注意:因为您的anchorPointrectView 的角,这将使rectView 的上边缘指向endView 的中心。解决此问题的一种方法是将anchorPoint 更改为rectView 左边缘的中心,然后使用该点计算angle

【讨论】:

  • 太棒了!感谢您更新您的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多