两个 Three-JS 对象如何在同一页面同时运行和动画?

Posted

技术标签:

【中文标题】两个 Three-JS 对象如何在同一页面同时运行和动画?【英文标题】:How to two Three-JS Objects run and animate at the same time same page? 【发布时间】:2021-11-20 06:23:58 【问题描述】:

我无法弄清楚为什么通过添加第二个对象,第一个对象会停止动画并且不再运行?我如何才能弄清楚为什么我的对象会相互抵消,以及如何创建两个不同或多个同时动画的threejs项目? 我想在某个文件中运行多于三个.js 脚本。有人可以帮助我吗? 谢谢

    //firt object

var scene2 = new THREE.Scene();
document.addEventListener( 'mousemove', onMouseMove, false );
var camera2 = new THREE.PerspectiveCamera( 40, window.innerWidth/window.innerHeight, 0.1, 1000 );
var mouseX;
var mouseY;

var renderer2 = new THREE.WebGLRenderer();
renderer2.setSize( window.innerWidth, window.innerHeight );
renderer2.autoClear = false;
document.body.appendChild( renderer2.domElement );

window.addEventListener("resize", function() 
  camera2.aspect = window.innerWidth / window.innerHeight;
  camera2.updateProjectionMatrix();
  renderer2.setSize( window.innerWidth, window.innerHeight );
);

var distance = Math.min(200, window.innerWidth / 4);
var geometry = new THREE.Geometry();

for (var i = 0; i < 1000; i++) 

  var vertex = new THREE.Vector3();

  var theta = THREE.Math.randFloatSpread(360); 
  var phi = THREE.Math.randFloatSpread(360); 

  vertex.x = distance * Math.sin(theta) * Math.cos(phi);
  vertex.y = distance * Math.sin(theta) * Math.sin(phi);
  vertex.z = distance * Math.cos(theta);

  geometry.vertices.push(vertex);

var particles = new THREE.Points(geometry, new THREE.PointsMaterial(color: 0xFFFF00, size: 2));
particles.boundingSphere = 50;


var renderingParent = new THREE.Group();
renderingParent.add(particles);

var resizeContainer = new THREE.Group();
resizeContainer.add(renderingParent);
scene2.add(resizeContainer);

camera2.position.z = 400;

var animate = function () 
  requestAnimationFrame( animate );
  renderer2.render( scene2, camera2 );
;
var myTween;
function onMouseMove(event) 
  if(myTween)
    myTween.kill();
  
  mouseX = ( event.clientX / window.innerWidth ) * 2 - 1;
  mouseY = - ( event.clientY / window.innerHeight ) * 2 + 1;
  myTween = gsap.to(particles.rotation, duration: 0.1, x: mouseY*-1, y: mouseX);
  //particles.rotation.x = mouseY*-1;
  //particles.rotation.y = mouseX;

animate();

// Scaling animation
var animProps = scale: 0.5, xRot: 0, yRot: 0;
gsap.to(animProps, duration: 20, scale: 1.5, repeat: -1, yoyo: true, ease: "sine", onUpdate: function() 
  renderingParent.scale.set(animProps.scale,animProps.scale,animProps.scale);
);

gsap.to(animProps, duration: 120, xRot: Math.PI * 2, yRot: Math.PI * 4, repeat: -1, yoyo: true, ease: "none", onUpdate: function() 
  renderingParent.rotation.set(animProps.xRot,animProps.yRot,0);
);

'''

//second object
<script>
    var scene = new THREE.Scene();
    document.addEventListener( 'mousemove', onMouseMove, false );
    var camera = new THREE.PerspectiveCamera( 40, window.innerWidth/window.innerHeight, 0.1, 1000 );
    var mouseX;
    var mouseY;
    
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.autoClear = false;
    document.body.appendChild( renderer.domElement );
    
    window.addEventListener("resize", function() 
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize( window.innerWidth, window.innerHeight );
    );
    
    var distance = Math.min(200, window.innerWidth / 4);
    var geometry = new THREE.Geometry();
    
    for (var i = 0; i < 1000; i++) 
    
      var vertex = new THREE.Vector3();
    
      var theta = THREE.Math.randFloatSpread(360); 
      var phi = THREE.Math.randFloatSpread(360); 
    
      vertex.x = distance * Math.sin(theta) * Math.cos(phi);
      vertex.y = distance * Math.sin(theta) * Math.sin(phi);
      vertex.z = distance * Math.cos(theta);
    
      geometry.vertices.push(vertex);
    
    var particles = new THREE.Points(geometry, new THREE.PointsMaterial(color: 0xFFFF00, size: 2));
    particles.boundingSphere = 50;
    
    
    var renderingParent = new THREE.Group();
    renderingParent.add(particles);
    
    var resizeContainer = new THREE.Group();
    resizeContainer.add(renderingParent);
    scene.add(resizeContainer);
    
    camera.position.z = 400;
    
    var animate = function () 
      requestAnimationFrame( animate );
      renderer.render( scene, camera );
    ;
    var myTween;
    function onMouseMove(event) 
      if(myTween)
        myTween.kill();
      
      mouseX = ( event.clientX / window.innerWidth ) * 2 - 1;
      mouseY = - ( event.clientY / window.innerHeight ) * 2 + 1;
      myTween = gsap.to(particles.rotation, duration: 0.1, x: mouseY*-1, y: mouseX);
      //particles.rotation.x = mouseY*-1;
      //particles.rotation.y = mouseX;
    
    animate();
    
    // Scaling animation
    var animProps = scale: 0.5, xRot: 0, yRot: 0;
    gsap.to(animProps, duration: 20, scale: 1.5, repeat: -1, yoyo: true, ease: "sine", onUpdate: function() 
      renderingParent.scale.set(animProps.scale,animProps.scale,animProps.scale);
    );
    
    gsap.to(animProps, duration: 120, xRot: Math.PI * 2, yRot: Math.PI * 4, repeat: -1, yoyo: true, ease: "none", onUpdate: function() 
      renderingParent.rotation.set(animProps.xRot,animProps.yRot,0);
    );
    
    </script>

'''

【问题讨论】:

【参考方案1】:

您有两个名为 animate 的函数(即使您已努力将场景重命名为 scene2,将相机重命名为 camera2 等)

由于animate 调用requestAnimationFrame(animate),将不再调用另一个(被覆盖的)动画函数。

最简单(虽然绝不是漂亮)的修复方法是将其他动画函数类似地重命名为 animate2

更好的解决方法是将此代码重构为具有本地命名空间的函数,这样这样的混淆就更难了。 (当你这样做时,你还可以将创建几何的函数重构为它自己的函数等)

【讨论】:

非常感谢 AKX 第一种方式有效,我会尽快尝试第二种方式,但非常感谢。我遇到了另一个问题,我想将场景的背景从黑色更改为白色,但找不到实现它的方法。你能帮助我吗?谢谢 我搜索了“three.js 背景颜色”,找到了***.com/a/16177178/51685 - 创建场景后添加scene.background = new THREE.Color( 0xffffff );

以上是关于两个 Three-JS 对象如何在同一页面同时运行和动画?的主要内容,如果未能解决你的问题,请参考以下文章

pycham怎么在同一个页面出现3个图

两个线程不能同时作用于同一个对象吗[关闭]

如果我在同一个类上同步了两个方法,它们可以同时运行吗?

Three-js 创建第一个3D场景

如何在同一个项目中同时拥有 MVC 和 Razor 页面?

如何强制两个数字在 LaTeX 中保持在同一页面上?