chore: added media panning
19a47a6d
1 file(s) · +50 −26
| 124 | 124 | let data: Data |
|
| 125 | 125 | @State private var scale: CGFloat = 1.0 |
|
| 126 | 126 | @State private var lastScale: CGFloat = 1.0 |
|
| 127 | + | @State private var offset: CGSize = .zero |
|
| 128 | + | @State private var lastOffset: CGSize = .zero |
|
| 127 | 129 | ||
| 128 | 130 | var body: some View { |
|
| 129 | 131 | if let uiImage = UIImage(data: data) { |
|
| 130 | - | Image(uiImage: uiImage) |
|
| 131 | - | .resizable() |
|
| 132 | - | .aspectRatio(contentMode: .fit) |
|
| 133 | - | .scaleEffect(scale) |
|
| 134 | - | .gesture( |
|
| 135 | - | MagnificationGesture() |
|
| 136 | - | .onChanged { value in |
|
| 137 | - | scale = lastScale * value |
|
| 138 | - | } |
|
| 139 | - | .onEnded { _ in |
|
| 140 | - | lastScale = scale |
|
| 141 | - | if scale < 1.0 { |
|
| 142 | - | withAnimation { |
|
| 143 | - | scale = 1.0 |
|
| 144 | - | lastScale = 1.0 |
|
| 132 | + | GeometryReader { geometry in |
|
| 133 | + | Image(uiImage: uiImage) |
|
| 134 | + | .resizable() |
|
| 135 | + | .aspectRatio(contentMode: .fit) |
|
| 136 | + | .scaleEffect(scale) |
|
| 137 | + | .offset(offset) |
|
| 138 | + | .frame(width: geometry.size.width, height: geometry.size.height) |
|
| 139 | + | .gesture( |
|
| 140 | + | MagnificationGesture() |
|
| 141 | + | .onChanged { value in |
|
| 142 | + | scale = lastScale * value |
|
| 143 | + | } |
|
| 144 | + | .onEnded { _ in |
|
| 145 | + | lastScale = scale |
|
| 146 | + | if scale < 1.0 { |
|
| 147 | + | withAnimation { |
|
| 148 | + | scale = 1.0 |
|
| 149 | + | lastScale = 1.0 |
|
| 150 | + | offset = .zero |
|
| 151 | + | lastOffset = .zero |
|
| 152 | + | } |
|
| 145 | 153 | } |
|
| 146 | 154 | } |
|
| 147 | - | } |
|
| 148 | - | ) |
|
| 149 | - | .onTapGesture(count: 2) { |
|
| 150 | - | withAnimation { |
|
| 151 | - | if scale > 1.0 { |
|
| 152 | - | scale = 1.0 |
|
| 153 | - | lastScale = 1.0 |
|
| 154 | - | } else { |
|
| 155 | - | scale = 2.0 |
|
| 156 | - | lastScale = 2.0 |
|
| 155 | + | .simultaneously(with: |
|
| 156 | + | DragGesture() |
|
| 157 | + | .onChanged { value in |
|
| 158 | + | if scale > 1.0 { |
|
| 159 | + | offset = CGSize( |
|
| 160 | + | width: lastOffset.width + value.translation.width, |
|
| 161 | + | height: lastOffset.height + value.translation.height |
|
| 162 | + | ) |
|
| 163 | + | } |
|
| 164 | + | } |
|
| 165 | + | .onEnded { _ in |
|
| 166 | + | lastOffset = offset |
|
| 167 | + | } |
|
| 168 | + | ) |
|
| 169 | + | ) |
|
| 170 | + | .onTapGesture(count: 2) { |
|
| 171 | + | withAnimation { |
|
| 172 | + | if scale > 1.0 { |
|
| 173 | + | scale = 1.0 |
|
| 174 | + | lastScale = 1.0 |
|
| 175 | + | offset = .zero |
|
| 176 | + | lastOffset = .zero |
|
| 177 | + | } else { |
|
| 178 | + | scale = 2.0 |
|
| 179 | + | lastScale = 2.0 |
|
| 180 | + | } |
|
| 157 | 181 | } |
|
| 158 | 182 | } |
|
| 159 | - | } |
|
| 183 | + | } |
|
| 160 | 184 | } else { |
|
| 161 | 185 | VStack(spacing: 16) { |
|
| 162 | 186 | Image(systemName: "photo.badge.exclamationmark") |