提问者:小点点

创建许多CAShapeLayers并在其中创建Unquue触摸事件


我想显示很多星星,当用户触摸其中一颗星星的内部时,我可以改变星星的颜色,并将星星id附加到数组中。

我有一个恒星坐标数组=[[恒星1的顶点坐标],[恒星2的顶点坐标],...,[恒星60的顶点坐标]]


//function to create a star UIBezierPath

func StarFromArray(points: [Array<Int>]  ) -> UIBezierPath {
        let starPath = UIBezierPath()
        let point1 = points[0]
        starPath.move(to: CGPoint(x: point1[0], y: point1[1]))
        
        for i in 1...(starPath.count-1) {
            let ar = starPath[i]
            starPath.addLine(to: CGPoint(x: ar[0], y: ar[1]))
        }
        starPath.close()
        
        return starPath
    }


//function to create and display every star from my StarArray, I call this in ViewDidLoad

func loadStar() {
        for i in 0...StarArray.size {
            let ar = StarArray[i]

            let starLayer = CAShapeLayer()
            let star = StarFromArray(points: ar)
            
            starLayer.path = star.cgPath
            starLayer.fillColor = UIColor.blue.cgColor
            self.view.layer.addSublayer(starLayer)
            
        }
    }


上面的代码显示了我所有的星星,现在我需要为我的每个星星创建一个触摸事件,这样当一个星星被触摸时,我可以将一个星星ID追加到一个数组中。

我该怎么做?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let point = touch!.location(in: self.view)

        if starLayer.path!.contains(point) {
            print("star touched")
            starLayer.fillColor = UIColor.blue.cgColor
            
        }
    }

上面的代码是如果我有一颗星的话可以使用的,但是如果我有很多颗星的话显然就不起作用了。


共1个答案

匿名用户

不能将触摸事件发送到图层。你得自己处理。我建议在包含这些图层的视图上附加一个手势识别器,然后为每个图层添加一个包含边界矩形的结构数组,然后确定哪一个图层是这样点击的。

CALayer确实有一个最棒的方法,你可以用它来判断一个轻击是否落在一个图层中,但你必须自己来决定它。您可以在父层上调用hittest(),它会告诉您点击落在哪个子层(或父层)的帧上。

如果您想要检测不规则形状(如您的星型示例图像)内的抽头,您必须自己编写代码。(UIBezierPath和CGPath都有contains()方法,您可以使用这些方法查询路径,以查看某个点是否位于路径内部。)