How to manage video inside a class

So, im working on displaying multiple videos in a 3D website.

I´ve copy the code from the three.js example :
https://threejs.org/examples/?q=video#webgl_materials_video

I´ve replicated 3 times :

///////////
	// VIDEO 1 //
	///////////
	// create the video element
	//document.getElementById("render").innerHTML+= "<video ></video>";

	video1 = document.createElement("video");
	video1.setAttribute("muted", "muted");
	// video.id = 'video';
	// video.type = ' video/ogg; codecs="theora, vorbis" ';
	video1.src = "videos/selva.mp4";
	video1.load(); // must call after setting/changing source
	//video.play();
		
	var videoImage = document.createElement("canvas");;
	videoImage.width = 1920;
	videoImage.height = 1080;

	videoImageContext1 = videoImage.getContext( '2d' );
	// background color if no video present
	videoImageContext1.fillStyle = '#000000';
	videoImageContext1.fillRect( 0, 0, videoImage.width, videoImage.height );

	videoTexture1 = new THREE.Texture( videoImage );
	videoTexture1.minFilter = THREE.LinearFilter;
	videoTexture1.magFilter = THREE.LinearFilter;
	
	var movieMaterial = new THREE.MeshBasicMaterial( { map: videoTexture1, overdraw: true, side:THREE.DoubleSide } );
	var movieGeometry = new THREE.PlaneGeometry( 20, 10, 0, 0 );
	var movieScreen = new THREE.Mesh( movieGeometry, movieMaterial );
	movieScreen.position.set(cube.position.x+1,cube.position.y,cube.position.z);
	movieScreen.rotation.y = 11;
	
	
	
	///////////
	// VIDEO 2//
	///////////
	// create the video element
	
		
	
	video2 = document.createElement("video");
	video2.setAttribute("muted", "muted");
	// video.id = 'video';
	// video.type = ' video/ogg; codecs="theora, vorbis" ';
	video2.src = "videos/sintel.ogv";
	video2.load(); // must call after setting/changing source
	//video.play();
		
	var videoImage2  = document.createElement("canvas");
	videoImage2.width = 480;
	videoImage2.height = 204;

	videoImageContext2 = videoImage2.getContext( '2d' );
	// background color if no video present
	videoImageContext2.fillStyle = '#000000';
	videoImageContext2.fillRect( 0, 0, videoImage2.width, videoImage2.height );

	videoTexture2 = new THREE.Texture( videoImage2 );
	videoTexture2.minFilter = THREE.LinearFilter;
	videoTexture2.magFilter = THREE.LinearFilter;
	
	var movieMaterial2 = new THREE.MeshBasicMaterial( { map: videoTexture2, overdraw: true, side:THREE.DoubleSide } );
	var movieGeometry2 = new THREE.PlaneGeometry( 20, 10, 0, 0 );
	var movieScreen2 = new THREE.Mesh( movieGeometry2, movieMaterial2 );
	movieScreen2.position.set(cube2.position.x-1,cube2.position.y,cube2.position.z);
	movieScreen2.rotation.y = 11;
	
	
	///////////
	// VIDEO 3//
	///////////
	// create the video element
	video3 = document.createElement("video");
	video3.setAttribute("muted", "muted");
	// video.id = 'video';
	// video.type = ' video/ogg; codecs="theora, vorbis" ';
	video3.src = "videos/bird.mp4";
	video3.load(); // must call after setting/changing source
	//video.play();
		
	var videoImage3 = document.createElement("canvas");;
	videoImage3.width = 1280;
	videoImage3.height = 720;

	videoImageContext3 = videoImage3.getContext( '2d' );
	// background color if no video present
	videoImageContext3.fillStyle = '#000000';
	videoImageContext3.fillRect( 0, 0, videoImage3.width, videoImage3.height );

	videoTexture3 = new THREE.Texture( videoImage3 );
	videoTexture3.minFilter = THREE.LinearFilter;
	videoTexture3.magFilter = THREE.LinearFilter;
	
	var movieMaterial3 = new THREE.MeshBasicMaterial( { map: videoTexture3, overdraw: true, side:THREE.DoubleSide } );
	var movieGeometry3 = new THREE.PlaneGeometry( 20, 10, 0, 0 );
	var movieScreen3 = new THREE.Mesh( movieGeometry3, movieMaterial3 );
	movieScreen3.position.set(cube3.position.x,cube3.position.y,cube3.position.z+1);
	//movieScreen3.rotation.y = 11;
	
	
	scene.add(movieScreen);
	scene.add(movieScreen2);
	scene.add(movieScreen3);

The same happens with variables :

var video1, videoImageContext1, videoTexture1;
var video2, videoImageContext2, videoTexture2;
var video3, videoImageContext3, videoTexture3;

var videorayscasting1 = false;
var videorayscasting2 = false;
var videorayscasting3 = false;

var videoplaying1 = false;
var videoplaying2 = false;
var videoplaying3 = false;

