SKNode从触摸点开始缩放

时间:2014-02-20 07:05:48

标签: scaling sprite-kit pinchzoom sknode

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

4 个答案:

答案 0 :(得分:20)

我一直在研究同样的问题,我的解决方案如下所示。不确定这是否是最好的方法,但到目前为止它似乎工作。我正在使用此代码放大和缩小具有多个SKSpriteNode子项的SKNode。孩子们都可以根据需要随着SKNode移动和缩放。缩放的锚点是捏合手势的位置。场景中的父SKScene和其他SKNode不受影响。所有工作都在recognizer.state == 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));
}

答案 1 :(得分:3)

我已经为Swift和Pinch Gestures翻译了九十九个解决方案。我花了几天时间试图让自己开始工作。谢天谢地,感谢九十九的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


}

答案 2 :(得分:0)

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

答案 3 :(得分:0)

在Swift 4中,我的SKSceneUIPinchGestureRecognizer添加到视图中,但将捏合手势的处理传递给在场景中创建的SKNode个孩子之一&#39}。 s init(),由于某些原因与此无关。无论如何,从他/她所谓的_mySkNode的角度来看,这是九十九的回答。它还包括一些限制缩放的代码,不使用帖子底部列出的便利功能。声明的@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
    }
}