Swift中SceneKit视频纹理对象的布局坐标设置及节点实现问询
解决SceneKit中SCNPlane视频纹理的布局坐标问题
嘿,我来帮你搞定这个视频纹理的布局调整!你已经完成了基础的节点和播放器创建,接下来咱们把视频的布局和显示搞定,主要有两种常用的方式,我给你详细讲清楚:
方法一:用SpriteKit的SKScene控制布局(推荐,更灵活)
这种方式借助SpriteKit的布局系统来调整视频的位置、缩放和适配模式,操作起来更直观,还能顺便加一些2D元素(比如字幕、动画)到视频上。
先补全你的代码,然后加上布局设置:
// 你的基础代码 let plane = SCNPlane(width: 5, height: 5) let node = SCNNode(geometry: plane) GlobalScene.shared.rootNode.addChildNode(node) guard let urlStr = Bundle.main.path(forResource: "test", ofType: "mov"), let videoURL = NSURL(fileURLWithPath: urlStr) as? URL else { fatalError("找不到视频文件") } // 创建AVPlayer和SKVideoNode let player = AVPlayer(url: videoURL) let videoNode = SKVideoNode(avPlayer: player) // 1. 创建适配SCNPlane尺寸的SKScene let skSceneSize = CGSize(width: plane.width, height: plane.height) let skScene = SKScene(size: skSceneSize) // 2. 设置SKScene的缩放模式,控制整体适配逻辑 skScene.scaleMode = .resizeAspectFill // 可选:.resizeAspect(保持比例,留黑边)、.resizeAspectFill(铺满,裁剪超出部分) // 3. 调整videoNode在SKScene中的布局,让它居中铺满 videoNode.position = CGPoint(x: skScene.size.width/2, y: skScene.size.height/2) videoNode.size = skScene.size videoNode.videoGravity = .resizeAspectFill // 和scene的scaleMode配合,保证视频适配 // 4. 将SKScene设置为SCNPlane的材质内容 plane.firstMaterial?.contents = skScene // 开始播放视频 player.play()
如果遇到视频倒过来的情况(因为SceneKit的Y轴和SpriteKit的Y轴方向相反),给videoNode加个翻转就行:
videoNode.yScale = -1
方法二:直接用SCNMaterial的contentsTransform调整
如果不需要SpriteKit的额外功能,也可以直接通过SceneKit材质的contentsTransform属性,用CATransform3D来控制视频纹理的缩放、平移,实现布局调整。
示例代码:
// 基础代码和上面一致,到创建player为止 let player = AVPlayer(url: videoURL) let material = plane.firstMaterial! // 1. 将AVPlayer直接设为材质内容 material.contents = player // 2. 计算视频和平面的宽高比,调整缩放比例 let videoAspectRatio = 16.0/9.0 // 替换成你的视频实际宽高比 let planeAspectRatio = plane.width / plane.height var scaleX: CGFloat = 1.0 var scaleY: CGFloat = 1.0 if videoAspectRatio > planeAspectRatio { // 视频比平面宽,缩放Y轴让高度适配平面 scaleY = CGFloat(planeAspectRatio / videoAspectRatio) } else { // 视频比平面高,缩放X轴让宽度适配平面 scaleX = CGFloat(videoAspectRatio / planeAspectRatio) } // 3. 创建变换:先缩放,再平移让视频居中 let scaleTransform = CATransform3DMakeScale(scaleX, scaleY, 1) let translateTransform = CATransform3DMakeTranslation((1 - scaleX)/2, (1 - scaleY)/2, 0) material.contentsTransform = CATransform3DConcat(scaleTransform, translateTransform) // 可选:如果视频倒过来,加上Y轴翻转 // material.contentsTransform = CATransform3DConcat(material.contentsTransform, CATransform3DMakeScale(1, -1, 1)) // 开始播放 player.play()
额外注意点
- 如果只需要视频显示在平面的一面,可以设置
material.isDoubleSided = false,节省渲染性能 - 记得处理视频播放的生命周期:比如进入后台时暂停
player.pause(),回到前台时继续player.play() - 如果需要视频循环播放,可以设置
player.actionAtItemEnd = .none,然后监听AVPlayerItemDidPlayToEndTimeNotification来实现循环逻辑
内容的提问来源于stack exchange,提问作者narner
相关产品推荐
相关产品推荐

