![](/img/trans.png)
[英]How do I prevent UIScrollView from intercepting touches outside of it's own view hierarchy?
[英]How do I prevent touches from hitting hidden content in SKCropNode?
我在游戲中大量使用了SKCropNode
,以用於樣式用途,並且在一種情況下,我已經構建了自己的SpriteKit版本的UIScrollView
。 我注意到,當我發生觸摸事件或手勢識別器在某個點觸發時, SKScene.nodeAtPoint(...)
仍會擊中在裁剪節點上觸摸點處隱藏的節點。
如何防止SKScene.nodeAtPoint(...)
擊中裁剪的內容,而是返回其下面的下一個可見節點?
你不能 一切都基於內容的框架,並且具有裁剪節點,因此非常龐大。 唯一可以做的就是檢查觸摸點,使用nodesAtPoint獲取所有節點,然后一一枚舉,通過檢查像素數據或進行CGPath概述來檢查觸摸點是否在觸摸可見像素。精靈,並檢查您是否在其中。
我設法解決了這個問題,但是它並不漂亮,並且並非在每種情況下都有效。
這個想法是,當記錄觸摸時,我將在該點上遍歷所有節點。 如果這些節點中的任何一個是SKCropNodes(或是SKCropNodes的子代),則檢查裁剪節點上的蒙版框架。 如果觸摸位於蒙版外部,則我們知道該點在該點不可見,並且可以假定觸摸沒有擊中它。
這種方法的問題在於,我沒有對裁剪蒙版中的透明度做任何評估-我只是假設它是一個矩形。 如果遮罩形狀不正常,我可能會在節點觸摸時給出誤報。
extension SKScene {
// Get the node at a given point, but ignore those that are hidden due to SKCropNodes.
func getVisibleNodeAtPoint(point: CGPoint) -> SKNode? {
var testedNodes = Set<SKNode>()
// Iterate over all the nodes hit by this click.
for touchedNode in self.nodesAtPoint(point) {
// If we've already checked this node, skip it. This happens because nodesAtPoint
// returns both leaf and ancestor nodes, and we test the ancestor nodes while
// testing leaf nodes.
if testedNodes.contains(touchedNode) {
continue
}
var stillVisible = true
// Walk the ancestry chain of the target node starting with the touched
// node itself.
var currentNode: SKNode = touchedNode
while true {
testedNodes.insert(currentNode)
if let currentCropNode = currentNode as? SKCropNode {
if let currentCropNodeMask = currentCropNode.maskNode {
let pointNormalizedToCurrentNode = self.convertPoint(point, toNode: currentCropNode)
let currentCropNodeMaskFrame = currentCropNodeMask.frame
// Check if the touch is inside the crop node's mask. If not, we
// know we've touched a hidden point.
if
pointNormalizedToCurrentNode.x < 0 || pointNormalizedToCurrentNode.x > currentCropNodeMaskFrame.size.width ||
pointNormalizedToCurrentNode.y < 0 || pointNormalizedToCurrentNode.y > currentCropNodeMaskFrame.size.height
{
stillVisible = false
break
}
}
}
// Move to next parent.
if let parent = currentNode.parent {
currentNode = parent
} else {
break
}
}
if !stillVisible {
continue
}
// We made it through the ancestry nodes. This node must be visible.
return touchedNode
}
// No visible nodes found at this point.
return nil
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.