Как использовать Swiftui MagnifyGesture, чтобы масштабировать зажатую часть изображения, а не центр?IOS

Программируем под IOS
Ответить
Anonymous
 Как использовать Swiftui MagnifyGesture, чтобы масштабировать зажатую часть изображения, а не центр?

Сообщение Anonymous »

Основная причина состоит в том, чтобы применить жест увеличения к зажатой части изображения. По умолчанию он работает отлично, но всегда увеличивает в центре/выходе данного изображения. Как манипулировать этим, чтобы увеличить фактическую часть изображения? Если я увеличиваю левый верхний угол изображения, он должен оставаться в том же месте, где эта часть изображения, которую я хочу увеличить. < /P>
Где проблема? Пока вы его ущипните, он неправильно масштабирует изображение. Кажется, что смещение рассчитывается правильно, но понятия не имею, почему это не работает. < /P>
перетаскивание работает отлично, а не увеличивать. Это все. < /P>
Вот мой код: < /p>

Код: Выделить всё

struct WrapperForCropView: View {
let image = UIImage(
size: CGSize(width: 2100, height: 1200),
gradientPoints:  [
GradientPoint(location: 0, color: #colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 0.2530534771)),
GradientPoint(location: 0.2, color: #colorLiteral(red: 0.9686274529, green: 0.78039217, blue: 0.3450980484, alpha: 0.5028884243)),
GradientPoint(location: 0.4, color: #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 0.3388534331)),
GradientPoint(location: 0.6, color: #colorLiteral(red: 0.2588235438, green: 0.7568627596, blue: 0.9686274529, alpha: 0.3458681778)),
GradientPoint(location: 0.8, color: #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 0.3851232394))
]
)!
var body: some View {
NavigationView {
ZStack {
Color.red
GeometryReader { proxy in
VStack {
DemoCroppingView(uiImage: image, bounds: proxy.size)
}
.frame(width: proxy.size.width, height: proxy.size.height)
.clipped()
}
}
}
}
}

@available(iOS 17.0, *)
struct DemoCroppingView: View {
var uiImage: UIImage
var bounds: CGSize
@State private var offsetLimit: CGSize = .zero
@State private var offset: CGSize = .zero
@State private var lastOffset: CGSize = .zero
@State private var scale: CGFloat = 1
@State private var lastScale: CGFloat = 1
@State private var imageViewSize: CGSize = .zero
private let mask = CGSize(width: 300, height: 300)

private var dragGesture: some Gesture {
DragGesture()
.onChanged { gesture in
offsetLimit = getOffsetLimit()

let width = min(
max(-offsetLimit.width, lastOffset.width + gesture.translation.width),
offsetLimit.width
)
let height = min(
max(-offsetLimit.height, lastOffset.height + gesture.translation.height),
offsetLimit.height
)

offset = CGSize(width: width, height: height)
}
.onEnded { _ in
lastOffset = offset
}
}

private var scaleGesture: some Gesture {
MagnifyGesture()
.onChanged { gesture in
let startX = gesture.startLocation.x
let startY = gesture.startLocation.y
let currentScale = lastScale * gesture.magnification
scale = currentScale
let offsetWidth = (startX - (startX - lastOffset.width) * scale)
let offsetHeight = (startY - (startY - lastOffset.height) * scale)
offset = CGSize(width: offsetWidth, height: offsetHeight)
}
.onEnded { _ in
lastScale = scale
lastOffset = offset
}
}

var body: some View {
ZStack(alignment: .center) {
ZStack {
Rectangle()
.fill(.black)
Image(uiImage: uiImage)
.resizable()
.scaledToFill()
.scaleEffect(scale)
.offset(offset)
}
.overlay {
Color.black.opacity(0.5)
}
Image(uiImage: uiImage)
.resizable()
.scaledToFill()
.scaleEffect(scale)
.offset(offset)
.mask(
Circle()
.frame(width: mask.width, height: mask.height)
)
.overlay {
Circle()
.stroke(Color.red, lineWidth: 1)
.frame(width: mask.width, height: mask.height)
}
}
.simultaneousGesture(dragGesture)
.simultaneousGesture(scaleGesture)
.clipped()
.onChange(of: bounds) { _, _ in
calculateImageViewSize()
}
.onChange(of:  uiImage) { _, _ in
calculateImageViewSize()
lastOffset = .zero
offset = .zero
offsetLimit = .zero
}
}

private func calculateImageViewSize() {
let viewRatio = bounds.width / bounds.height
let width = uiImage.size.width
let height = uiImage.size.height
let imageRatio = width / height
let factor = viewRatio < imageRatio ? bounds.height / height : bounds.width / width
imageViewSize.height = height * factor
imageViewSize.width = width * factor
}

private func getOffsetLimit() -> CGSize {
var offsetLimit: CGSize = .zero
offsetLimit.width = ((imageViewSize.width * scale) - mask.width) / 2
offsetLimit.height = ((imageViewSize.height * scale) - mask.height) / 2
return offsetLimit
}
}

И вот полный пример картинки:

Какова цель? Вы просто можете перемещать и масштабировать изображение со следующими ограничениями: < /p>

🏆 Изображение за шкалой не должно быть меньше, чем размер маски < /li>
🏆 Смещение после масштаба не должно оставлять какое -либо пустое пространство в маске < /li>
>

Подробнее здесь: https://stackoverflow.com/questions/797 ... not-the-ce
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»