我想根据 DragGesture 的值旋转一个stackedImageView(包含图像和形状)。旋转应该以stackedImageView 的中心为锚点旋转。它似乎基于父视图的中心旋转。
放置在屏幕中间时旋转效果很好(location = CGPoint(x: 0, y: 0);但是,当放置在父视图边缘附近时,旋转变得不可预测(例如 CGPoint(x: -80 ,y:-100))。
我认为这是由于.rotateEffect() 中的anchorPoint。如何计算 UnitPoint 到我的旋转stackedImageView 的中心并将其用作rotateEffect 的锚点?有没有办法从 DragGesture 的 startLocation 计算它?
谢谢!
struct ContentView: View {
@State private var angle: CGFloat = 0
@State private var lastAngle: CGFloat = 0
@State private var length : CGFloat = 100
@State private var location: CGPoint = CGPoint(x: -80, y: -100)
let systemImage = UIImage(systemName: "camera")!
var body: some View {
var body: some View {
VStack {
Text("Rotating View Example")
.frame(height: 200)
rotationView
.frame(width: 300, height: 300)
.border(.blue, width: 2)
}
}
private var rotationView: some View {
let imageSize = newSize(100)
return ZStack {
Image(uiImage: systemImage)
.resizable()
.aspectRatio(contentMode: .fit)
.offset(x: location.x, y: location.y)
Circle()
.foregroundColor(Color.accentColor)
.frame(width: 20, height: 20)
.position(x: location.x + imageSize.width, y: location.y + imageSize.height)
}
.rotationEffect(.degrees(Double(self.angle)))
.gesture(DragGesture()
.onChanged{ value in
let centerPt = CGPoint(x: value.startLocation.x - imageSize.width / 2, y: value.startLocation.y - imageSize.height / 2)
let theta = (atan2(value.location.y - centerPt.y, value.location.x - centerPt.x) - atan2(value.startLocation.y - centerPt.y, value.startLocation.x - centerPt.x)) * 180 / .pi
angle = theta + lastAngle
print("angle: \(angle), centerPt: (\(centerPt.x), \(centerPt.y)), start: (\(value.startLocation.x), \(value.startLocation.y), end: (\(value.location.x), \(value.location.y)")
}
.onEnded { v in
self.lastAngle = self.angle
}
)
.animation(.none)
.frame(width: imageSize.width, height: imageSize.height)
}
func newSize(_ maxDimension: CGFloat) -> CGSize {
let imageSize = systemImage.size
if imageSize.width > imageSize.height {
return recalculateSize(imageSize: systemImage.size, width: maxDimension)
} else {
return recalculateSize(imageSize: systemImage.size, height: maxDimension)
}
}
func recalculateSize(imageSize: CGSize, width: CGFloat? = nil, height: CGFloat? = nil) -> CGSize {
if let width = width, height == nil {
let newHeight = imageSize.height / (imageSize.width / width)
return CGSize(width: width, height: newHeight)
} else if let height = height, width == nil {
let newWidth = imageSize.width / (imageSize.height / height)
return CGSize(width: newWidth, height: height)
}
return imageSize
}
}