检测在 CAShapeLayer 中点击的位置
Posted
技术标签:
【中文标题】检测在 CAShapeLayer 中点击的位置【英文标题】:Detecting where a tap is made in CAShapeLayer 【发布时间】:2015-11-25 15:45:59 【问题描述】:我正在尝试实现一个需要对触摸做出反应的自定义图表。我正在使用CAShapeLayer
在视图控制器视图中绘制图形。代码如下:
var PILL_GRAPH_ENDING_X_AXIS : CGFloat!
var PILL_GRAPH_BEGINNING_X_AXIS : CGFloat!
var PILL_GRAPH_DRAW_WIDTH : CGFloat!
var PILL_GRAPH_Y_AXIS : CGFloat!
var graphLayer : CAShapeLayer!
var tapGestureRecognizer : UITapGestureRecognizer!
//MARK: View Management
override func viewDidLoad()
super.viewDidLoad()
tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "viewTapped:")
view.addGestureRecognizer(tapGestureRecognizer)
override func viewWillAppear(animated: Bool)
super.viewWillAppear(animated)
print("View will appear has been called")
override func viewWillLayoutSubviews()
super.viewWillLayoutSubviews()
print("View will layout subviews")
PILL_GRAPH_Y_AXIS = view.frame.size.height/2
PILL_GRAPH_DRAW_WIDTH = 80
PILL_GRAPH_ENDING_X_AXIS = view.frame.size.width-50
PILL_GRAPH_BEGINNING_X_AXIS = 50
drawPillGraph()
//MARK: Graph Drawing
func drawPillGraph()
let bezierPath = UIBezierPath()
graphLayer = CAShapeLayer()
//Prepare the line drawing
bezierPath.moveToPoint(CGPoint(x: PILL_GRAPH_BEGINNING_X_AXIS, y: PILL_GRAPH_Y_AXIS))
let endingPoint = CGPoint(x: PILL_GRAPH_ENDING_X_AXIS, y: PILL_GRAPH_Y_AXIS)
bezierPath.addLineToPoint(endingPoint)
graphLayer.opacity = 1.0
graphLayer.backgroundColor = UIColor.lightGrayColor().CGColor
graphLayer.strokeColor = UIColor.redColor().CGColor
graphLayer.lineWidth = PILL_GRAPH_DRAW_WIDTH
graphLayer.lineCap = kCALineCapRound
graphLayer.path = bezierPath.CGPath
view.layer.addSublayer(graphLayer)
func viewTapped(gestureRecognizer: UITapGestureRecognizer)
print("View tapped")
let touch = gestureRecognizer.locationInView(self.view)
这将生成一个如下所示的图表:
我想要做的是能够检测何时点击红色图表以及点击点CGPoint
,特别是在点击的图表中。我尝试了几种不同的方法来尝试使用hitTest:
和CGPointContainsPoint
,但我一直无法成功实现我想要做的事情。如果有人有如何做到这一点的例子,将不胜感激。
【问题讨论】:
实现 hitTest 方法是正确的解决方案。如果您的代码不起作用,请编辑您的问题以显示该代码,我们可以帮助您调试它。 【参考方案1】:这是我直接从我的项目中复制的一些代码(CGPathContainsPoint
代码除外)。在我的例子中,手势识别器是长按,但这就是我实现hitTest:
func didLongPressView(lpGesture:UILongPressGestureRecognizer)
let location = lpGesture.locationInView(self)
let point = self.convertPoint(location, fromView: nil)
let foundLayer = self.rootLayer!.hitTest(point)
if let shapeLayer = foundLayer as? CAShapeLayer
// You've found a shape layer, see if the point is inside
// its path
if CGPathContainsPoint(shapeLayer.path, nil, point, false)
// The tap was inside the shape layer's path.
rootLayer
变量是我的层层次结构中最外层(***父级)。
【讨论】:
【参考方案2】:在 Swift 3.0 中,事情变得更加简洁和不同。
func buttonTapped(sender: UITapGestureRecognizer)
// Check location of tap in the View.
let location = tapGesture?.location(in: self.view)
// Convert location into a Point
let point = self.view.convert(location!, from: nil)
if shapeLayer!.path!.contains(point)
startAnimation()
或者使用您的 LongPress 示例马特...
func didLongPressView(sender: UILongPressGestureRecognizer)
// Check location of long press in the View.
let location = lpGesture?.location(in: self.rootLayer)
// Convert location into a Point
let point = self.rootLayer.convert(location!, from: nil)
if shapeLayer!.path!.contains(point)
startAnimation()
即在此函数之外声明的 tapGesture/lpGesture 并且 ShapeLayer 已在 viewDidLoad 中实例化为 CAShapeLayer()(如下所示)......
self.shapeLayer = CAShapeLayer()
shapeLayer!.path = shapeBezier.cgPath
shapeLayer!.fillColor = UIColor.whiteColor().cgColor
self.view.layer.addSublayer(shapeLayer!)
【讨论】:
以上是关于检测在 CAShapeLayer 中点击的位置的主要内容,如果未能解决你的问题,请参考以下文章