exyte / SVGView

SVG parser and renderer written in SwiftUI
MIT License
655 stars 79 forks source link

Value of type 'some View' has no member 'getNode' #32

Open CodeTropolis opened 1 year ago

CodeTropolis commented 1 year ago
    if let filePath = Bundle.main.url(forResource: "zones", withExtension: "svg") {
            ScrollView(.horizontal) {
                let zoneMap = SVGView(contentsOf: filePath).frame(width: 1100, height: 550)

                if let part = zoneMap.getNode(byId: "part") {
                            part.onTapGesture { // onTapGesture not available.
                                part.opacity = 0.2
                            }
                        }
            }
        }

Nor does the following from your "Getting Started" recognize a tap:


struct ZoneSelect: View {
    let fileURL = Bundle.main.url(forResource: "zones", withExtension: "svg")!
    var body: some View {
        let root = SVGView(contentsOf: fileURL)// 1
        let first = root.getNode(byId:"zone1")// 2
        first?.onTapGesture{ // 3
            (first as? SVGShape)?.fill = SVGColor.by(name: "red") // 4
            print("Tapped!")
        }
        return root
    }

}

What is the correct API to recognize a tap? Have you changed the API overall? If so, where's the documentation?

ystrot commented 1 year ago

Hi @CodeTropolis,

You're right that onTap was renamed to onTapGesture and documentation doesn't reflect it. So we'll update it.

But your examples are correct. Could you attach an SVG you're using? Probably a node you're trying to get is missing or it's an element which couldn't be tapped (for example, shape with stroke and without fill).

CodeTropolis commented 1 year ago

Here's the SVG(Github attachment not working): https://pastebin.com/Eguxingd

The SVG is a world map.

Not concerned about CSS id or class properties except for the necessary props required for tap recognition on a region.

Appreciate your help.

ystrot commented 1 year ago

I reproduced your issue. Tap works on some parts of "americas" for me, but "europe" and "asia" can't be tapped at all. Will take a look.

CodeTropolis commented 1 year ago

I'm experiencing something similar. I'm able to log to console upon a tap on both americas and europe but not asia. Also, the fill does not change color.

struct ZoneSelect: View {
    var body: some View {
        let filePath = Bundle.main.url(forResource: "zones.svg", withExtension: nil)!
        let root = SVGView(contentsOf: filePath)
        let zones = ["americas", "europe", "asia"]
        zones.forEach { region in
           let zone = root.svg?.getNode(byId: region)
            zone?.onTapGesture {
                print("Region: \(region) tapped!")
                (zone as? SVGPath)?.fill = SVGColor.by(name: "orange")
            }
        }
        return ScrollView(.horizontal) {
            root.frame(width: 1280, height: 640)

        }

    }

}
ystrot commented 1 year ago

That's because zone is not a path, it's a group containing several paths. You need to use something like this to change fill color:

func setColor(_ node: SVGNode, color: SVGColor) {
    if let group = node as? SVGGroup {
        for content in group.contents {
            setColor(content, color: color)
        }
    } else if let shape = node as? SVGShape {
        shape.fill = color
    }
}
...
setColor(zone, color: SVGColor.by(name: "orange"))
CodeTropolis commented 1 year ago

Thank you Yuri! Appreciate your help.