当前位置:网站首页>Three. JS introductory learning notes 13: animation learning

Three. JS introductory learning notes 13: animation learning

2022-07-07 15:49:00 Jiang Duoduo_ Mostly Harmless

Reference learning
https://www.ituring.com.cn/book/miniarticle/53322
Playback settings ( Pause 、 Period of time 、 Point in time )
https://blog.csdn.net/u014291990/article/details/103350524
Zoom in and out
https://blog.csdn.net/liu4071325/article/details/52302053

Animation principle

The essence of animation is to use the visual persistence of human eyes , Quickly change the picture , Thus producing the illusion of biological movement .Three.js The animation is realized by redrawing many times per second .

FPS yes (Frames Per Second) It refers to the number of times the picture is redrawn per second .FPS The bigger it is , The smoother the animation effect ,FPS Less than 20 There will be picture stagnation . When FPS achieve 60, If you increase the number of frames, the human eye will not feel the change obviously , Of the movie FPS The standard for the 24,Three.js Animation , commonly FPS stay 30-60

setInterval Method

Customizable fps

setInterval(func, msec)

func Every time msec Function executed in milliseconds , If you will func Defined as a function of redrawing the picture , Can achieve animation effect .setInterval The function returns a id, If you need to stop redrawing , Need to use clearInterval Method , And pass in the id

Need to be in init Call in function

id = setInterval(draw, 20);
// Changes in each frame ( After all , If every frame is the same , Even if redrawn many times , There will still be no animation effect ), Here we let the box in the scene wrap around y Shaft rotation 
function draw() {
    
    mesh.rotation.y = (mesh.rotation.y + 0.01) % (Math.PI * 2);
    renderer.render(scene, camera);
}

Every time 20 It will be called once in milliseconds draw function , Change the rotation value of the box , And then redraw it . The result is FPS by 50 Rotating box .
We are HTML Add a button to , Press to stop animation :

<button id="stopBtn" onclick="stop()">Stop</button>
function stop() {
    
    if (id !== null) {
    
        clearInterval(id);
        id = null;
    }
}

Example 1

1. Plug in translation and rotation
2. Click to change color
3. Auto rotate
4. Click the stop button to stop the rotation
Button call draw Function time :
Click the start button , Every click , Change once , Rotation increases 0.01
Button call start Function time :

Animation core code

<body>
 <script src="js/three.js"></script>
 <script>
<button id="stopBtn" onclick="stop()">stop</button>
<button id="startBtn" onclick="start()">start</button>
function init() {
    
  // init scene
  // Omit 
  // init camera
  // Omit 
  //light
  // Omit 

 // Load two by C4D use blender Turn into fbx Again into json Model files for 
// use mesh1 = obj1,mesh2=obj2, You can control the animation of multiple models 
 var loaderC1 = new THREE.ObjectLoader();
        loaderC1.load("json/cfbx3.json", function(obj1) {
    
        obj1.traverse(function(child) {
    
            if (child instanceof THREE.Mesh) {
    
                child.material.side = THREE.DoubleSide;
        }
    });
        obj1.scale.multiplyScalar(3);//3 Multiple size  
        mesh1 = obj1; 
        obj1.position.set(0,1.3,8.5)
        obj1.rotation.z = -Math.PI;// rotate 180 degree 
        scene.add(obj1);
    }); 
    
    
      var loaderC2 = new THREE.ObjectLoader();
        loaderC2.load("json/cfbx3.json", function(obj2) {
    
        obj2.traverse(function(child) {
    
            if (child instanceof THREE.Mesh) {
    
                child.material.side = THREE.DoubleSide;
        }
    });
        obj2.scale.multiplyScalar(3);//3 Multiple size  
        mesh2 = obj2; 
        obj2.position.set(0,1.3,6)
        obj2.rotation.z = -Math.PI;// rotate 180 degree 
        scene.add(obj2);
    }); 
    // Animation redrawing   Every time 20 One call in milliseconds draw function , I understand that is 20 Redraw once in milliseconds  
       id = setInterval(draw, 20);
}//init end
   // Animation 
  
        function draw() {
    
                // Two models rotate 
                mesh1.rotation.y = (mesh1.rotation.y + 0.01) % (Math.PI * 2);
                mesh2.rotation.y = (mesh1.rotation.y + 0.01) % (Math.PI * 2);
                renderer.render(scene, camera);
            }
       
        // Stop button 
         function stop() {
    
                if (id !== null) {
    
                    clearInterval(id);
                    id = null;
                }
            }  
        // Restart button 
        function start() {
    
                mesh1.rotation.y = (mesh1.rotation.y + 0.01) % (Math.PI * 2);
                mesh2.rotation.y = (mesh1.rotation.y + 0.01) % (Math.PI * 2);
                renderer.render(scene, camera);
                id = setInterval(draw, 20);
            }  


