Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/469.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Render on Demand Three.js多画布(带类实现)_Javascript_Three.js - Fatal编程技术网

Javascript Render on Demand Three.js多画布(带类实现)

Javascript Render on Demand Three.js多画布(带类实现),javascript,three.js,Javascript,Three.js,我的情况是这样的:我有一个包含多个资产的资产清单,每当用户悬停在它们上面时,我都希望使用OrbitController开始渲染(我更喜欢轨迹球,但我知道这是不可能的,因为有一个bug)。关键是类实例的“this”变量不能传递到类的render方法中: import*作为三个源'https://threejsfundamentals.org/threejs/resources/threejs/r122/build/three.module.js'; 从导入{OrbitControls}https:

我的情况是这样的:我有一个包含多个资产的资产清单,每当用户悬停在它们上面时,我都希望使用OrbitController开始渲染(我更喜欢轨迹球,但我知道这是不可能的,因为有一个bug)。关键是类实例的“this”变量不能传递到类的render方法中:

import*作为三个源'https://threejsfundamentals.org/threejs/resources/threejs/r122/build/three.module.js';
从导入{OrbitControls}https://threejsfundamentals.org/threejs/resources/threejs/r122/examples/jsm/controls/OrbitControls.js';
班长{
构造函数(canvasId)
{
this.canvas=document.querySelector(canvasId);
this.renderer=new THREE.WebGLRenderer({canvas:this.canvas});
这个.fov=75;
this.aspect=2;//画布默认值
该值为0.1;
这个.far=5;
this.camera=新的3.PerspectiveCamera(this.fov,this.aspect,this.near,this.far);
这个.camera.position.z=2;
this.controls=新的轨道控制(this.camera,this.canvas);
this.controls.target.set(0,0,0);
this.controls.update();
this.scene=新的三个.scene();
this.color=0xFFFFFF;
这个强度=1;
this.light=新的三个方向光(this.color,this.intensity);
此.light.position.set(-1,2,4);
this.scene.add(this.light);
这个.boxWidth=1;
此.boxHeight=1;
这个.boxDepth=1;
this.geometry=新的三个.BoxGeometry(this.boxWidth、this.boxHeight、this.boxDepth);
}
makeInstance(几何体、颜色、x){
让材质=新的三个。网格材质(颜色);
让立方体=新的三个网格(几何体、材质);
this.scene.add(立方体);
立方体位置x=x;
返回立方体;
}
ResizeRenderToDisplaySize(渲染器){
this.canvas=this.renderer.doElement;
让宽度=this.canvas.clientWidth;
让高度=this.canvas.clientHeight;
让needResize=this.canvas.width!==width | | this.canvas.height!==height;
如果(需要调整大小){
设置大小(宽度、高度、假);
}
返回需要调整大小;
}
render(){
//此->控件对象或窗口,而它应该是类实例
if(this.resizerenderToDisplaySize(this.renderer)){
this.canvas=this.renderer.doElement;
this.camera.aspect=this.canvas.clientWidth/this.canvas.clientHeight;
this.camera.updateProjectMatrix();
}
this.renderer.render(this.scene,this.camera);
}
起动器(){
this.makeInstance(this.geometry,0x44aa88,0);
this.makeInstance(this.geometry,0x8844aa,-2);
this.makeInstance(this.geometry,0xaa8844,2);
这个。render();
this.controls.addEventListener('change',this.render);
window.addEventListener('resize',this.render);
//注意:这是OrbitControls问题的解决方法
//在iframe中。将在中修复问题后删除
//3.js
window.addEventListener('mousedown',(e)=>{
e、 预防默认值();
window.focus();
});
window.addEventListener('keydown',(e)=>{
e、 预防默认值();
});
}
}
设main=newmain('a');
main.starter();
我唯一能做的工作(但不是正确的)就是用“main”实例替换render方法中的“this”

render(){
if(main.resizerenderToDisplaySize(this.renderer)){
main.canvas=main.renderer.doElement;
main.camera.aspect=main.canvas.clientWidth/main.canvas.clientHeight;
main.camera.updateProjectMatrix();
}
main.renderer.render(main.scene,main.camera);
}
然而,以这种方式我杀死了这个类,并且我无法生成其他实例,例如main2
我已经生成了一个代码笔:

