我正在构建SwiftUI应用程序,在那里我需要在视图中旋转、放置签名和调整签名大小.我已经实现了最后两个手势,但当我激活最后一个手势时,它 destruct 了一切.最理想的情况是,如果黑色圆圈能够同时配置Angular 和大小,但两者开始相互冲突.在这个测试片段中,我已经 Select 了使用的代码,并删除了连接到签名后面的图像的代码,因为它并不重要.
主要问题是如何让.simultaneousGesture(applyRotation(width: width, height: height))
正常工作.
struct NEwVIew: View {
@State private var location: CGPoint = CGPoint(x: 150, y: 300)
@GestureState private var fingerLocation: CGPoint? = nil
@GestureState private var startLocation: CGPoint? = nil
// Initialise to a size proportional to the screen dimensions.
@State private var width: CGFloat = 100
@State private var height: CGFloat = 100
@State private var previousRotation: Double = 0.0
@State private var knobRotation: Double = 0.0
@State var rotationActive = false
private func location2Degrees(location: CGPoint, midX: CGFloat, midY: CGFloat) -> CGFloat {
let radians = location.y < midY
? atan2(location.x - midX, midY - location.y)
: .pi - atan2(location.x - midX, location.y - midY)
let degrees = (radians * 180 / .pi) - 135
return degrees < 0 ? degrees + 360 : degrees
}
private func applyRotation(width: CGFloat, height: CGFloat) -> some Gesture {
DragGesture()
.onChanged { value in
let midX = width / 2
let midY = height / 2
let startAngle = location2Degrees(location: value.startLocation, midX: midX, midY: midY)
let endAngle = location2Degrees(location: value.location, midX: midX, midY: midY)
let dAngle = endAngle - startAngle
knobRotation = previousRotation + dAngle
}
.onEnded { value in
previousRotation = knobRotation
}
}
var simpleDrag: some Gesture {
DragGesture()
.onChanged { value in
var newLocation = startLocation ?? location // 3
newLocation.x += value.translation.width
newLocation.y += value.translation.height
self.location = newLocation
}.updating($startLocation) { (value, startLocation, transaction) in
startLocation = startLocation ?? location // 2
}
}
var fingerDrag: some Gesture {
DragGesture()
.updating($fingerLocation) { (value, fingerLocation, transaction) in
fingerLocation = value.location
}
}
var body: some View {
VStack {
GeometryReader { geometry in
ZStack {
VStack {
ZStack {
if let image = loadImageFromDocumentDirectory(filename: "signature.png") {
ZStack(alignment: .bottomTrailing) {
Rectangle()
.stroke(style: StrokeStyle(lineWidth: 1, dash: [5]))
.fill(.blue)
.frame(width: width, height: height)
// I've commented it because you don't have this image in app files.
// Image(uiImage: image)
// .resizable()
// .scaledToFit()
// .frame(width: width, height: height)
// BLACK CIRCLE I WAS TALKING ABOUT
Circle()
.frame(width: 25, height: 25)
.gesture(
DragGesture()
.onChanged { value in
// Enforce minimum dimensions.
DispatchQueue.main.async {
withAnimation {
width = max(50, width + value.translation.width / 10)
height = width
}
}
}
)
.zIndex(1)
}
.rotationEffect(Angle(degrees: knobRotation))
// NEEDS TO WORK TOO AT THE SAME TIME WITH TWO FIRST!
// .simultaneousGesture(applyRotation(width: width, height: height))
}
}
}
.frame(maxWidth: width, maxHeight: height, alignment: .center)
.position(location)
.gesture(
simpleDrag.simultaneously(with: fingerDrag)
)
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
}
.background(Color.black.opacity(0.3))
.overlay(
VStack {
Spacer()
Button {
} label: {
Text("Save")
}
}
)
.ignoresSafeArea(.all)
}
func loadImageFromDocumentDirectory(filename: String) -> UIImage? {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsDirectory.appendingPathComponent(filename)
do {
let imageData = try Data(contentsOf: fileURL)
return UIImage(data: imageData)
} catch {
print("Error loading image: \(error)")
return nil
}
}
}