放大和缩小 SpriteKit 场景的数学运算
Math for zooming in and out of a SpriteKit scene
使用这些作为指南:
SpriteKit pinch to zoom camera
我实现了以下功能来放大和缩小 SpriteKit 场景,以及使用两个 UIButton 逐步放大和缩小场景的能力:
var previousCameraScale = CGFloat()
var count = 0
@objc func pinchGestureAction(_ sender: UIPinchGestureRecognizer) {
guard let camera = cadScene.camera else {
return
}
if sender.state == .began {
previousCameraScale = camera.xScale
}
camera.setScale(previousCameraScale * 1 / sender.scale)
}
@IBAction func zoomIn(_ sender: Any) {
count = count+1
guard let camera = cadScene.camera else {
return
}
previousCameraScale = camera.xScale
camera.setScale(previousCameraScale / CGFloat(count))
}
@IBAction func zoomOut(_ sender: Any) {
count = count-1
guard let camera = cadScene.camera else {
return
}
previousCameraScale = camera.xScale
camera.setScale(previousCameraScale * CGFloat(count))
}
双指缩放效果很好;我在放大和缩小时遇到了问题,尽管...出于某种原因将比例设置为 inf
和 -inf
。
不是最擅长数学;任何帮助表示赞赏!
编辑:
更新逻辑:
@IBAction func zoomIn(_ sender: Any) {
count = count+0.1
guard let camera = cadScene.camera else {
return
}
previousCameraScale = camera.xScale - CGFloat(count)
camera.setScale(previousCameraScale * 1)
print("Previous camera scale \(previousCameraScale)")
}
@IBAction func zoomOut(_ sender: Any) {
count = count-0.1
guard let camera = cadScene.camera else {
return
}
previousCameraScale = camera.xScale + CGFloat(count)
if previousCameraScale < 0 {
return
}
camera.setScale(previousCameraScale * 1)
print("Previous camera scale \(previousCameraScale)")
}
@objc func pinchGestureAction(_ sender: UIPinchGestureRecognizer) {
guard let camera = cadScene.camera else {
return
}
if sender.state == .began {
previousCameraScale = camera.xScale
}
camera.setScale(previousCameraScale * 1 / sender.scale)
print("Previous camera scale \(previousCameraScale)")
print("Sender scale \(sender.scale)")
print("Camera scale \(camera.xScale)")
}
我不知道这是否能解决问题,但您是将 previousCameraScale 乘以 1 除以 senderScale,而不是除以 1 除以 senderScale。如果你想将 previousCameraScale 除以 1 / senderScale 你的声明应该是这样的:
camera.setScale(previousCameraScale * (1 / sender.scale))
这是由于数学运算符的优先级。
您可以尝试以下操作吗?它结合了捏合和步进缩放
// MARK: - Zoom
var scene: SKScene! // Setup this first
var stepper: UIStepper!
let zoomStepsInOneDirection: Double = 25
var cameraScaleAtRest: CGFloat!
func setupCamera() {
let cameraNode = SKCameraNode()
scene.addChild(cameraNode)
scene.camera = cameraNode
cameraScaleAtRest = cameraNode.xScale
}
func setupControls() {
let gr = UIPinchGestureRecognizer(target: self, action: #selector(pinchGestureAction(_:)))
view.addGestureRecognizer(gr)
let stepper = UIStepper(frame: CGRect(x: 0, y: 50, width: 400, height: 100))
stepper.minimumValue = -zoomStepsInOneDirection
stepper.value = 0
stepper.maximumValue = zoomStepsInOneDirection
stepper.addTarget(self, action: #selector(stepperPressed(_:)), for: .touchUpInside)
view.addSubview(stepper)
self.stepper = stepper
}
@objc func stepperPressed(_ sender: UIStepper) {
assert(cameraScaleAtRest != nil)
assert(scene.camera != nil)
let scaleFactor = exp(sender.value / zoomStepsInOneDirection)
// the following could also work
// let scaleFactor = pow(2, sender.value / zoomStepsInOneDirection)
let newScale = cameraScaleAtRest / scaleFactor
scene.camera?.setScale(newScale)
}
@objc func pinchGestureAction(_ sender: UIPinchGestureRecognizer) {
assert(scene.camera != nil)
guard let camera = scene.camera else {
return
}
switch sender.state {
case .began:
cameraScaleAtRest = camera.xScale
stepper.value = 0
case .ended:
cameraScaleAtRest = camera.xScale
stepper.value = 0
default:
let newScale = cameraScaleAtRest / sender.scale
camera.setScale(newScale)
}
}
使用这些作为指南:
SpriteKit pinch to zoom camera
我实现了以下功能来放大和缩小 SpriteKit 场景,以及使用两个 UIButton 逐步放大和缩小场景的能力:
var previousCameraScale = CGFloat()
var count = 0
@objc func pinchGestureAction(_ sender: UIPinchGestureRecognizer) {
guard let camera = cadScene.camera else {
return
}
if sender.state == .began {
previousCameraScale = camera.xScale
}
camera.setScale(previousCameraScale * 1 / sender.scale)
}
@IBAction func zoomIn(_ sender: Any) {
count = count+1
guard let camera = cadScene.camera else {
return
}
previousCameraScale = camera.xScale
camera.setScale(previousCameraScale / CGFloat(count))
}
@IBAction func zoomOut(_ sender: Any) {
count = count-1
guard let camera = cadScene.camera else {
return
}
previousCameraScale = camera.xScale
camera.setScale(previousCameraScale * CGFloat(count))
}
双指缩放效果很好;我在放大和缩小时遇到了问题,尽管...出于某种原因将比例设置为 inf
和 -inf
。
不是最擅长数学;任何帮助表示赞赏!
编辑:
更新逻辑:
@IBAction func zoomIn(_ sender: Any) {
count = count+0.1
guard let camera = cadScene.camera else {
return
}
previousCameraScale = camera.xScale - CGFloat(count)
camera.setScale(previousCameraScale * 1)
print("Previous camera scale \(previousCameraScale)")
}
@IBAction func zoomOut(_ sender: Any) {
count = count-0.1
guard let camera = cadScene.camera else {
return
}
previousCameraScale = camera.xScale + CGFloat(count)
if previousCameraScale < 0 {
return
}
camera.setScale(previousCameraScale * 1)
print("Previous camera scale \(previousCameraScale)")
}
@objc func pinchGestureAction(_ sender: UIPinchGestureRecognizer) {
guard let camera = cadScene.camera else {
return
}
if sender.state == .began {
previousCameraScale = camera.xScale
}
camera.setScale(previousCameraScale * 1 / sender.scale)
print("Previous camera scale \(previousCameraScale)")
print("Sender scale \(sender.scale)")
print("Camera scale \(camera.xScale)")
}
我不知道这是否能解决问题,但您是将 previousCameraScale 乘以 1 除以 senderScale,而不是除以 1 除以 senderScale。如果你想将 previousCameraScale 除以 1 / senderScale 你的声明应该是这样的:
camera.setScale(previousCameraScale * (1 / sender.scale))
这是由于数学运算符的优先级。
您可以尝试以下操作吗?它结合了捏合和步进缩放
// MARK: - Zoom
var scene: SKScene! // Setup this first
var stepper: UIStepper!
let zoomStepsInOneDirection: Double = 25
var cameraScaleAtRest: CGFloat!
func setupCamera() {
let cameraNode = SKCameraNode()
scene.addChild(cameraNode)
scene.camera = cameraNode
cameraScaleAtRest = cameraNode.xScale
}
func setupControls() {
let gr = UIPinchGestureRecognizer(target: self, action: #selector(pinchGestureAction(_:)))
view.addGestureRecognizer(gr)
let stepper = UIStepper(frame: CGRect(x: 0, y: 50, width: 400, height: 100))
stepper.minimumValue = -zoomStepsInOneDirection
stepper.value = 0
stepper.maximumValue = zoomStepsInOneDirection
stepper.addTarget(self, action: #selector(stepperPressed(_:)), for: .touchUpInside)
view.addSubview(stepper)
self.stepper = stepper
}
@objc func stepperPressed(_ sender: UIStepper) {
assert(cameraScaleAtRest != nil)
assert(scene.camera != nil)
let scaleFactor = exp(sender.value / zoomStepsInOneDirection)
// the following could also work
// let scaleFactor = pow(2, sender.value / zoomStepsInOneDirection)
let newScale = cameraScaleAtRest / scaleFactor
scene.camera?.setScale(newScale)
}
@objc func pinchGestureAction(_ sender: UIPinchGestureRecognizer) {
assert(scene.camera != nil)
guard let camera = scene.camera else {
return
}
switch sender.state {
case .began:
cameraScaleAtRest = camera.xScale
stepper.value = 0
case .ended:
cameraScaleAtRest = camera.xScale
stepper.value = 0
default:
let newScale = cameraScaleAtRest / sender.scale
camera.setScale(newScale)
}
}