这节讲如何在threejs中添加一个视频的功能,在某些场景中可能会需要播放视频,比如在场景中方式一个大屏幕,大屏幕上需要播放视频,亦或者在场景中添加电视机的模型,电视机的画面上需要播放一些视频等。
其实添加视频和以前介绍的添加纹理贴图一样,只不过这是添加视频的纹理贴图,让画面动起来,首先还是需要创建一个场景,包括scene,camera,renderer,OrbitControls可以根据需要添加
initScene(){scene = new THREE.Scene();},initCamera(){this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);this.camera.position.set(100,100,100);},initRenderer(){this.renderer = new THREE.WebGLRenderer({ antialias: true });this.container = document.getElementById("container")this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);this.renderer.setClearColor('#294f9a', 1.0);this.container.appendChild(this.renderer.domElement);},initControl(){this.controls = new OrbitControls(this.camera, this.renderer.domElement);this.controls.enableDamping = true;// // 最大角度this.controls.maxPolarAngle = Math.PI / 2.2;},initAnimate() {requestAnimationFrame(this.initAnimate);this.renderer.render(scene, this.camera);},
创建完场景后,我们在场景中添加一个整体,然后在正方体的各个面都添加视频画面,
initVideo( x,y,z,width,length,videoId){//先创建一个正方体模型let geometry = new THREE.BoxGeometry(20,20,20);//获取到页面中video标签中的视频let video = document.getElementById(videoId);//将视频数据用于贴图let texture = new THREE.VideoTexture(video);//设置视频的效果texture.minFilter = THREE.LinearFilter;texture.magFilter = THREE.LinearFilter;//给每个面添加视频const material = [new THREE.MeshBasicMaterial({ map: texture}),new THREE.MeshBasicMaterial({ map: texture }),new THREE.MeshBasicMaterial({ map: texture }),new THREE.MeshBasicMaterial({ map: texture }),new THREE.MeshBasicMaterial({ map: texture }),new THREE.MeshBasicMaterial({ map: texture })]//创建网格let mesh = new THREE.Mesh(geometry, material);//设置位置mesh.position.set(x,y,z);//添加到场景中scene.add(mesh);},
最终就实现了在一个正方体的的六个面都添加视频效果,也可以根据需求将正方体设置会举矩形,类似电视机的效果,然后只在正面添加视频效果,完整的代码如下:
<template><div><div id="container"></div><video id="video" autoplay loop muted><source src="/static/video/video.mp4"></video></div>
</template><script>
import * as THREE from 'three'
import {OrbitControls} from "three/addons/controls/OrbitControls";let scene;
export default {name: "bay-single",data() {return{camera:null,water:undefined,}},methods:{initScene(){scene = new THREE.Scene();},initCamera(){this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);this.camera.position.set(100,100,100);},initVideo( x,y,z,width,length,videoId){//先创建一个正方体模型let geometry = new THREE.BoxGeometry(20,20,20);//获取到页面中video标签中的视频let video = document.getElementById(videoId);//将视频数据用于贴图let texture = new THREE.VideoTexture(video);//设置视频的效果texture.minFilter = THREE.LinearFilter;texture.magFilter = THREE.LinearFilter;//给每个面添加视频const material = [new THREE.MeshBasicMaterial({ map: texture}),new THREE.MeshBasicMaterial({ map: texture }),new THREE.MeshBasicMaterial({ map: texture }),new THREE.MeshBasicMaterial({ map: texture }),new THREE.MeshBasicMaterial({ map: texture }),new THREE.MeshBasicMaterial({ map: texture })]//创建网格let mesh = new THREE.Mesh(geometry, material);//设置位置mesh.position.set(x,y,z);//添加到场景中scene.add(mesh);},initRenderer(){this.renderer = new THREE.WebGLRenderer({ antialias: true });this.container = document.getElementById("container")this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);this.renderer.setClearColor('#294f9a', 1.0);this.container.appendChild(this.renderer.domElement);},initControl(){this.controls = new OrbitControls(this.camera, this.renderer.domElement);this.controls.enableDamping = true;// // 最大角度this.controls.maxPolarAngle = Math.PI / 2.2;},initAnimate() {requestAnimationFrame(this.initAnimate);this.renderer.render(scene, this.camera);},initPage(){this.initScene();this.initCamera();this.initRenderer();this.initControl();this.initVideo( 0, 0, 0, 200, 100 , 'video' );this.initAnimate();}},mounted() {this.initPage()}
}
</script><style scoped>
#container{position: absolute;width:100%;height:100%;overflow: hidden;
}</style>
效果图