</script>
</body>

 Insert picture description here

Complete code

rotationDraw and otherDraw The function executes only once each time the button is pressed , To execute multiple times, you need to call again setInterval(otherDraw, 20), Let it redraw every millisecond 20 Time , So put it in start Function can realize the effect of playing again after pause

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>3D</title>
        <meta charset="utf-8">
        <!--  The adaptive  -->
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
* {
    
    margin: 0;
    padding: 0;
}
    
</style>
    </head>
<body>
<button class="startBtn" onclick="start1()">start1</button>
<button class="startBtn" onclick="otherDraw()">start2</button>
    <script src="js/three.js"></script>
    <script type="text/javascript" src="js/OrbitControls.js"></script>
    <script>
        	var stats, light, mesh ,group;
			var camera, scene, raycaster, renderer;

			var mouse = new THREE.Vector2(), INTERSECTED;// Intersecting 
			var radius = 100, theta = 0;
        
        init();
        
        
        function init() {
    
            
            
             // init scene
            scene = new THREE.Scene();
			scene.background = new THREE.Color( 0xf0f0f0 );
            
             // init camera
           camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
           camera.position.set(15,15,15);
// camera.lookAt(new THREE.Vector3(0,0,0));
           camera.lookAt( scene.position );
           scene.add(camera);
            

             //light
          	var light = new THREE.DirectionalLight( 0xffffff, 1 );
				light.position.set( 1, 1, 1 ).normalize();// Vector attribute vector is converted to unit vector , Set the direction to be the same as the original vector , The length is 1
                light.intensity=1.5;// Strength 
				scene.add( light );

     // Cache Library 

    var loaderC1 = new THREE.ObjectLoader();
        loaderC1.load("json/cfbx3.json", function(obj1) {
    
        obj1.traverse(function(child) {
    
            if (child instanceof THREE.Mesh) {
    
                child.material.side = THREE.DoubleSide;
          
        }
    });
        obj1.scale.multiplyScalar(3);//3 Multiple size  
        mesh1 = obj1; 
        obj1.position.set(0,1.3,8.5)
        obj1.rotation.z = -Math.PI;// rotate 180 degree 
        scene.add(obj1);
    }); 
    
    
      var loaderC2 = new THREE.ObjectLoader();
        loaderC2.load("json/cfbx3.json", function(obj2) {
    
        obj2.traverse(function(child) {
    
            if (child instanceof THREE.Mesh) {
    
                child.material.side = THREE.DoubleSide;
          
        }
    });
        obj2.scale.multiplyScalar(3);//3 Multiple size  
        mesh2 = obj2; 
        obj2.position.set(0,1.3,6)
        obj2.rotation.z = -Math.PI;// rotate 180 degree 
        scene.add(obj2);
    }); 

            // ray 
            raycaster = new THREE.Raycaster();
          /* var raycaster = new THREE.Raycaster(); var mouseVector = new THREE.Vector3();*/
            
            
            //renderer
				renderer = new THREE.WebGLRenderer();
				renderer.setSize( window.innerWidth, window.innerHeight );
				document.getElementsByTagName("body")[0].appendChild(renderer.domElement);
            
           // monitor 
           document.addEventListener( "mousedown", onDocumentMouseDown, false );
           
           // Window changes 
           window.addEventListener( "resize", onWindowResize, false );
            
            
            // plug-in unit 
    var controls = new THREE.OrbitControls( camera, renderer.domElement );//camera and render The variable of is consistent with the variable set by the camera and renderer 

        //  If you use animate When the method is used , Delete this function 
        //controls.addEventListener( 'change', render );
        //  Make the animation rotate or damp when cycling   Does the meaning have inertia 
        controls.enableDamping = true;
        // Dynamic damping coefficient   It's the mouse drag rotation sensitivity 
        //controls.dampingFactor = 0.25;
        // Can I zoom 
        controls.enableZoom = true;
        // Whether to rotate automatically 
        controls.autoRotate = true;
        // Set the maximum distance from the camera to the origin 
        controls.minDistance  = 1;
        // Set the maximum distance from the camera to the origin 
        controls.maxDistance  = 200;
        // Whether to turn on right-click drag and drop 
        controls.enablePan = true; 
            

       // Animation redrawing  
       id = setInterval(rotationDraw, 20);
            
      
        }//function end 
        
        // Window changes 
        function onWindowResize() {
    

				camera.aspect = window.innerWidth / window.innerHeight;
// camera.updateProjectionMatrix();

				renderer.setSize( window.innerWidth, window.innerHeight );

			}
        
        // Coordinate transformation 
       function onDocumentMouseDown( event ) {
    // Mouse event starts 

				event.preventDefault();
               
				mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
				mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
           
           
                 //  Update the ray with camera and mouse position 
	     raycaster.setFromCamera( mouse, camera );

	      //  Calculate the focus of objects and rays 
	     var intersects = raycaster.intersectObjects( scene.children ,true);// Rays pass through objects , Automatically sort from near to far 


            
            // The second kind 
        if ( intersects.length > 0 ) {
    // When there are objects 
         

					if ( INTERSECTED != intersects[ 0 ].object ) {
    // The last selection is not equal to the current selection , It's time to replace ,intersects[ 0 ] Is the current selection   At the front , It is automatically sorted 
                 

						if ( INTERSECTED ) 
                            if( INTERSECTED.material .length==undefined){
    
                            INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );// The last selected material should be replaced with the original material 
                            }

						INTERSECTED = intersects[ 0 ].object;
                       if( INTERSECTED.material .length==undefined){
    
						INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();// Save the current materials 
						INTERSECTED.material.emissive.setHex( 0xff0000 );// Color change 
                    }

					}

				} else {
    // When selecting the blank space 
//
					if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );

					INTERSECTED = null;

				}

			}//mousedown The mouse event ends 

        // Animation 
  
    function rotationDraw() {
    
                mesh1.rotation.y = (mesh1.rotation.y + 0.01) % (Math.PI * 2);
                mesh2.rotation.y = (mesh1.rotation.y + 0.01) % (Math.PI * 2);
                renderer.render(scene, camera);
            }
        
        function otherDraw() {
    
                mesh1.position.y = mesh1.position.y + 1;
                mesh2.scale.x = mesh2.scale.x * 2;
                mesh2.scale.y = mesh2.scale.y * 2;
                mesh2.scale.z = mesh2.scale.z * 2;
// mesh2.scale.multiplyScalar = mesh2.scale.multiplyScalar(2);
                renderer.render(scene, camera);
            }
       
        
         function stop() {
    
                if (id !== null) {
    
                    clearInterval(id);
                    id = null;
                }
            }  
          
        function start1() {
    
                id = setInterval(rotationDraw, 20);
            }  
        
         function start2() {
    
                id = setInterval(otherDraw, 20);
            }  
    </script>

</body>
</html>

requestAnimationFrame Method

This method has no effect , I don't know why

init Function

 id = requestAnimationFrame(draw);

Cancel animation

function stop() {
    
    if (id !== null) {
    
        cancelAnimationFrame(id);
        id = null;
    }
}

and setInterval The difference is , because requestAnimationFrame Only one frame is requested , therefore , In addition to the init Function needs to call , In the function called by it, you need to call again requestAnimationFrame:

function draw() {
    
    mesh.rotation.y = (mesh.rotation.y + 0.01) % (Math.PI * 2);
    renderer.render(scene, camera);
    id = requestAnimationFrame(draw);
}

To support these browsers , We'd better call before , First judge whether it is defined requestAnimationFrame And the above functions :

var requestAnimationFrame = window.requestAnimationFrame 
        || window.mozRequestAnimationFrame
        || window.webkitRequestAnimationFrame
        || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;

Load the model and control the animation playback

https://blog.csdn.net/kfyzjd2008/article/details/87000788

原网站

版权声明
本文为[Jiang Duoduo_ Mostly Harmless ]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202130610087155.html