一、原理部分
1.利用SceneKit 造一个球面
2.将图片铺满球面
3.在球中心放一个相机,也就是我们的眼睛所在,
4.根据手势或者陀螺仪,改变相机视野
二、代码部分
1.导入 SceneKit框架
SceneKit是一个高性能的渲染游戏引擎,它能够将 3D 模型文件,用很简单的方式渲染出来.
import SceneKit
2.创建SCNView 并加到 view上
let scnView = SCNView()
scnView.frame = view.bounds
//SCNView中scene默认为 nil
scnView.scene = SCNScene()
self.view.addSubview(scnView);
3.添加相机节点
let camera = SCNCamera()
cameraNode.camera = camera
cameraNode.camera?.automaticallyAdjustsZRange = true;
cameraNode.position = SCNVector3Make(0, 0, 0);
scnView.scene?.rootNode.addChildNode(cameraNode);
4.添加图片显示节点
let panoramaNode = SCNNode()
panoramaNode.geometry = SCNSphere(radius: 100);
//剔除外表面
panoramaNode.geometry?.firstMaterial?.cullMode = .front
//只显示一个面
panoramaNode.geometry?.firstMaterial?.isDoubleSided = false
panoramaNode.position = SCNVector3Make(0, 0, 0);
scnView.scene?.rootNode.addChildNode(panoramaNode);
5.显示图片
let image = UIImage(named: "星空")
panoramaNode.geometry?.firstMaterial?.diffuse.contents = image
6.实现滑动旋转
let pan = UIPanGestureRecognizer(target: self, action: #selector(panImage(gesture:)))
scnView.addGestureRecognizer(pan)
根据手指移动距离计算角度,然后旋转相机节点
if gesture.state == .began {
let currentPoint = gesture .location(in: self.scnView)
lastPoint_x = currentPoint.x
lastPoint_y = currentPoint.y
}else{
let currentPoint = gesture .location(in: self.scnView)
var distX = currentPoint.x - lastPoint_x
var distY:CGFloat = currentPoint.y - lastPoint_y
lastPoint_x = currentPoint.x
lastPoint_y = currentPoint.y
distX *= -0.003
distY *= -0.003
fingerRotationY += distY
fingerRotationX += distX
var modelMatrix = SCNMatrix4MakeRotation(0, 0, 0, 0)
modelMatrix = SCNMatrix4Rotate(modelMatrix, Float(fingerRotationX),0, 1, 0);
modelMatrix = SCNMatrix4Rotate(modelMatrix, Float(fingerRotationY), 1, 0, 0);
self.cameraNode.pivot = modelMatrix;
}
7.实现图片放大缩小
添加捏合手势
let pinch = UIPinchGestureRecognizer(target: self, action: #selector(pinchGesture(gesture:)))
scnView.addGestureRecognizer(pinch)
手势计算
@objc func pinchGesture(gesture:UIGestureRecognizer){
if !gesture.isKind(of: UIPinchGestureRecognizer.self){
return
}
let pinchGesture = gesture as! UIPinchGestureRecognizer
if pinchGesture.state != .ended && pinchGesture.state != .failed{
if/* pinchGesture.scale != NAN && */ pinchGesture.scale != 0.0{
var scale = pinchGesture.scale - 1
if scale < 0 {
scale *= (sScaleMax - sScaleMin)
}
currentScale = scale + prevScale
currentScale = validateScale(scale: currentScale)
let valScale = validateScale(scale: currentScale)
let xFov = 90 * (1-(valScale-1)*0.15)
let yFov = 50 * (1-(valScale-1)*0.15)
cameraNode.camera?.xFov = Double(xFov)
cameraNode.camera?.yFov = Double(yFov)
}
}else if pinchGesture.state == .ended{
prevScale = currentScale
}
}
private func validateScale(scale:CGFloat) -> CGFloat {
var validateScale = scale
if scale < sScaleMin {
validateScale = sScaleMin
} else if scale > sScaleMax{
validateScale = sScaleMax
}
return validateScale
}