three打造一个三维小鱼跟随鼠标游动效果代码
代码语言:html
所属分类:三维
代码描述:three打造一个三维小鱼跟随鼠标游动效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> @import url(https://fonts.googleapis.com/css?family=Open+Sans:800); #world{ background: linear-gradient(#8ee4ae, #e9eba3); position:absolute; width:100%; height:100%; overflow:hidden; } #instructions{ position:absolute; width:100%; top:50%; margin: auto; margin-top:80px; font-family:'Open Sans', sans-serif; color:#71b583; font-size:1.2em; text-transform: uppercase; text-align : center; } #credits{ position:absolute; width:100%; margin: auto; bottom:0; margin-bottom:20px; font-family:'Open Sans', sans-serif; color:#71b583; font-size:0.7em; text-transform: uppercase; text-align : center; } #credits a { color:#71b583; } </style> </head> <body > <div id="world"></div> <div id="instructions">Move your mouse <br/>to change speed and direction</div> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/stats-min.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.72.js"></script> <script> //THREEJS RELATED VARIABLES var scene, camera, fieldOfView, aspectRatio, nearPlane, farPlane, shadowLight, light, renderer, container; //SCREEN VARIABLES var HEIGHT, WIDTH, windowHalfX, windowHalfY, xLimit, yLimit; // FISH BODY PARTS var fish, bodyFish, tailFish, topFish, rightIris, leftIris, rightEye, leftEye, lipsFish, tooth1, tooth2, tooth3, tooth4, tooth5; // FISH SPEED // the colors are splitted into rgb values to facilitate the transition of the color var fishFastColor = { r: 255, g: 0, b: 224 }; // pastel blue fishSlowColor = { r: 0, g: 207, b: 255 }; // purple angleFin = 0; // angle used to move the fishtail // PARTICLES COLORS // array used to store a color scheme to randomly tint the particles var colors = ['#dff69e', '#00ceff', '#002bca', '#ff00e0', '#3f159f', '#71b583', '#00a2ff']; // PARTICLES // as the particles are recycled, I use 2 arrays to store them // flyingParticles used to update the flying particles and waitingParticles used to store the "unused" particles until we need them; var flyingParticles = []; waitingParticles = []; // maximum z position for a particle maxParticlesZ = 600; // SPEED var speed = { x: 0, y: 0 }; var smoothing = 10; // MISC var mousePos = { x: 0, y: 0 }; var stats; var halfPI = Math.PI / 2; function init() { // To work with THREEJS, you need a scene, a camera, and a renderer // create the scene; scene = new THREE.Scene(); // create the camera HEIGHT = window.innerHeight; WIDTH = window.innerWidth; aspectRatio = WIDTH / HEIGHT; fieldOfView = 60; nearPlane = 1; // the camera won't "see" any object placed in front of this plane farPlane = 2000; // the camera wont't see any object placed further than this plane camera = new THREE.PerspectiveCamera( fieldOfView, aspectRatio, nearPlane, farPlane); camera.position.z = 1000; //create the renderer renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); renderer.setSize(WIDTH, HEIGHT); container = document.getElementById('world'); container.appendChild(renderer.domElement); /* As I will recycle the particles, I need to know the left and right limits they can fly without disappearing from the camera field of view. As soon as a particle is out of the camera view, I can recycle it : remove it from the flyingParticles array and push it back in the waitingParticles array. I guess I can do that by raycasting each particle each frame, but I think this will be too heavy. Instead I prefer to precalculate the x coordinate from which a particle is not visible anymore. But this depends on the z position of the particle. Here I decided to use the furthest possible z position for a particle, to be sure that all the particles won't be recycled before they are out of the camera view. But this could be much more precise, by precalculating the x limit for each particle depending on its z position and store it in the particle when it is "fired". But today, I'll keep it simple :) !!!!!! I'm really not sure this is the best way to do it. If you find a better solution, please tell me */ // convert the field of view to radians var ang = fieldOfView / 2 * Math.PI / 180; // calculate the max y position seen by the camera related to the maxParticlesZ position, I start by calculating the y limit because fielOfView is a vertical field of view. I then calculate the x Limit yLimit = (camera.position.z + maxParticlesZ) * Math.tan(ang); // this is a formula I found, don't ask me why it works, it just does :) // Calculate the max x position seen by the camera related to the y Limit position xLimit = yLimit * camera.aspect; // precalculate the center of the screen, used to update the speed depending on the mouse position windowHalfX = WIDTH / 2; windowHalfY = HEIGHT / 2; // handling resize and mouse move events window.addEventListener('resize', onWindowResize, false); document.addEventListener('mousemove', handleMouseMove, false); // let's make it work on mobile too document.addEventListener('touchstart', handleTouchStart, false); document.addEventListener('touchend', handleTouchEnd, false); document.addEventListener('touchmove', handleTouchMove, false); } function onWindowResize() { HEIGHT = window.innerHeight; WIDTH = window.innerWidth; windowHalfX = WIDTH / 2; windowHalfY = HEIGHT / 2; renderer.setSize(WIDTH, HEIGHT); camera.aspect = WIDTH / HEIGHT; camera.updateProjectionMatrix(); // force the camera to update its aspect ratio // recalculate the limits var ang = fieldOfView / 2 * Math.PI / 180; yLimit = (camera.position.z + maxPartcilesZ) * Math.tan(ang); xLimit = yLimit * camera.aspect; } function handleMouseMove(event) { mousePos = { x: event.clientX, y: event.clientY }; updateSpeed(); } function handleTouchStart(event) { if (event.touches.length > 1) { event.preventDefault(); mousePos = { x: event.touches[0].pageX, y: event.touches[0].pageY }; updateSpeed(); } } function handleTouchEnd(event) { mousePos = { x: windowHalfX, y: windowHalfY }; updateSpeed(); } function handleTouchMove(event) { if (event.touches.length == 1) { event.preventDefault(); mousePos = { x: event.touches[0].pageX, y: event.touches[0].pageY }; updateSpeed(); } } function updateSpeed() { speed.x = mousePos.x / WIDTH * 100; speed.y = (mousePos.y - windowHalfY) / 10; } function loop() { // Update fish position, rotation, scale... depending on the mouse position // To make a smooth update of each value I use this formula : // currentValue += (targetValue - currentValue) / smoothing // make the fish swing according to the mouse direction fish.rotation.z += (-speed.y / 50 - fish.rotation.z) / smoothing; fish.rotation.x += (-speed.y / 50 - fish.rotation.x) / smoothing; fish.rotation.y += (-speed.y / 50 - fish.rotation.y) / smoothing; // make the fish move according to the mouse direction fish.position.x += (mousePos.x - windowHalfX - fish.position.x) / smoothing; fish.position.y += (-speed.y * 10 - fish.position.y) / smoothing; // make the eyes follow the mouse direction rightEye.rotation.z = leftEye.rotation.z = -speed.y / 150; rightIris.position.x = leftIris.position.y = -10 - speed.y / 2; // make it look angry when the speed increases by narrowing the eyes rightEye.scale.set(1, 1 - speed.x / 150, 1); leftEye.scale.set(1, 1 - speed.x / 150, 1); // in order to optimize, I precalculate a smaller speed values depending on speed.x // these variables will be used to update the wagging of the tail, the color of the fish and the scale of the fish var s2 = speed.x / 100; // used for the wagging speed and color var s3 = speed.x / 300; // used for the scale // I use an angle that I increment, and then use its cosine and sine to make the tail wag in a cyclic movement. The speed of the wagging depends on the global speed angleFin += s2; // for a better optimization, precalculate sine and cosines var backTailCycle = Math.cos(angleFin); var sideFinsCycle = Math.sin(angleFin / 5); tailFish.rotation.y.........完整代码请登录后点击上方下载按钮下载查看
网友评论0