Жест магинификации не отвечает с использованием ZStack - PullRequest
0 голосов
/ 01 августа 2020

Я хотел бы создать интерфейс для отображения набора путей Безье (векторное изображение), который позволил бы пользователю изменять свойство каждого пути Безье (например, цвет заливки), а также изменять размер изображения в целом, чтобы включить взаимодействие с меньшими путями.

В целях тестирования я создал сетку прямоугольников как ZStack; Я хотел попробовать изменить цвет прямоугольника при касании, а также проверить, насколько отзывчивый пользовательский интерфейс, предполагая, что в реальном случае может быть более 1000 путей.

Ниже приведен код реализации:

import SwiftUI

struct PathView: View {
    @State var scale: CGFloat = 1.0
    var body: some View {
        GeometryReader {
            geometry in
            let rectangles: [GridItem] = getSquareGrid(width: geometry.size.width, height: geometry.size.height, count: 10)
            let rects = ZStack {
                ForEach(rectangles) { rectangle in
                    RoundedRectangle(cornerRadius: rectangle.cornerRadius, style: /*@START_MENU_TOKEN@*/.continuous/*@END_MENU_TOKEN@*/)
                        .fill(rectangle.color)
                        .frame(width: rectangle.size, height: rectangle.size)
                        .offset(x: rectangle.offsetX, y: rectangle.offsetY)
                        .onTapGesture {
                            print("rectangle \(rectangle.id) tapped")
                            // TODO: implement the logic to change the fill of the tapped shape/path
                                
                        }
                }
            }.frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading)
            .scaleEffect(scale)
            .gesture(MagnificationGesture()
                        .onChanged({ (scale) in
                            self.scale = scale.magnitude
                        })
                        .onEnded({ (scaleFinal) in
                            self.scale = scaleFinal
                        }))
            rects.drawingGroup()
            
        }
    }
}

struct GridItem: Identifiable {
    let size: CGFloat
    let offsetX: CGFloat
    let offsetY: CGFloat
    let cornerRadius: CGFloat
    let color: Color
    let id = UUID()
    
    init(size: CGFloat, offsetX: CGFloat, offsetY: CGFloat, cornerRadius: CGFloat, color: Color) {
        self.size = size
        self.offsetX = offsetX
        self.offsetY = offsetY
        self.cornerRadius = cornerRadius
        self.color = color
    }
}

func getSquareGrid(width: CGFloat, height: CGFloat, count: Int) -> [GridItem] {
    var rectangleArray: [GridItem] = []
    let size = min(width, height)
    let rectangleSize = round(size/CGFloat(count))
    for row in 0...count - 1 {
        for column in 0...count - 1 {
            let rect = GridItem(size: rectangleSize, offsetX: CGFloat(column) * rectangleSize, offsetY: CGFloat(row) * rectangleSize, cornerRadius: 10, color: Color.red)
            
            rectangleArray.append(rect)
        }
    }
    return rectangleArray
}

struct PathView_Previews: PreviewProvider {
    static var previews: some View {
        PathView()
    }
}

При попытке изменить размер всей сетки я заметил, что она не реагирует. Я хотел спросить, был ли жест увеличения реализован оптимально или ZStak не подходит в случае, если на нем размещено большое количество элементов.

1 Ответ

0 голосов
/ 01 августа 2020

Попробуйте добавить .contentShape

}.frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading)
.contentShape(Rectangle())       // << here !!
.scaleEffect(scale)
...