【问题标题】:Flickering while dragging SKNode using NSPanGestureRecognizer on OS X在 OS X 上使用 NSPanGestureRecognizer 拖动 SKNode 时闪烁
【发布时间】:2015-03-19 15:19:20
【问题描述】:

今天我决定尝试一些新添加到 OS X 的闪亮(iOS 灵感)的东西:手势识别器和 Sprite Kit。我已经为 SKView 设置了一个 NSPanGestureRecognizer,我正在使用它来拖动添加到场景中的节点。但是,快速拖动节点时,我看到了奇怪的闪烁。

代码非常简单,在 AppDelegate 中设置所有内容,

func applicationDidFinishLaunching(aNotification: NSNotification) {
    // Insert code here to initialize your application

    // Add and scene to the view and create a root node
    hostingView.presentScene(SKScene(size: CGSize(width: 1500.0, height: 1500.0)))
    rootNode = SKNode()

    // A a red circle
    let node = SKShapeNode(circleOfRadius: 50.0)
    node.lineWidth = 5.0
    node.strokeColor = NSColor.whiteColor()
    node.fillColor = NSColor.redColor()
    node.userInteractionEnabled = true
    rootNode?.addChild(node)
    hostingView.scene?.addChild(rootNode!)

}

然后实现手势识别器的action方法,

@IBAction func panAction(sender: AnyObject) {

    // Get the location in the view from the pan gesture recogniser
    let viewPoint = (sender as NSPanGestureRecognizer).locationInView(hostingView)

    // Convert from view -> scene -> root node coordinates
    if let scene = hostingView.scene {

        let scenePoint = hostingView.convertPoint(viewPoint, toScene:scene)

        if let root = self.rootNode {

                let rootNodePoint = scene.convertPoint(scenePoint, toNode: root)
                let node = root.nodeAtPoint(rootNodePoint)
                node.position = rootNodePoint
                println("Drag to point:", NSStringFromPoint(scenePoint))
                return
            }
        }

    println("Node was nil.")
}

如果想运行这个项目,it's on github.

【问题讨论】:

  • 您是否尝试过将 shapeNode 直接添加到视图而不是先将其添加到 SKNode?​​span>
  • 有趣,我认为你正在做某事。现在不同的问题,当你这样做时,当鼠标移动到节点边界之外时,圆圈会停止拖动。因此,之前发生的事情是,当鼠标快速移动时,我们从拖动圆形节点到根节点。

标签: macos cocoa swift sprite-kit uigesturerecognizer


【解决方案1】:

当鼠标被快速拖动并退出节点边界时,nodeAtPoint: 正在返回背景节点。这导致了闪烁(感谢@sangony)。

解决方案是使用NSGestureRecognizer's state 值来区分第一次触发(NSGestureRecognizerStateBegan)、更新(NSGestureRecognizerStateChanged)和释放鼠标时(NSGestureRecognizerStateEnded)。通过检查这些值,即使鼠标移动到节点边界之外,正确的节点也可以被缓存和更新。

更新的动作方法是,

@IBAction func panAction(sender: AnyObject) {

    // Get the location in the view from the pan gesture recogniser
    let recognizer = (sender as NSPanGestureRecognizer)
    let viewPoint = recognizer.locationInView(hostingView)


    if let scene = hostingView.scene {

        // Convert from view -> scene
        let scenePoint = hostingView.convertPoint(viewPoint, toScene:scene)


        if let root = self.rootNode {

            // Convert from scene -> rootNode
            let rootNodePoint = scene.convertPoint(scenePoint, toNode: root)

            // Use the recogniser state, this keeps track of the correct node
            // even if the mouse has moved outside of the node bounds during
            // the drag operation.
            switch recognizer.state {
            case .Began:

                // Cache the clicked node
                let node = root.nodeAtPoint(rootNodePoint)
                if node != root {
                    node.position = rootNodePoint
                    draggedNode = node
                    return
                }

            case .Changed:

                // Update the cached node position
                if let draggedNode = self.draggedNode {
                    draggedNode.position = rootNodePoint
                }

            case .Ended:

                // Finally update the position and clear the cache
                if let draggedNode = self.draggedNode {
                    draggedNode.position = rootNodePoint
                    self.draggedNode = nil
                }

            default:
                return

            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-28
    • 2013-02-24
    • 2023-03-25
    相关资源
    最近更新 更多