您正在提供
这个。将
呈现给事件处理程序
this.render
技术上是指向原型函数(
Main.prototype.render
)的指针

当启动处理程序时,上下文将取决于源代码执行处理程序的方式。在大多数情况下,提供给处理程序的上下文将是源的上下文(甚至可能是
null
)。例如,
window.addEventListener('resize',handler)
将通过调用与
handler.call(窗口,事件)等价的函数来触发调整大小事件

有几种方法可以解决这个问题

箭头函数隐式
箭头函数使用定义它们的上下文的
。因此,如果您的arrow函数是在类的成员函数中定义的,并且该成员函数是在该类实例的上下文中执行的,则该arrow函数体中的
将引用该实例

类测试{
构造函数(){
this.name=“Test”
//在实例上下文中定义的箭头函数:
window.addEventListener('resize',()=>{
console.log(this.name)//打印:“Test”
} )
//正常函数将以“窗口”作为其“this”执行
addEventListener('resize',function()){
console.log(this.name)//结果可能因浏览器而异,但“this”不是测试的实例
} )
}
}
将函数绑定到上下文 使用可以将函数附加到指定的上下文。
bind
函数返回一个永久绑定到所提供上下文的新函数

类测试{
构造函数(){
this.name=“Test”
this.boundRender=this.render.bind(this)//返回永久绑定到“this”的“render”
window.addEventListener('resize',this.boundRender)
}
render(){
console.log(this.name)
}
}
上面的示例仍然会将“Test”打印到控制台。即使
resize
事件希望使用
窗口
上下文执行处理程序,
绑定import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r122/build/three.module.js';
import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r122/examples/jsm/controls/OrbitControls.js';



class Main {

  constructor(canvasId)
  {
    this.canvas = document.querySelector(canvasId);

    this.renderer = new THREE.WebGLRenderer({canvas: this.canvas});

    this.fov = 75;
    this.aspect = 2;  // the canvas default
    this.near = 0.1;
    this.far = 5;
    this.camera = new THREE.PerspectiveCamera(this.fov, this.aspect, this.near, this.far);
    this.camera.position.z = 2;

    this.controls = new OrbitControls(this.camera, this.canvas);
    this.controls.target.set(0, 0, 0);
    this.controls.update();

    this.scene = new THREE.Scene();


    this.color = 0xFFFFFF;
    this.intensity = 1;
    this.light = new THREE.DirectionalLight(this.color, this.intensity);
    this.light.position.set(-1, 2, 4);
    this.scene.add(this.light);


    this.boxWidth = 1;
    this.boxHeight = 1;
    this.boxDepth = 1;
    this.geometry = new THREE.BoxGeometry(this.boxWidth, this.boxHeight, this.boxDepth);
    
     this.boundRender = this.render.bind( this );
  }

  makeInstance(geometry, color, x){

    let material = new THREE.MeshPhongMaterial(color);

    let cube = new THREE.Mesh(geometry, material);
    this.scene.add(cube);
    cube.position.x = x;

    return cube;
  }



  resizeRendererToDisplaySize(renderer) {
    this.canvas = this.renderer.domElement;
    let width = this.canvas.clientWidth;
    let height = this.canvas.clientHeight;
    let needResize = this.canvas.width !== width || this.canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }

    return needResize;
  }

  render() {
    
    if (this.resizeRendererToDisplaySize(this.renderer)) {
      this.canvas = this.renderer.domElement;
      this.camera.aspect = this.canvas.clientWidth / this.canvas.clientHeight;
      this.camera.updateProjectionMatrix();
    }
    
    this.renderer.render(this.scene, this.camera);
    
  }

  starter() {

    this.makeInstance(this.geometry, 0x44aa88,  0);
    this.makeInstance(this.geometry, 0x8844aa, -2);
    this.makeInstance(this.geometry, 0xaa8844,  2);

    this.render();

    this.controls.addEventListener('change', this.boundRender );

    window.addEventListener('resize', this.boundRender);

    // note: this is a workaround for an OrbitControls issue
    // in an iframe. Will remove once the issue is fixed in
    // three.js

    window.addEventListener('mousedown', (e) => {
      e.preventDefault();
      window.focus();
    });

    window.addEventListener('keydown', (e) => {
      e.preventDefault();
    });
  }
}



let main = new Main('#a');
main.starter();

let main2 = new Main('#b');
main2.starter();