代码之家  ›  专栏  ›  技术社区  ›  Hide

三.js对象动态变化与LOD动画

  •  0
  • Hide  · 技术社区  · 6 年前

    宇宙的概念有这么多的文本。

    有两件事我必须实现。

    第一。当相机和物体之间的距离较远时,物体就是恒星。

    第二。当摄影机和对象之间的距离接近时,对象是文本。

    所以,我用 LOD .

    一切正常。

    我想插入平滑变化过渡(动画)到它。

    所以我读了一本书,遗憾的是,它有任何属性。

    是否可以将动画插入LOD?

    或者有什么可能的解决办法?

    // VARIABLES
    let clock, camera, scene, renderer, mixer;
    
    var myElement = document.getElementById("threejs");
    const mouse = new THREE.Vector2();
    const clicked = new THREE.Vector2();
    const target = new THREE.Vector2();
    const windowHalf = new THREE.Vector2( window.innerWidth / 2, window.innerHeight / 2 );
    const moveState = {forward: 0, back: 0};
    var isMobile = false;
    var textCount = 200;
    
    checkMobile()
    init();
    
    function init() { 
      // CAMERA
      camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2100 );
      camera.position.x = 0;
      camera.position.y = 0;
      camera.position.z = 1200;
    
      scene = new THREE.Scene();
      scene.fog = new THREE.Fog(0xf05fa6, 300, 400);
    
      clock = new THREE.Clock();
    
    	// HELPER
      
      const gridHelper = new THREE.PolarGridHelper( 8, 16 );
      scene.add( gridHelper );
    
      // LIGHT
      const ambientLight = new THREE.AmbientLight( 0xffffff, 0.2 );
      scene.add( ambientLight );
    
      const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
      directionalLight.position.set( 1, 1, - 1 );
      scene.add( directionalLight );
    
      // CONTROLS
      if(isMobile) {
        var controls = new THREE.DeviceOrientationControls(camera);
        console.log('isMobile true');
      } else {
        console.log('isMobile false');
      }
      
      // ADD MESH
      var group = new THREE.Group();
      var size = ( isMobile ? 2 : 4 );
      var starsLights = new THREE.Group();
    
      for ( let i = 0; i < textCount; i ++ ) {
        var lod = new THREE.LOD();
        // Star
        var geometry = new THREE.SphereGeometry(0.3, 16, 16);
        var material = new THREE.MeshBasicMaterial({color: 0xffffff});
        var star = new THREE.Mesh(geometry, material);
        // Text
        let sprite = new THREE.TextSprite({
          textSize: size,
          redrawInterval: 250,
          texture: {
            text: 'TEST TEST TEST',
            fontFamily: 'Arial, Helvetica, sans-serif',
          },
          material: {
            color: 'white',
          },
        });
        // Star Light
        var velX = (Math.random() + 0.1) * 0.1 * (Math.random()<0.5?-1:1);
        var velY = (Math.random() + 0.1) * 0.1 * (Math.random()<0.5?-1:1);
        star.vel = new THREE.Vector2(velX, velY);
        var starLight = new THREE.PointLight(0x000000, 0.8, 3);
        starLight.position.copy(star.position);
        starLight.position.y += 0.5;
        starsLights.add(starLight);
        // Add
        lod.addLevel(sprite, 1);
        lod.addLevel(star, 200);
        lod.position.x = Math.random() * 180-100;
        lod.position.y = Math.random() * 180-100;
        lod.position.z = Math.random() * 1000-40;
        group.add(lod);
    //    group.add(starsLights);
      }
      scene.add(group);
      scene.add(starLight);
    
      // Renderer
      renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
      renderer.setPixelRatio( window.devicePixelRatio );
      renderer.setSize( window.innerWidth, window.innerHeight );
      document.getElementById("universe").appendChild(renderer.domElement);
    
      // Event handler
      window.addEventListener( 'resize', onWindowResize, false );
      document.addEventListener('mousemove', onMouseMove, false);
      document.addEventListener('mousewheel', onMouseWheel, false);
      document.addEventListener('contextmenu', onContextMenu, false);
    
    
      function animate() {
        target.x = ( 1 - mouse.x ) * 0.002;
        target.y = ( 1 - mouse.y ) * 0.002;
        camera.rotation.x += 0.05 * ( target.y - camera.rotation.x );
        camera.rotation.y += 0.05 * ( target.x - camera.rotation.y );
    
        if(isMobile) {
          controls.update();
        }
        // Object change related to distance
        group.children.forEach(function(child) {
          child.update(camera);
          var distance = camera.position.distanceTo(child.position);
          var opacity = -1 / 400 * distance + 1;
          if (opacity < 0) {
            opacity = 0;
          }
          child.getObjectForDistance(distance).material.opacity = opacity;
        })
        // Render
        requestAnimationFrame( animate );
        render(scene, camera);
      }
      
      animate();
    }
    
    function onWindowResize() {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize( window.innerWidth, window.innerHeight );
    }
    
    function onMouseWheel(event) {
      if(camera.position.z > 100) {
        event.preventDefault();
        camera.position.z -= event.deltaY * 0.2;
      } else {
    
      }
    }
    
    function render() {
      const delta = clock.getDelta();
      if ( mixer !== undefined ) mixer.update( delta );
      renderer.render( scene, camera );
    }
    
    function onTransitionEnd( event ) {
      console.log("Loading Complete");
      event.target.remove();
    }
    
    // Exist functions
    function checkMobile() {
      var UserAgent = navigator.userAgent;
    
      if (UserAgent.match(/iPhone|iPod|Android|Windows CE|BlackBerry|Symbian|Windows Phone|webOS|Opera Mini|Opera Mobi|POLARIS|IEMobile|lgtelecom|nokia|SonyEricsson/i) != null || UserAgent.match(/LG|SAMSUNG|Samsung/) != null) {
          isMobile = true;
      } else {
          isMobile = false;
      }
    }
    
    function onMouseMove(event) {
      mouse.x = ( (event.clientX/2) - (windowHalf.x/2) );
      mouse.y = ( (event.clientY/2) - (windowHalf.y/2) );
      clicked.x = ( event.clientX / window.innerWidth ) * 2 - 1;
      clicked.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    }
    
    function onResize(event) {
      const width = window.innerWidth;
      const height = window.innerHeight;
      
      windowHalf.set( width / 2, height / 2 );
    	
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
      renderer.setSize( width, height );
    }
    
    function onContextMenu(event) {
      event.preventDefault();
    }
    
    function topFunction() {
      document.body.scrollTop = 0;
      document.documentElement.scrollTop = 0;
    }
    canvas {
      width: 100%;
      height: 100%;
      
    /*  background: #11e8bb;  Old browsers */
    /*  background: -moz-linear-gradient(top,  #11e8bb 0%, #8200c9 100%);  FF3.6-15 */
    /*  background: -webkit-linear-gradient(top,  #11e8bb 0%,#8200c9 100%);  Chrome10-25,Safari5.1-6 */
    /*  background: linear-gradient(to bottom,  #11e8bb 0%,#8200c9 100%);  W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
      background: radial-gradient(circle, #ed1654, #f61e6c, #f76098);
      filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#11e8bb', endColorstr='#8200c9',GradientType=0 ); /* IE6-9 */
    }
    
    body {
      margin: 0;
    }
    canvas {
      width: 100%;
      height: 100%;
    }
    #threejs {
      position: absolute;
      overflow: hidden;
      width: 100%;
      height: 100%;
    }
    header {
      position: fixed;
      z-index: 9999;
      background-color: white;
      width: 100%;
      top: 0;
      display: flex;
      align-items: center;
      height: 50px;
    }
    /* Header Left */
    .header-left {
      display: flex;
      justify-content: center;
      flex: 1;
    }
    .header-left img {
      width: 80px;
      height: 20px;
    }
    /* Header Right */
    .header-right {
      flex: 1;
      padding-left: 200px;
    }
    .header-right a {
      text-decoration: none;
      color: black;
      font-weight: 600;
    }
    .header-right a:nth-child(2) {
      padding-left: 50px;
      padding-right: 50px;
    }
    /* Main Company */
    .down-btn {
      display: flex;
      position: absolute;
      justify-content: center;
      align-items: center;
      bottom: 0;
      color: white;
      left: 50%;
      font-size: 2rem;
      cursor: pointer;
    }
    .down-btn a {
      text-decoration: none;
      color: white;
      padding-bottom: 20px;
    }
    /* Section */
    section {
      background-color: aliceblue;
      height: 100%;
    }
    <html>
    <head>
      <link rel="stylesheet" type="text/css" href="style.css">
    <!--  <script src="three.js"></script>-->
      <script src="https://cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script> 
      <script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
      <script src="https://unpkg.com/three.texttexture"></script>
      <script src="https://unpkg.com/three.textsprite"></script>
      <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
    </head>
    <body>
      <header>
        <div class="header-left">
          <a href="#">MAIN</a>
        </div>
        <div class="header-right">
          <a href="#">ABOUT</a>
          <a href="#">PRODUCT</a>
          <a href="#">CONTACT</a>
        </div>
      </header>
      <section id="universe"></section>
      <script src="src.js"></script>
      <section id="section">
        SECTION
      </section>
    </body>
    </html>
    1 回复  |  直到 6 年前
        1
  •  0
  •   Mugen87    6 年前

    THREE.LOD

    下面的fiddle演示了这种方法(我确信实现这种更优雅的方法是可能的,但它至少是一个起点^^): https://jsfiddle.net/f2Lommf5/14585/

     const lod = new LOD();
     lod.threshold = 250;