【问题标题】:SKNode scale from the touched pointSKNode 从接触点缩放
【发布时间】:2014-03-20 23:18:59
【问题描述】:

我已将 UIPinchGestureRecognizer 添加到我的 scene.view 以缩放我的内容。我实际上缩放了所有可见内容所在的父节点。但是我有缩放点的问题。问题是左下角的节点比例。这绝对不是我想要的。我是否必须编写大量代码才能从发生挤压的点进行扩展?能否请您提供一些关于如何遵循的提示。

【问题讨论】:

  • 你是否更改了节点的anchorPoint
  • 无法改变SKNode的锚点。

标签: scaling sprite-kit pinchzoom sknode


【解决方案1】:

我一直在解决同样的问题,我的解决方案如下所示。不确定这是否是最好的方法,但到目前为止它似乎有效。我正在使用此代码放大和缩小具有多个 SKSpriteNode 子级的 SKNode。孩子们都根据需要使用 SKNode 移动和缩放。缩放的锚点是捏合手势的位置。场景中的父 SKScene 和其他 SKNode 不受影响。所有工作都在识别器状态 == UIGestureRecognizerStateChanged 期间进行。

// instance variables of MyScene.
SKNode *_mySkNode;
UIPinchGestureRecognizer *_pinchGestureRecognizer;

- (void)didMoveToView:(SKView *)view
{
    _pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleZoomFrom:)];
    [[self view] addGestureRecognizer:_pinchGestureRecognizer];
}

// Method that is called by my UIPinchGestureRecognizer.
- (void)handleZoomFrom:(UIPinchGestureRecognizer *)recognizer
{
     CGPoint anchorPoint = [recognizer locationInView:recognizer.view];
     anchorPoint = [self convertPointFromView:anchorPoint];

     if (recognizer.state == UIGestureRecognizerStateBegan) {

         // No code needed for zooming...

     } else if (recognizer.state == UIGestureRecognizerStateChanged) {

         CGPoint anchorPointInMySkNode = [_mySkNode convertPoint:anchorPoint fromNode:self];

         [_mySkNode setScale:(_mySkNode.xScale * recognizer.scale)];

         CGPoint mySkNodeAnchorPointInScene = [self convertPoint:anchorPointInMySkNode fromNode:_mySkNode];
         CGPoint translationOfAnchorInScene = CGPointSubtract(anchorPoint, mySkNodeAnchorPointInScene);

         _mySkNode.position = CGPointAdd(_mySkNode.position, translationOfAnchorInScene);

         recognizer.scale = 1.0;

     } else if (recognizer.state == UIGestureRecognizerStateEnded) {

         // No code needed here for zooming...

     }
}

以下是上面使用的辅助函数。它们来自 Ray Wenderlich 关于 Sprite Kit 的书。

SKT_INLINE CGPoint CGPointAdd(CGPoint point1, CGPoint point2) {
    return CGPointMake(point1.x + point2.x, point1.y + point2.y);
}

SKT_INLINE CGPoint CGPointSubtract(CGPoint point1, CGPoint point2) {
    return CGPointMake(point1.x - point2.x, point1.y - point2.y);
}

SKT_INLINE GLKVector2 GLKVector2FromCGPoint(CGPoint point) {
    return GLKVector2Make(point.x, point.y);
}

SKT_INLINE CGPoint CGPointFromGLKVector2(GLKVector2 vector) {
    return CGPointMake(vector.x, vector.y);
}

SKT_INLINE CGPoint CGPointMultiplyScalar(CGPoint point, CGFloat value) {
    return CGPointFromGLKVector2(GLKVector2MultiplyScalar(GLKVector2FromCGPoint(point), value));
}

【讨论】:

  • 谢谢,身体。但是什么是 trackNodeShift?你是说 mySkNodeShift 吗?
  • 是的,应该是 mySkNodeShift。当我更改名称以使其更通用时,我错过了那个。我回去改正了。谢谢!
  • 我试过你的方法,确实有帮助。再次感谢。
  • 我试过了,它奏效了,但是......不像我预期的那样。假设您放大 (200, 200),抬起手指,缩小 (50, 50)……这一刻打破了一切。 Doh...任何想法如何解决它?
  • AndrewShmig... 你能发布你的代码吗?我没有那个问题。我可以放大或缩小,抬起手指,然后放大或缩小,没有任何问题。
