exyte / Macaw

Powerful and easy-to-use vector graphics Swift library with SVG support
MIT License
6.01k stars 553 forks source link

Find node after zooming #737

Open alexanderwe opened 3 years ago

alexanderwe commented 3 years ago

I am currently facing an issue when using the SVGView.zoom.enable() method. I want to let users tap on different nodes on my SVG. Furthermore it should be possible for them to zoom into the SVG view and then tap on the nodes as well.

I attached a UITapGestureRecognizer to my view for that.

private let svgView: SVGView = SVGView()

let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
svgView.addGestureRecognizer(tap)
svgView.zoom.enable(move: true, scale: true, rotate: false)

Then I try to find the nodes location based on the touch location of the users

@objc func handleTap(_ sender: UITapGestureRecognizer? = nil) {
        guard let sender = sender else {
            return
        }

       let location = sender.location(in: svgView)
        let contentScaleFactor = svgView.contentScaleFactor

        guard let node = svgView.findNodeAt(location: location) else {
            return
        }

        print(contentScaleFactor)

        let nodeShape = node as! Shape
        nodeShape.fill = Color.red

}

This does work if I do not zoom at all, but as soon as I start to zoom the touch location obviously doesn't change. Now I need to find a way to scale the touch location to the correct location inside the original svg. Unfortunately I couldn't find a way to do that.

Did I get something wrong here or miss any property on the SVGView that I could use for my calculation of the correct touch location ?

alexanderwe commented 3 years ago

Maybe this is related to #667

alexanderwe commented 3 years ago

I did some further investigations on my problem. If I attach an onTap listener directly to the nodes of interest the tap is recognised, even when the view is zoomed.

  svgView.node.nodesBy(predicate: { $0.visible && !$0.tag.isEmpty  }).forEach { node in
            node.onTap { event in
                guard let shape = node as? Shape else {
                    return
                }
                print(node.tag)
                shape.fill = Color.red
            }
        }