将视图从其原点旋转到另一个视图
Rotate a view from its origin towards another view
我正在尝试将视图旋转到另一个视图中心点(记住不是围绕,而是朝向)。
假设我有 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
}
}
但这并没有像预期的那样工作,旋转距离很远。检查以下问题的屏幕截图
我认为这个问题与角度的计算方式有关,但我想不通是什么?
非常感谢任何帮助。
角度需要以弧度为单位
旋转角度需要指定弧度:
变化:
rectView.transform = rectView.transform.rotated(by: angle)
至:
rectView.transform = rectView.transform.rotated(by: angle / 180.0 * .pi)
或将您的 angle(to:)
方法更改为 return 弧度而不是度数。
使用frame
代替bounds
此外,计算角度时需要使用 rectView
的 frame
。视图的 bounds
是它的内部坐标 space,这意味着它的原点始终是 (0, 0)
。您需要 frame
,它是视图在其父坐标系中的坐标。
变化:
let angle = rectView.bounds.origin.angle(to: end)
至:
let angle = rectView.frame.origin.angle(to: end)
注意:因为你的anchorPoint
是rectView
的角,这会把rectView
的上边缘指向rectView
的中心endView
。解决此问题的一种方法是将 anchorPoint
更改为 rectView
左边缘的中心,然后使用该点计算 angle
.
我正在尝试将视图旋转到另一个视图中心点(记住不是围绕,而是朝向)。
假设我有 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
}
}
但这并没有像预期的那样工作,旋转距离很远。检查以下问题的屏幕截图
我认为这个问题与角度的计算方式有关,但我想不通是什么?
非常感谢任何帮助。
角度需要以弧度为单位
旋转角度需要指定弧度:
变化:
rectView.transform = rectView.transform.rotated(by: angle)
至:
rectView.transform = rectView.transform.rotated(by: angle / 180.0 * .pi)
或将您的 angle(to:)
方法更改为 return 弧度而不是度数。
使用frame
代替bounds
此外,计算角度时需要使用 rectView
的 frame
。视图的 bounds
是它的内部坐标 space,这意味着它的原点始终是 (0, 0)
。您需要 frame
,它是视图在其父坐标系中的坐标。
变化:
let angle = rectView.bounds.origin.angle(to: end)
至:
let angle = rectView.frame.origin.angle(to: end)
注意:因为你的anchorPoint
是rectView
的角,这会把rectView
的上边缘指向rectView
的中心endView
。解决此问题的一种方法是将 anchorPoint
更改为 rectView
左边缘的中心,然后使用该点计算 angle
.