这节讲如何在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>
效果图