当前位置: 首页 > news >正文

Three.js 视频碎片教程

视频碎片 ·Video Effect· ▶ 在线运行案例

  • 案例合集:三维可视化功能案例(threehub.cn)
  • 开源仓库github地址:https://github.com/z2586300277/three-cesium-examples
  • 400个案例代码:网盘链接

你将学到什么

  • OrbitControls 相机轨道交互
  • requestAnimationFrame渲染循环与resize自适应

效果说明

本案例演示视频碎片效果:基于 WebGL 实现「视频碎片」可视化效果,附完整可运行源码;核心用到 OrbitControls。建议先打开文首在线案例查看动态画面,再对照下方源码逐步理解。

核心概念

  • Scene / Camera / WebGLRenderer构成最小渲染闭环;大场景可开logarithmicDepthBuffer缓解 Z-fighting。
  • OrbitControls提供轨道旋转/缩放;开启enableDamping后需在 animate 中controls.update()
  • 阅读下方完整源码时,建议从init/load/animate三条主线入手,再深入 shader 与工具函数。

实现步骤

  • 搭建 Scene、PerspectiveCamera、WebGLRenderer,挂载 canvas 并处理resize
  • 创建 OrbitControls(及 Raycaster 等交互控件,若源码包含)
  • requestAnimationFrame循环中更新状态并 render(Cesium 为viewer.render或自动渲染)
  • 代码要点

    import * as THREE from 'three'

    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

    const box = document.getElementById('box')

    const scene = new THREE.Scene()

    const camera = new THREE.PerspectiveCamera(50, box.clientWidth / box.clientHeight, 0.1, 1000)

    camera.position.set(0, 0, 20)

    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true })

    renderer.setSize(box.clientWidth, box.clientHeight)

    box.appendChild(renderer.domElement)

    const controls = new OrbitControls(camera, renderer.domElement)

    controls.enableDamping = true

    const video = document.createElement('video')

    video.crossOrigin = 'anonymous' // 跨域

    video.src = 'https://z2586300277.github.io/3d-file-server/video/test.mp4'

    video.loop = true // 循环播放

    video.muted = true // 静音

    video.play()

    const texture = await new Promise(r => video.onloadeddata = () => r(new THREE.VideoTexture(video))) // 创建视频纹理

    const group = new THREE.Group() const config = { width: 16, height: 9, xGrid: 4, yGrid: 3, offset: 0.1 } const ux = 1 / config.xGrid const uy = 1 / config.yGrid const planeWidth = config.width / config.xGrid - config.offset const planeHeight = config.height / config.yGrid - config.offset for (let i = 0; i < config.xGrid; i++) { for (let j = 0; j < config.yGrid; j++) { // 创建 4 * 3 子平面实现整体效果 const geometry = new THREE.PlaneGeometry(planeWidth, planeHeight) const material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide })

    // 切割uv来实现纹理映射到全部平面 const uvs = geometry.attributes.uv.array for (let index = 0; index < uvs.length; index += 2) { uvs[index] = (uvs[index] + i) * ux uvs[index + 1] = (uvs[index + 1] + j) * uy }

    const mesh = new THREE.Mesh(geometry, material)

    mesh.dx = 0.004 * (0.5 - Math.random()) mesh.dy = 0.004 * (0.5 - Math.random())

    const x = (i - config.xGrid / 2)planeWidth + planeWidth0.5 + (i * config.offset) / 2 const y = (j - config.yGrid / 2)planeHeight + planeHeight0.5 + (j * config.offset) / 2 mesh.position.set(x, y, 0) group.add(mesh)

    }

    } scene.add(group)

    const clock = new THREE.Clock() animate()

    function animate() {

    const elapsedTime = clock.getElapsedTime()

    for (const mesh of group.children) { mesh.rotation.x += Math.sin(elapsedTime0.1)mesh.dx; mesh.rotation.y += Math.sin(elapsedTime0.2)mesh.dy;

    mesh.position.x -= Math.sin(elapsedTime0.1)mesh.dx; mesh.position.y += Math.sin(elapsedTime0.3)mesh.dy; mesh.position.z += Math.cos(elapsedTime0.2)mesh.dx; }

    requestAnimationFrame(animate)

    controls.update()

    renderer.render(scene, camera)

    }

    window.onresize = () => {

    renderer.setSize(box.clientWidth, box.clientHeight)

    camera.aspect = box.clientWidth / box.clientHeight

    camera.updateProjectionMatrix()

    }

    完整源码:GitHub

    小结

    • 本文提供视频碎片完整 Three.js 源码与在线 Demo,建议先运行案例再改 uniform/参数做二次实验
    • 更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库
http://www.jsqmd.com/news/1089716/

相关文章:

  • 浏览器音乐解密革命:Unlock-Music如何让你真正拥有数字音乐
  • NifSkope突破性实战指南:掌握游戏文件编辑与3D模型处理的完整解决方案
  • 终极Mac鼠标增强指南:如何让10美元鼠标超越苹果触控板体验
  • 告别重复配置:在VS2022中创建可复用的OpenCV项目模板
  • Windows窗口置顶神器:AlwaysOnTop让你轻松实现多窗口高效管理
  • 免费开源虚拟桌面伴侣:Mate Engine让你的桌面活起来
  • 测试用例繁衍 Skill:从 JSDoc 到 Jest/Mocha 覆盖边界、异常与回归
  • 网络安全渗透测试入门:从零到实战的完整学习路径与靶场攻防指南
  • 3步快速掌握iOS激活锁绕过:免费解决方案终极指南
  • 从YT9218芯片看国产交换机的工业场景落地与成本优势
  • Windows任务栏透明化神器:TranslucentTB中文配置终极指南
  • 5分钟极速部署:用DroidCam将安卓手机变身专业高清摄像头
  • 基于HarmonyOS 7.0 跨端开发的流浪动物救助页面实战
  • MSPM0复位与低功耗模式解析:从系统重启到异步时钟请求
  • ESXi Unlocker 终极指南:在VMware ESXi上运行macOS虚拟机的完整解决方案
  • Navicat重置工具终极指南:3种简单方法解决Mac版试用到期问题
  • 魔兽世界API查询与宏命令生成工具:终极免费指南
  • TPIC7710EVM评估模块:汽车电子ASIC硬件设计与GUI软件调试实战
  • 【大数据】HiveQL视图:从逻辑抽象到查询优化的实战指南
  • 为什么你的音乐文件被加密了?5步掌握Unlock-Music解锁技术
  • 计算机专业就业:一篇讲清核心用法
  • PDMS Pipeline Tool 实战指南(一):从零到一的部署与集成
  • 终极指南:5分钟快速上手REFramework,打造专属RE引擎游戏模组
  • 从0到挖SRC漏洞全流程详细讲解,耐心看完拿下第一桶金只是时间问题!
  • ENSP实战:基于EVPN构建VXLAN数据中心网络
  • DS4Windows终极指南:3大场景解锁PlayStation手柄的PC游戏潜力
  • 5步解锁被锁的iPhone:applera1n帮你免费绕过iOS 15-16激活锁
  • 抖音无水印下载器终极指南:三分钟掌握高效下载技巧
  • 免费解锁WeMod Pro的终极指南:3步轻松获取高级功能
  • VoiceFixer:3分钟让任何模糊语音变清晰的AI音频修复神器