Home > Blockchain >  Tap anywhere to add multiple items on canvas
Tap anywhere to add multiple items on canvas

Time:10-31

import SwiftUI

struct Level1: View {
    @State var tapScore = 0
    @State var showingMinedHammer = false
    @State var points:[CGPoint] = [CGPoint(x:0,y:0), CGPoint(x:50,y:50)]
    @State private var location = CGPoint.zero      // < here !!
    
    
    func mine() {
        tapScore  = 1
        showMinedHammer()
    }
    
    func showMinedHammer() {
        self.showingMinedHammer = true
        DispatchQueue.main.asyncAfter(deadline: .now()   99) {
            self.showingMinedHammer = false
        }
    }
    
    var body: some View {
        GeometryReader { geometryProxy in
            ZStack {
                Image("hammer.fill").resizable().frame(width: UIScreen.main.bounds.height * 1.4, height: UIScreen.main.bounds.height)
                    .gesture(DragGesture(minimumDistance: 0).onEnded { value in
                        self.location = value.location // < here !!
                        self.mine()
                    })
                if self.showingMinedHammer {
                    Image(systemName: "hammer.fill")
                        .resizable()
                        .frame(width: 30, height: 30)
                        .position(self.location)    // < here !!
                }
            }
        }.edgesIgnoringSafeArea(.all)
    }
    
}

struct Level1_Previews: PreviewProvider {
    static var previews: some View {
        Level1()
    }
}

struct GetTapLocation:UIViewRepresentable {
    var tappedCallback: ((CGPoint) -> Void)
    
    func makeUIView(context: UIViewRepresentableContext<GetTapLocation>) -> UIView {
        let v = UIView(frame: .zero)
        let gesture = UITapGestureRecognizer(target: context.coordinator,
                                             action: #selector(Coordinator.tapped))
        v.addGestureRecognizer(gesture)
        return v
    }
    
    class Coordinator: NSObject {
        var tappedCallback: ((CGPoint) -> Void)
        init(tappedCallback: @escaping ((CGPoint) -> Void)) {
            self.tappedCallback = tappedCallback
        }
        @objc func tapped(gesture:UITapGestureRecognizer) {
            let point = gesture.location(in: gesture.view)
            self.tappedCallback(point)
        }
    }
    
    func makeCoordinator() -> GetTapLocation.Coordinator {
        return Coordinator(tappedCallback:self.tappedCallback)
    }
    
    func updateUIView(_ uiView: UIView,
                      context: UIViewRepresentableContext<GetTapLocation>) {
    }
    
}

New to SwiftUI and I am trying to combine gestures that allow me to tap anywhere on the screen to add an infinite amount of "Images", but currently the image only stays on screen for a short while. Where am I going wrong? Am I supposed to combine another gesture to get the item to stay on screen whilst adding?

CodePudding user response:

You only have a singular location, so only one item will ever appear in your example. To have multiple items, you'll need some sort of collection, like an Array.

The following is a pared-down example showing using an array:

struct Hammer: Identifiable {
    var id = UUID()
    var location: CGPoint
}

struct Level1: View {
    @State var hammers: [Hammer] = [] //<-- Start with `none`
    
    var body: some View {
        ZStack {
            ForEach(hammers) { hammer in // Display all of the hammers
                Image(systemName: "hammer.fill")
                    .resizable()
                    .frame(width: 30, height: 30)
                    .position(hammer.location)
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .contentShape(Rectangle())
        .gesture(DragGesture(minimumDistance: 0).onEnded { value in
            self.hammers.append(Hammer(location: value.location)) // Add a Hammer
        })
        .edgesIgnoringSafeArea(.all)
    }
}

Note: I'm unclear on what the GeometryReader is for in your code -- you declare it, then use UIScreen dimensions -- normally in SwiftUI we just use GeometryReader

  • Related