我已将UIPinchGestureRecognizer添加到我的场景视图中以缩放内容。我实际上是在缩放包含所有可见内容的父节点。但是,我遇到了一个问题,就是缩放点的位置。事实上,节点从左下角开始缩放,这显然不是我想要的。我是否需要编写大量代码才能从捏合发生的点开始缩放?您能否请给出一些提示应该遵循什么方式。
我已将UIPinchGestureRecognizer添加到我的场景视图中以缩放内容。我实际上是在缩放包含所有可见内容的父节点。但是,我遇到了一个问题,就是缩放点的位置。事实上,节点从左下角开始缩放,这显然不是我想要的。我是否需要编写大量代码才能从捏合发生的点开始缩放?您能否请给出一些提示应该遵循什么方式。
我一直在解决同一个问题,我的解决方案如下所示。不确定这是否是最好的方式,但到目前为止,它似乎可以工作。我使用此代码来放大和缩小具有多个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 书籍。
以下是先前使用过的辅助函数。它们来自于 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));
}
我翻译了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
}
SKScene
将UIPinchGestureRecognizer
添加到视图中,但将捏合手势的处理传递给其中一个在场景的init()
中创建的SKNode
子节点,由于这里不相关的某些原因。无论如何,这是ninefifteen从他所称的_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
}
}
无法缩放,我不知道为什么,但主要问题是那些SKT_INLINE。我已经谷歌过它们,没有找到任何关于它们的信息...问题是当我将它们复制/粘贴到我的项目中时,编译器告诉我必须在它们后面添加一个“;”。我想知道这是否是我无法缩放的原因。
anchorPoint
吗? - Andrey Gordeev