2014-02-20 55 views
8

我已將UIPinchGestureRecognizer添加到我的scene.view中以縮放我的內容。實際上我縮放了我所有可見內容所在的父節點。但是我有問題,但有比例縮放點。事情是從左下角開始的節點比例。這絕對不是我想要的。我是否必須編寫大量代碼才能從發生夾點的位置進行縮放?您能否提供一些關於如何遵循的提示。從觸摸點開始的SKNode縮放比例

+0

你改變節點的'anchorPoint'? –

+0

無法更改SKNode的錨點。 –

回答

20

我一直在研究同樣的問題,我的解決方案如下所示。不知道這是否是最好的方式,但目前看來似乎有效。我使用這段代碼來放大和縮小一個有幾個SKSpriteNode子元素的SKNode。孩子們都可以根據需要隨着SKNode移動和縮放。縮放的錨點是捏合手勢的位置。場景中的父SKScene和其他SKNode不受影響。所有的工作都是在recognitionizer.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)); 
} 
+0

謝謝,身體。但什麼是trackNodeShift?你的意思是mySkNodeShift? –

+0

是的,它應該是mySkNodeShift。當我改變名稱使其更通用時,我錯過了那一個。我回去糾正它。謝謝! – ninefifteen

+0

我試過你的方法,它的確有幫助。再次感謝。 –

0

無法縮放我不知道爲什麼,但主要問題是那些SKT_INLINE。我GOOGLE了他們,並沒有發現任何關於他們......問題是當我複製/粘貼他們在我的項目編譯器告訴我,我必須添加一個「;」緊隨其後。我想知道這是否是我可以放大的原因。

3

我翻譯了ninefifteen的Swift和Pinch手勢解決方案。我花了幾天的時間試圖讓自己的工作。謝天謝地,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 


} 
+0

這是9fifteen的答案中的Ray Wenderlich幫助函數的Swift版本:https://github.com/raywenderlich/SKTUtils/blob/master/SKTUtils/CGPoint%2BExtensions.swift – peacetype

0

在斯威夫特4,我SKScene添加UIPinchGestureRecognizer的看法,但經過處理的縮放手勢的關閉到在現場的init()創建的,其SKNode的一個孩子由於某些原因沒有與此有關。無論如何,這是九十年代從他/他所稱的_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 
    } 
}