我想创建一个界面来显示一组bezier路径(矢量图像),这将使用户能够更改每个bezier路径的属性(例如,填充颜色),还可以将图像整体调整为启用与较小路径的交互。
出于测试目的,我创建了一个矩形网格作为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不是一个好的选择。
答案 0 :(得分:0)
尝试添加.contentShape
}.frame(width: geometry.size.width, height: geometry.size.height, alignment: .topLeading)
.contentShape(Rectangle()) // << here !!
.scaleEffect(scale)