admin管理员组文章数量:1393859
We have made it possible to scale, rotate, and move images using SwiftUI. The movement gesture is implemented independently, while the zoom and rotation gestures can be performed simultaneously using SimultaneousGesture.
When repeatedly performing image zoom gestures, at some point the image seemed to freeze, and any further zoom, rotation, or movement gestures were no longer possible.
I would like to know the code that will solve this problem and make it possible to permanently scale images.
import SwiftUI
struct ContentView: View {
@State private var offset: CGSize = .zero // drag value
@State private var lastOffset: CGSize = .zero // hold last drag value
@State private var scale: CGFloat = 1.0 // pinch scale value
@State private var lastScale: CGFloat = 1.0 // hold last scale value
@State private var angle: Angle = .zero // pinch angle value
@State private var lastAngle: Angle = .zero // hold last angle value
@State private var isReset: Bool = false
let minScale = 0.2 // minimum scale value
let maxScale = 5.0 // maximum scale value
var dragGesture: some Gesture { // Move
DragGesture()
.onChanged {
offset = CGSize(width: lastOffset.width + $0.translation.width, height: lastOffset.height + $0.translation.height)
}
.onEnded { _ in
lastOffset = offset
}
}
var scaleGesture: some Gesture { // Scaling
MagnificationGesture()
.onChanged {
if ($0 > minScale) && ($0 < maxScale) { // scaling range for pinch
scale = $0 * lastScale
}
}
.onEnded { _ in
lastScale = scale
}
}
var rotateGesture: some Gesture { // rotate
RotationGesture(minimumAngleDelta: .degrees(8)) // minimun start angle = 8degrees
.onChanged {
angle = $0 + lastAngle
}
.onEnded { _ in
lastAngle = angle
}
}
var body: some View {
NavigationStack {
VStack {
GeometryReader { geometry in
Image(systemName: "globe")
.resizable()
.scaledToFit()
.frame(maxWidth: .infinity, maxHeight: .infinity) // placement size
.rotationEffect(angle, anchor: .center) // rotationEffect must be first
.scaleEffect(scale) // scaleEffect must be after rotationEffect
.offset(offset) // offset is last
.gesture(dragGesture)
.gesture(SimultaneousGesture(rotateGesture, scaleGesture))
}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Spacer()
}
ToolbarItem(placement: .topBarTrailing) {
Button(action: {
isReset = true
}) {
Image(systemName: "arrow.trianglehead.clockwise")
.font(.title)
.foregroundColor(.red)
}
}
}
}
}
.onChange(of: isReset) {
if (isReset == true) {
offset = .zero; lastOffset = .zero
scale = 1.0; lastScale = 1.0
angle = .zero; lastAngle = .zero
}
isReset = false
}
}
}
We have made it possible to scale, rotate, and move images using SwiftUI. The movement gesture is implemented independently, while the zoom and rotation gestures can be performed simultaneously using SimultaneousGesture.
When repeatedly performing image zoom gestures, at some point the image seemed to freeze, and any further zoom, rotation, or movement gestures were no longer possible.
I would like to know the code that will solve this problem and make it possible to permanently scale images.
import SwiftUI
struct ContentView: View {
@State private var offset: CGSize = .zero // drag value
@State private var lastOffset: CGSize = .zero // hold last drag value
@State private var scale: CGFloat = 1.0 // pinch scale value
@State private var lastScale: CGFloat = 1.0 // hold last scale value
@State private var angle: Angle = .zero // pinch angle value
@State private var lastAngle: Angle = .zero // hold last angle value
@State private var isReset: Bool = false
let minScale = 0.2 // minimum scale value
let maxScale = 5.0 // maximum scale value
var dragGesture: some Gesture { // Move
DragGesture()
.onChanged {
offset = CGSize(width: lastOffset.width + $0.translation.width, height: lastOffset.height + $0.translation.height)
}
.onEnded { _ in
lastOffset = offset
}
}
var scaleGesture: some Gesture { // Scaling
MagnificationGesture()
.onChanged {
if ($0 > minScale) && ($0 < maxScale) { // scaling range for pinch
scale = $0 * lastScale
}
}
.onEnded { _ in
lastScale = scale
}
}
var rotateGesture: some Gesture { // rotate
RotationGesture(minimumAngleDelta: .degrees(8)) // minimun start angle = 8degrees
.onChanged {
angle = $0 + lastAngle
}
.onEnded { _ in
lastAngle = angle
}
}
var body: some View {
NavigationStack {
VStack {
GeometryReader { geometry in
Image(systemName: "globe")
.resizable()
.scaledToFit()
.frame(maxWidth: .infinity, maxHeight: .infinity) // placement size
.rotationEffect(angle, anchor: .center) // rotationEffect must be first
.scaleEffect(scale) // scaleEffect must be after rotationEffect
.offset(offset) // offset is last
.gesture(dragGesture)
.gesture(SimultaneousGesture(rotateGesture, scaleGesture))
}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Spacer()
}
ToolbarItem(placement: .topBarTrailing) {
Button(action: {
isReset = true
}) {
Image(systemName: "arrow.trianglehead.clockwise")
.font(.title)
.foregroundColor(.red)
}
}
}
}
}
.onChange(of: isReset) {
if (isReset == true) {
offset = .zero; lastOffset = .zero
scale = 1.0; lastScale = 1.0
angle = .zero; lastAngle = .zero
}
isReset = false
}
}
}
Share
Improve this question
asked Mar 27 at 13:50
BB-8BB-8
1075 bronze badges
3
- You will be able to instantly find a problem if you simply add some print statements inside the changed and on ended clauses. I can't really figure out all your code, but I'm guessing you almost certainly need to do something as well when the gesture begins as well as change and end, and don't fet cancel as well. As I say, if you just add print statements, you'll instantly find the problem. Writing touch related code is very subtle and tricky. – Fattie Commented Mar 27 at 17:51
- I checked the situation using the print statement, but couldn't determine the cause, so I submitted Feedback to Apple. FB17031685 – BB-8 Commented Mar 28 at 5:59
- Since MagnificationGesture is already deprecated, I checked using MagnifyGesture but I am getting the same issue. – BB-8 Commented Mar 28 at 6:00
1 Answer
Reset to default -1This issue does not occur if you define the image scaling gesture alone.
Problems arise when SimultaneousGesture allows multiple gestures to be performed simultaneously.
.gesture(scaleGesture) ---> No problems occur
.gesture(SimultaneousGesture(rotateGesture, scaleGesture)) ----> Problems occur
本文标签: iosImage scaling is disabled in SwiftUIStack Overflow
版权声明:本文标题:ios - Image scaling is disabled in SwiftUI - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744084341a2588233.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论