Я хотел бы создать интерфейс для отображения набора путей Безье (векторное изображение), который позволил бы пользователю изменять свойство каждого пути Безье (например, цвет заливки), а также изменять размер изображения в целом, чтобы включить взаимодействие с меньшими путями.
В целях тестирования я создал сетку прямоугольников как 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 не подходит в случае, если на нем размещено большое количество элементов.