первые три фотографии, которые я показываю, представляют вид обрезки в его исходное состояние (поэтому не похоже на использование смещения для перемещения фотографии)
[img]https://i. sstatic.net/TScRpfJj.png[/img]


как вы можете видеть, если мы возьмем туфлю девушки в качестве ориентира, мы заметим, что она всегда находится за пределами области круглой маски, даже если я использую разделенный вид для 2/3, 1/2, 1/3 изображение подходит идеально
Если, однако, мы посмотрим на эти 3 фотографии, на которых я использовал жест перетаскивания, всегда беря опорную точку , то есть туфельку девушки, мы замечаем, что при каждом изменении разделенного вида она не всегда остается в том же положении. Это, конечно, меняется из-за размеров изображения, но я просто не могу понять, почему это происходит.
[img]https:/ /i.sstatic.net/wu7H3GY8.png[/img]


Если я не использую жест перетаскивания, маска и фотография во всем идеальны три первых фотографии, но как только значение смещения меняется с помощью dragGesture, я вижу эту разницу на последних трех фотографиях.
Можете ли вы помочь мне понять? Надеюсь, я смог правильно объясниться
Код: Выделить всё
public struct CropView: PlatformView {
var selectedPhoto: UIImage
let prefersShape: Mask
public init(selectedPhoto: UIImage, prefersShape: Mask = .circle) {
self.selectedPhoto = selectedPhoto
self.prefersShape = prefersShape
}
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@Environment(\.verticalSizeClass) var verticalSizeClass
@State private var viewSize: CGSize = .zero
@State private var offset: CGSize = .zero
@State private var lastOffset: CGSize = .zero
private var maskScale: CGFloat {
isCompact ? 0.6 : 0.65
}
@State private var photoSize: CGSize = .zero
private var dragGesture: some Gesture {
DragGesture()
.onChanged { value in
let currentOffset = lastOffset + value.translation
offset = currentOffset
// updateOffsetLimits(currentOffset: currentOffset)
}
.onEnded { _ in lastOffset = offset }
}
public var body: some View {
ZStack {
Image(uiImage: selectedPhoto)
.resizable()
.aspectRatio( contentMode: .fill)
.frame(photoSize)
.offset(offset)
.mask {
Rectangle().opacity(0.5)
.overlay {
prefersShape.shape
.blendMode(.destinationOver)
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.gesture(dragGesture)
.onGeometryChange(for: CGSize.self) { proxy in
proxy.size
} action: { newValue in
viewSize = newValue
let isLandscape = newValue.width > newValue.height
let reference = isLandscape ? newValue.height : newValue
.width
photoSize = prefersShape.size(relativeTo: .init(width: reference, height: reference)).scaledBy(maskScale)
}
}
}
extension View {
func frame(_ size: CGSize) -> some View {
frame(width: size.width, height: size.height)
}
}
@MainActor
protocol PlatformView: View {
var horizontalSizeClass: UserInterfaceSizeClass? { get }
var verticalSizeClass: UserInterfaceSizeClass? { get }
var isCompact: Bool { get }
var isRegular: Bool { get }
}
extension PlatformView {
var isCompact: Bool { horizontalSizeClass == .compact || verticalSizeClass == .compact }
var isRegular: Bool { horizontalSizeClass == .regular && verticalSizeClass == .regular }
}
Код: Выделить всё
public enum Mask {
case circle, square,
var shape: AnyShape {
switch self {
case .circle: return AnyShape(.circle)
case .square, .rectangle : return AnyShape(.rect)
}
}
func size(relativeTo size: CGSize) -> CGSize {
let isLandscape = size.width > size.height
let reference = isLandscape ? size.height : size
.width
switch self {
case .circle, .square :
return .init(width: size.width, height: size.width)
}
}
extension CGSize {
static func + (lhs: CGSize, rhs: CGSize) -> CGSize {
.init(width: lhs.width + rhs.width, height: lhs.height + rhs.height)
}
func scaledBy(_ scale: CGFloat) -> CGSize {
.init(width: self.width * scale, height: self.height * scale)
}
}

Подробнее здесь: https://stackoverflow.com/questions/792 ... -and-image
Мобильная версия