Я создал объект, который представляет текущее состояние рисования:
class ColoringImageViewModel: ObservableObject {
@Published var shapeItemsByKey = [UUID: ShapeItem]()
var shapeItemKeys: [UUID] = []
var scale: CGFloat = 0
var offset: CGSize = CGSize.zero
var dragGestureMode: DragGestureEnum = DragGestureEnum.FillAreas
@Published var selectedColor: Color?
var selectedImage: String?
init(selectedImage: String) {
let svgURL = Bundle.main.url(forResource: selectedImage, withExtension: "svg")!
let _paths = SVGBezierPath.pathsFromSVG(at: svgURL)
for (index, path) in _paths.enumerated() {
let scaledBezier = ScaledBezier(bezierPath: path)
let shapeItem = ShapeItem(path: scaledBezier)
shapeItemsByKey[shapeItem.id] = shapeItem
shapeItemKeys.append(shapeItem.id)
}
}
}
Основное представление состоит из нескольких представлений - одно для изображения и одно для цветовой палитры среди других:
struct ColoringScreenView: View {
@ObservedObject var coloringImageViewModel : ColoringImageViewModel = ColoringImageViewModel(selectedImage: "tiger")
var body: some View {
VStack {
ColoringImageView(coloringImageViewModel: coloringImageViewModel)
ColoringImageButtonsView(coloringImageViewModel: coloringImageViewModel)
}
}
}
ColoringImageButtonsView должен изменять выбранный цвет в зависимости от выбранного цвета:
import SwiftUI
struct ColoringImageButtonsView: View {
@ObservedObject var coloringImageViewModel : ColoringImageViewModel
var paletteColors: [PaletteColorItem] = [PaletteColorItem(color: .red), PaletteColorItem(color: .green), PaletteColorItem(color: .blue), PaletteColorItem(color: .yellow), PaletteColorItem(color: .purple), PaletteColorItem(color: .black), PaletteColorItem(color: .red), PaletteColorItem(color: .red), PaletteColorItem(color: .red)]
var body: some View {
HStack {
ForEach(paletteColors) { colorItem in
Button("blue", action: {
self.coloringImageViewModel.selectedColor = colorItem.color
print("Selected color: \(self.coloringImageViewModel.selectedColor)")
}).buttonStyle(ColorButtonStyle(color: colorItem.color))
}
}
}
}
struct ColorButtonStyle: ButtonStyle {
var color: Color
init(color: Color) {
self.color = color
}
func makeBody(configuration: Configuration) -> some View {
Circle()
.fill(color)
.frame(width: 40, height: 40, alignment: .top)
}
}
struct ColoringImageButtonsView_Previews: PreviewProvider {
static var previews: some View {
var coloringImageViewModel : ColoringImageViewModel = ColoringImageViewModel(selectedImage: "tiger")
ColoringImageButtonsView(coloringImageViewModel: coloringImageViewModel)
}
}
В ShapeView (subview ImageView) он видит, что colorImageViewModel.selectedColor всегда равен нулю:
struct ShapeView: View {
var id: UUID
@Binding var coloringImageViewModel : ColoringImageViewModel
var body: some View {
ZStack {
var shapeItem = coloringImageViewModel.shapeItemsByKey[id]!
shapeItem.path
.fill(shapeItem.color)
.gesture(
DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged { gesture in
print("Tap location: \(gesture.startLocation)")
guard let currentlySelectedColor = coloringImageViewModel.selectedColor else {return}
shapeItem.color = currentlySelectedColor
}
)
.allowsHitTesting(coloringImageViewModel.dragGestureMode == DragGestureEnum.FillAreas)
shapeItem.path.stroke(Color.black)
}
}
}
Я читал о @Binding, @State и @ObservedObject, но мне не удалось правильно использовать оболочки свойств, чтобы удерживать состояния в одном экземпляре объекта (ColoringImageViewModel) и изменять / передавать его значения среди нескольких представлений. Кто-нибудь знает, как правильно это сделать?