【解决方案2】:

无法缩放我不知道为什么,但主要问题是那些 SKT_INLINE。我用谷歌搜索了它们,但没有发现任何关于它们的信息……问题是当我将它们复制/粘贴到我的项目中时,编译器告诉我必须添加一个“;”就在他们之后。我想知道这是否是我可以缩放的原因。

【讨论】:

    【解决方案3】:

    我已经翻译了 Ninefifteen 的 Swift 和 Pinch Gestures 解决方案。我花了几天时间试图让它自己工作。谢天谢地,ninefifteen 的 Obj-C 帖子!这是似乎对我有用的 Swift 版本。

    func scaleExperiment(_ sender: UIPinchGestureRecognizer) {
    
    
        var anchorPoint = sender.location(in: sender.view)
    
        anchorPoint = self.convertPoint(fromView: anchorPoint)
    
        let anchorPointInMySkNode = _mySkNode.convert(anchorPoint, from: self)
    
        _mySkNode.setScale(_mySkNode.xScale * sender.scale)
    
        let mySkNodeAnchorPointInScene = self.convert(anchorPointInMySkNode, from: _mySkNode)
    
        let translationOfAnchorInScene = (x: anchorPoint.x - mySkNodeAnchorPointInScene.x, y: anchorPoint.y - mySkNodeAnchorPointInScene.y)
    
        _mySkNode.position = CGPoint(x: _mySkNode.position.x + translationOfAnchorInScene.x, y: _mySkNode.position.y + translationOfAnchorInScene.y)
    
        sender.scale = 1.0
    
    
    }
    

    【讨论】:

    【解决方案4】:

    在 Swift 4 中,我的 SKSceneUIPinchGestureRecognizer 添加到视图中,但将捏合手势的处理传递给在场景的 init() 中创建的 SKNode 子项之一,由于某些原因没有在这里相关。无论如何,从她/他所说的_mySkNode 的角度来看,这是ninefifteen 的答案。它还包含一些限制缩放的代码,并且不使用他帖子底部列出的便利功能。声明的@objc 部分允许函数在#selector() 中使用。

    这是我的SKScene

    override func didMove(to view: SKView) {
        let pinchRecognizer: UIPinchGestureRecognizer = UIPinchGestureRecognizer(target: self.grid, action: #selector(self.grid.pinchZoomGrid))
        self.view!.addGestureRecognizer(pinchRecognizer)
    }
    

    这是我的 SKNode 中的相关部分:

    // Pinch Management
    @objc func pinchZoomGrid(_ recognizer: UIPinchGestureRecognizer){
        var anchorPoint: CGPoint = recognizer.location(in: recognizer.view)
        anchorPoint = self.scene!.convertPoint(fromView: anchorPoint)
    
        if recognizer.state == .began {
            // No zoom code
        } else if recognizer.state == .changed {
            let anchorPointInGrid = self.convert(anchorPoint, from: self.scene!)
    
            // Start section that limits the zoom
            if recognizer.scale < 1.0 {
                if self.xScale * recognizer.scale < 0.6 {
                    self.setScale(0.6)
                } else {
                    self.setScale(self.xScale * recognizer.scale)
                }
            } else if recognizer.scale > 1.0 {
                if self.xScale * recognizer.scale > 1.5 {
                    self.setScale(1.5)
                } else {
                    self.setScale(self.xScale * recognizer.scale)
                }
            }
            // End section that limits the zoom
    
            let gridAnchorPointInScene = self.scene!.convert(anchorPointInGrid, from: self)
            let translationOfAnchorPointInScene = CGPoint(x:anchorPoint.x - gridAnchorPointInScene.x,
                                                          y:anchorPoint.y - gridAnchorPointInScene.y)
    
            self.position = CGPoint(x:self.position.x + translationOfAnchorPointInScene.x,
                                    y:self.position.y + translationOfAnchorPointInScene.y)
            recognizer.scale = 1.0
    
        } else if recognizer.state == .ended {
            // No zoom code
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-04
      • 1970-01-01
      相关资源
      最近更新 更多