最近看到一个能够在应用中观看360视频的应用,也来实现一下,熟悉一下操作。
先看一下当前实现效果。
用到了以下几个框架
- AVKit
- SceneKit
- SpriteKit
整体思路就是,首先先搭建一个场景,然后把物体跟相机都放进去,之后可以控制相机观察相应的物体。
首先声明以下场景及节点:
@State var scene: SCNScene = SCNScene()
@State var camera: SCNNode = SCNNode()
@State var circle: SCNNode = SCNNode()
界面部分:
VStack {
SceneView(
scene: scene,
pointOfView: camera,
options: [
.allowsCameraControl,
.autoenablesDefaultLighting,
.temporalAntialiasingEnabled
]
)
.border(Color.red, width: 3)
}
在页面显示的时候配置摄像机
.onAppear {
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 0, y: 0, z: 0)
camera.camera?.zFar = 1000
}
之后后台放置物品及图像纹理贴图。
// 球体
let geo = SCNSphere(radius: 200)
geo.segmentCount = 60
// 材质
let material = SCNMaterial()
material.lightingModel = .constant
material.isDoubleSided = true // 双面可见
material.transparencyMode = .aOne
circle = SCNNode(geometry: geo)
circle.geometry!.materials = [material]
circle.position = .init(x: 0, y: 0, z: -100)
scene.rootNode.addChildNode(circle)
// 贴纹理
material.diffuse.contents = UIImage(named: "p360")
测试图如下:
整体代码如下:
import SwiftUI
import AVKit
import SceneKit
import SpriteKit
struct ContentView: View {
@State var player: AVPlayer = AVPlayer()
@State var scene: SCNScene = SCNScene()
@State var camera: SCNNode = SCNNode()
@State var circle: SCNNode = SCNNode()
var body: some View {
VStack {
SceneView(
scene: scene,
pointOfView: camera,
options: [
.allowsCameraControl,
.autoenablesDefaultLighting,
.temporalAntialiasingEnabled
]
)
.border(Color.red, width: 3)
}
.padding()
.onAppear {
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 0, y: 0, z: 0)
camera.camera?.zFar = 1000
}
.task {
let geo = SCNSphere(radius: 200)
geo.segmentCount = 60
let material = SCNMaterial()
material.lightingModel = .constant
material.isDoubleSided = true
material.transparencyMode = .aOne
circle = SCNNode(geometry: geo)
circle.geometry!.materials = [material]
circle.position = .init(x: 0, y: 0, z: -100)
scene.rootNode.addChildNode(circle)
material.diffuse.contents = UIImage(named: "p360")
}
}
}
如果是视频,把其中的纹理替换成如下部分:
if let url = Bundle.main.url(forResource: "a360", withExtension: "mp4") {
self.player = AVPlayer(url: url)
self.player.play()
let skScene = SKScene(size: .init(width: 1000, height: 1000))
skScene.scaleMode = .aspectFill
let skNode = SKVideoNode(avPlayer: self.player)
skNode.size = .init(width: 1000, height: 1000)
skNode.position = .init(x: 500, y: 500)// 位置默认在左下角,因此增加点偏移,也可以通过设置矛点来操作
skScene.addChild(skNode)
material.diffuse.contents = skScene
}
测试视频地址如下:
https://download.csdn.net/download/xo19882011/87406177