and with with the update :

	if ( video1.readyState === video1.HAVE_ENOUGH_DATA ) {
		videoImageContext1.drawImage( video1, 0, 0 );
		if ( videoTexture1 ) videoTexture1.needsUpdate = true;
	}
	if ( video2.readyState === video2.HAVE_ENOUGH_DATA ) {
		videoImageContext2.drawImage( video2, 0, 0 );
		if ( videoTexture2 ) videoTexture2.needsUpdate = true;
	}
	if ( video3.readyState === video3.HAVE_ENOUGH_DATA ) {
		videoImageContext3.drawImage( video3, 0, 0 );
		if ( videoTexture3 ) videoTexture3.needsUpdate = true;
	}

This is working correctly, but as you can see, is a lot of code repeated it self 3 times. So I want to make a “class” to make this code reusable(I don´t know if in javascript is the same terminology , im thinking in the terms of c++ and other more tradional OOP languages). Where I can just make an object.

So i´ve made another file for working with “video player class” :

JPvideoplayer = function (_position,_src) {

	
	var position;
	var video, videoImageContext, videoTexture;
	var videorayscasting;
	var videoplaying;

	var lala = false;
	var scope = this;

	/*this.setup = function(){
		console.log("ARRANCA VIDEOPLAYER VERGA");
	}*/	
	function start(){
		var textureLoader = new THREE.TextureLoader();
		var crateTexture = new textureLoader.load("texturas/tele.png");	
		
		var geometry = new THREE.BoxGeometry( 21, 11, 0 );
		var material = new THREE.MeshPhongMaterial( {color: 0xffffff, map:crateTexture} );
		var cube = new THREE.Mesh( geometry, material );
		
		cube.name = "Pantalla_test";
		cube.position.x = _position.x;
		cube.position.y = _position.y;
		cube.position.z = _position.z;
		cube.rotation.y = 11;
		scene.add( cube );
		
		
		///////////
		// VIDEO 1 //
		///////////
		// create the video element
		//document.getElementById("render").innerHTML+= "<video ></video>";
		$("#render").append("<video id='lala'></video>");
		
		
		video = document.getElementById("lala");
		video.setAttribute("muted", "muted");
		// video.id = 'video';
		// video.type = ' video/ogg; codecs="theora, vorbis" ';
		video.src = "videos/sintel.ogv";
		video.load(); // must call after setting/changing source
		//video.play();
			
		var videoImage = document.createElement("canvas");;
		videoImage.width = 1920;
		videoImage.height = 1080;

		videoImageContext = videoImage.getContext( '2d' );
		// background color if no video present
		videoImageContext.fillStyle = '#000000';
		videoImageContext.fillRect( 0, 0, videoImage.width, videoImage.height );

		videoTexture = new THREE.Texture( videoImage );
		videoTexture.minFilter = THREE.LinearFilter;
		videoTexture.magFilter = THREE.LinearFilter;
		
		var movieMaterial = new THREE.MeshBasicMaterial( { map: videoTexture1, overdraw: true, side:THREE.DoubleSide } );
		var movieGeometry = new THREE.PlaneGeometry( 20, 10, 0, 0 );
		var movieScreen = new THREE.Mesh( movieGeometry, movieMaterial );
		movieScreen.position.set(cube.position.x+1,cube.position.y,cube.position.z);
		movieScreen.rotation.y = 11;
		
		scene.add(movieScreen);
		//console.log("BRUM BRUM BRUM");
	}
	start();
	
	this.display  = function (){
		
		
	}
	this.updateVideo = function(){
		if ( video.readyState === video.HAVE_ENOUGH_DATA ) {
			videoImageContext.drawImage( video, 0, 0 );
			if ( videoTexture ) videoTexture.needsUpdate = true;
		}
		/*if(lala){
			console.log("LALALA");
		}*/
		
	}
	
	//setup();
};

So i call the constructor in a init function where i pass only position and src of video. :

jp_video1 = new JPvideoplayer(new THREE.Vector3( 0, camposy, 0 ),"videos/selva.mp4");

So the cube with the texture to simulate the TV appears and everything works , except for the object video inside my class. When ever i´ve tryed to call a function for playing the video :

if(jp_video1.videorayscasting){
	if(jp_video1.videoplaying){
		jp_video1.video.pause();
	}else{
		jp_video1.video.play();
	}
	jp_video1.videoplaying = !jp_video1.videoplaying;
}

I get this error :

render.js:390 Uncaught TypeError: Cannot read property ‘play’ of undefined
at HTMLDocument.mousePressed (render.js:390)

It seems like i can´t access the variable "video " inside my JPvideoplayer class. I don´t see what im doing wrong, everything else aside the video variable appears when i call the object. And im initiating the video the same way as if it was not inside a “class”.

What im I doing wrong or im not seeing?

It looks like jpvideo1 exists as an object, otherwise it wouldn’t pass that condition block. The error is saying jp_video1.video is undefined. So however you’re passing jpvideo1 to your class, you’re not defining that property.

1 Like