Javascript 尝试通过Three.js模拟3D效果

Javascript 尝试通过Three.js模拟3D效果,javascript,animation,three.js,3d,geometry,Javascript,Animation,Three.js,3d,Geometry,我正试图实现类似于这个惊人效果的东西: /*-------------------- Setup --------------------*/ console.clear(); const canvas = document.querySelector('#bubble'); //wobble let mouseDown = false; let howMuch = 0; let howMuchLimit = 0.25; //ripple let rippleAmount = 0; let

我正试图实现类似于这个惊人效果的东西:

/*--------------------
Setup
--------------------*/
console.clear();
const canvas = document.querySelector('#bubble');

//wobble
let mouseDown = false;
let howMuch = 0;
let howMuchLimit = 0.25;

//ripple
let rippleAmount = 0;
let rippleRatio = 5;
let step = 0;
let sphereVerticesArray = [];
let sphereVerticesNormArray = [];

//raycaster
let raycaster;
let INTERSECTED = null;

let width = canvas.offsetWidth,
    height = canvas.offsetHeight;
const renderer = new THREE.WebGLRenderer({
  canvas: canvas,
  antialias: true,
  alpha: true
});
const scene = new THREE.Scene();

const setup = () => {
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize(width, height);
  renderer.setClearColor(0xebebeb, 0);
  renderer.shadowMap.enabled = true;
  renderer.shadowMapSoft = true;

  scene.fog = new THREE.Fog(0x000000, 10, 950);

  const aspectRatio = width / height;
  const fieldOfView = 100;
  const nearPlane = 0.1;
  const farPlane = 10000;
  camera = new THREE.PerspectiveCamera(
    fieldOfView,
    aspectRatio,
    nearPlane,
    farPlane
  );
  
  raycaster = new THREE.Raycaster();
   
  camera.position.x = 0;
  camera.position.y = 0;
  camera.position.z = 300;
}
setup();


/*--------------------
Lights
--------------------*/
let hemispshereLight, shadowLight, light2;
const createLights = () => {
    hemisphereLight = new THREE.HemisphereLight(0xffffff,0x000000, .5)
  
    shadowLight = new THREE.DirectionalLight(0x666666, .4);
    shadowLight.position.set(0, 450, 350);
    shadowLight.castShadow = true;

    shadowLight.shadow.camera.left = -650;
    shadowLight.shadow.camera.right = 650;
    shadowLight.shadow.camera.top = 650;
    shadowLight.shadow.camera.bottom = -650;
    shadowLight.shadow.camera.near = 1;
    shadowLight.shadow.camera.far = 1000;

    shadowLight.shadow.mapSize.width = 4096;
    shadowLight.shadow.mapSize.height = 4096;
  
  light2 = new THREE.DirectionalLight(0x666666, .25);
    light2.position.set(-600, 350, 350);
  
  light3 = new THREE.DirectionalLight(0x666666, .15);
    light3.position.set(0, -250, 300);

    scene.add(hemisphereLight);  
    scene.add(shadowLight);
  scene.add(light2);
  scene.add(light3);
}
createLights();


/*--------------------
Bubble
--------------------*/
const vertex = width > 575 ? 80 : 40;
const bubbleGeometry = new THREE.SphereGeometry( 150, vertex, vertex );

let bubble;
const createBubble = () => {
  for(let i = 0; i < bubbleGeometry.vertices.length; i++) {
    let vector = bubbleGeometry.vertices[i];
    vector.original = vector.clone();  
  }
  
  const bubbleMaterial = new THREE.MeshStandardMaterial({
    emissive: 0x91176b,
    emissiveIntensity: 0.85,
    roughness: 0.55,
    metalness: 0.51,
    side: THREE.FrontSide,
  });
  
  // save points for later calculation
  for (var i = 0; i < bubbleGeometry.vertices.length; i += 1) {
    var vertex = bubbleGeometry.vertices[i];
    var vec = new THREE.Vector3(vertex.x, vertex.y, vertex.z);
    sphereVerticesArray.push(vec);
    var mag = vec.x * vec.x + vec.y * vec.y + vec.z * vec.z;
    mag = Math.sqrt(mag);
    var norm = new THREE.Vector3(vertex.x / mag, vertex.y / mag, vertex.z / mag);
    sphereVerticesNormArray.push(norm);
  }
  
  bubble = new THREE.Mesh(bubbleGeometry, bubbleMaterial);
  bubble.castShadow = true;
  bubble.receiveShadow = false;
  bubble.rotation.y = -90;
  
  scene.add(bubble);
}
createBubble();


/*--------------------
Plane
--------------------*/
const createPlane = () => {
  const planeGeometry = new THREE.PlaneBufferGeometry( 2000, 2000 );
  const planeMaterial = new THREE.ShadowMaterial({
    opacity: 0.15
  });
  const plane = new THREE.Mesh( planeGeometry, planeMaterial );
  plane.position.y = -150;
  plane.position.x = 0;
  plane.position.z = 0;
  plane.rotation.x = Math.PI / 180 * -90;
  plane.receiveShadow = true;
  scene.add(plane);
}
createPlane();


/*--------------------
Map
--------------------*/
const map = (num, in_min, in_max, out_min, out_max) => {
  return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


/*--------------------
Distance
--------------------*/
const distance = (a, b) => {
  const dx = a.x - b.x;
  const dy = a.y - b.y;
  const d = Math.sqrt( dx * dx + dy * dy );
  return d;
}


/*--------------------
Mouse
--------------------*/
let mouse = new THREE.Vector2(0, 0);
const onMouseMove = (e) => {
  TweenMax.to(mouse, 0.8, {
    x : ( e.clientX / window.innerWidth ) * 2 - 1,
    y: - ( e.clientY / window.innerHeight ) * 2 + 1,
    ease: Power2.easeOut
  });
  
  raycaster.setFromCamera( mouse, camera );
  let intersects = raycaster.intersectObjects( scene.children );

  try{
    if ( intersects.length > 0 ) {
      if ( INTERSECTED != intersects[ 0 ].object ) {

        if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );

        INTERSECTED = intersects[ 0 ].object;
        INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
        INTERSECTED.material.emissive.setHex( 0x000000 );
        document.body.style.cursor = 'pointer';
      }
    } else {
      if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
      INTERSECTED = null;
      document.body.style.cursor = 'auto';
    }
  }catch(e){
    
  }
};
['mousemove', 'touchmove'].forEach(event => {
  window.addEventListener(event, onMouseMove);  
});


/*--------------------
Spring
--------------------*/
let spring = {
  scale: 1
};
const clicking = {
  down: () => {
    mouseDown = true;
  },
  up: () => {
    mouseDown = false;
  }
};
['mousedown', 'touchstart'].forEach(event => {
  window.addEventListener(event, clicking.down);
});
['mouseup', 'touchend'].forEach(event => {
  window.addEventListener(event, clicking.up);
});


/*--------------------
Resize
--------------------*/
const onResize = () => {
  canvas.style.width = '';
  canvas.style.height = '';
  width = canvas.offsetWidth;
  height = canvas.offsetHeight;
  camera.aspect = width / height;
  camera.updateProjectionMatrix(); 
  maxDist = distance(mouse, {x: width / 2, y: height / 2});
  renderer.setSize(width, height);
}
let resizeTm;
window.addEventListener('resize', function(){
  resizeTm = clearTimeout(resizeTm);
  resizeTm = setTimeout(onResize, 200);
});


/*--------------------
Noise
--------------------*/
let dist = new THREE.Vector2(0, 0);
let maxDist = distance(mouse, {x: width / 2, y: height / 2});
const updateVertices = (time) => {
  dist = distance(mouse, {x: width / 2, y: height / 2});
  dist /= maxDist;
  dist = map(dist, 1, 0, 0, 1);
  for(let i = 0; i < bubbleGeometry.vertices.length; i++) {
    let vector = bubbleGeometry.vertices[i];
    vector.copy(vector.original);
    let perlin = noise.simplex3(
      (vector.x * 0.006) + (time * 0.0005),
      (vector.y * 0.006) + (time * 0.0005),
      (vector.z * 0.006)
    );
    
    let ratio = ((perlin * 0.3 * (howMuch + 0.1)) + 0.9);
    vector.multiplyScalar(ratio);
  }
  bubbleGeometry.verticesNeedUpdate = true;
}

/*--------------------
Animate
--------------------*/
const render = (a) => {
  step +=1;
  requestAnimationFrame(render);
  
  //bubble.scale.set(spring.scale, spring.scale, spring.scale);
  updateVertices(a);
  renderer.clear();
  renderer.render(scene, camera);
  
  //Activate on mouse down
  if(mouseDown && howMuch < howMuchLimit)
    howMuch += 0.01;
  else if (howMuch > 0)
    howMuch -= 0.01;
  
  if(INTERSECTED){
    if(rippleAmount < 10)
      rippleAmount += 0.05;
  }else if(rippleAmount > 0)
      rippleAmount -= 0.05;
  
  doRipple();

}
requestAnimationFrame(render);
renderer.render(scene, camera);

/*--------------------
Helpers
--------------------*/

function fbm(p) {
  var result = noise.simplex3(p._x, p._y, p._z);
  return result;
}

function addPoint(arr) {
  var r = new Point(0, 0, 0);
  var len = arr.length;
  for (var i = 0; i < len; i += 1) {
    r._x += arr[i]._x;
    r._y += arr[i]._y;
    r._z += arr[i]._z;
  }

  return r;
}

function Point(_x=0, _y=0, _z=0) {
  this._x = _x;
  this._y = _y;
  this._z = _z;
}

function ripple(p) {
  var q = new Point(fbm(addPoint([p, new Point(0, 0, 0)])), 
                    fbm(addPoint([p, new Point(0, 1, 0)])),
                    fbm(addPoint([p, new Point(0, 0, 1)])));

  return fbm(addPoint([p, new Point(0.5 * q._x, 0.5 * q._y, 0.5 * q._z)]));
}

function doRipple(){
  //ripple
  for (var i = 0; i < bubbleGeometry.vertices.length; i += 1) {
    var vertex = bubbleGeometry.vertices[i];

    // var value = pn.noise((vertex.x + step)/ 10, vertex.y / 10, vertex.z / 10);

    var value = ripple(new Point((vertex.x + step) / 100.0), vertex.y / 100.0, vertex.z / 100.0);

    vertex.x = sphereVerticesArray[i].x + sphereVerticesNormArray[i].x * value * rippleAmount;
    vertex.y = sphereVerticesArray[i].y + sphereVerticesNormArray[i].y * value * rippleAmount;
    vertex.z = sphereVerticesArray[i].z + sphereVerticesNormArray[i].z * value * rippleAmount;
  }
  bubbleGeometry.computeFaceNormals();
  bubbleGeometry.computeVertexNormals();

  bubbleGeometry.verticesNeedUpdate = true;
  bubbleGeometry.normalsNeedUpdate = true;
}
以下是我到目前为止所做的:

/*--------------------
Setup
--------------------*/
console.clear();
const canvas = document.querySelector('#bubble');

//wobble
let mouseDown = false;
let howMuch = 0;
let howMuchLimit = 0.25;

//ripple
let rippleAmount = 0;
let rippleRatio = 5;
let step = 0;
let sphereVerticesArray = [];
let sphereVerticesNormArray = [];

//raycaster
let raycaster;
let INTERSECTED = null;

let width = canvas.offsetWidth,
    height = canvas.offsetHeight;
const renderer = new THREE.WebGLRenderer({
  canvas: canvas,
  antialias: true,
  alpha: true
});
const scene = new THREE.Scene();

const setup = () => {
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize(width, height);
  renderer.setClearColor(0xebebeb, 0);
  renderer.shadowMap.enabled = true;
  renderer.shadowMapSoft = true;

  scene.fog = new THREE.Fog(0x000000, 10, 950);

  const aspectRatio = width / height;
  const fieldOfView = 100;
  const nearPlane = 0.1;
  const farPlane = 10000;
  camera = new THREE.PerspectiveCamera(
    fieldOfView,
    aspectRatio,
    nearPlane,
    farPlane
  );
  
  raycaster = new THREE.Raycaster();
   
  camera.position.x = 0;
  camera.position.y = 0;
  camera.position.z = 300;
}
setup();


/*--------------------
Lights
--------------------*/
let hemispshereLight, shadowLight, light2;
const createLights = () => {
    hemisphereLight = new THREE.HemisphereLight(0xffffff,0x000000, .5)
  
    shadowLight = new THREE.DirectionalLight(0x666666, .4);
    shadowLight.position.set(0, 450, 350);
    shadowLight.castShadow = true;

    shadowLight.shadow.camera.left = -650;
    shadowLight.shadow.camera.right = 650;
    shadowLight.shadow.camera.top = 650;
    shadowLight.shadow.camera.bottom = -650;
    shadowLight.shadow.camera.near = 1;
    shadowLight.shadow.camera.far = 1000;

    shadowLight.shadow.mapSize.width = 4096;
    shadowLight.shadow.mapSize.height = 4096;
  
  light2 = new THREE.DirectionalLight(0x666666, .25);
    light2.position.set(-600, 350, 350);
  
  light3 = new THREE.DirectionalLight(0x666666, .15);
    light3.position.set(0, -250, 300);

    scene.add(hemisphereLight);  
    scene.add(shadowLight);
  scene.add(light2);
  scene.add(light3);
}
createLights();


/*--------------------
Bubble
--------------------*/
const vertex = width > 575 ? 80 : 40;
const bubbleGeometry = new THREE.SphereGeometry( 150, vertex, vertex );

let bubble;
const createBubble = () => {
  for(let i = 0; i < bubbleGeometry.vertices.length; i++) {
    let vector = bubbleGeometry.vertices[i];
    vector.original = vector.clone();  
  }
  
  const bubbleMaterial = new THREE.MeshStandardMaterial({
    emissive: 0x91176b,
    emissiveIntensity: 0.85,
    roughness: 0.55,
    metalness: 0.51,
    side: THREE.FrontSide,
  });
  
  // save points for later calculation
  for (var i = 0; i < bubbleGeometry.vertices.length; i += 1) {
    var vertex = bubbleGeometry.vertices[i];
    var vec = new THREE.Vector3(vertex.x, vertex.y, vertex.z);
    sphereVerticesArray.push(vec);
    var mag = vec.x * vec.x + vec.y * vec.y + vec.z * vec.z;
    mag = Math.sqrt(mag);
    var norm = new THREE.Vector3(vertex.x / mag, vertex.y / mag, vertex.z / mag);
    sphereVerticesNormArray.push(norm);
  }
  
  bubble = new THREE.Mesh(bubbleGeometry, bubbleMaterial);
  bubble.castShadow = true;
  bubble.receiveShadow = false;
  bubble.rotation.y = -90;
  
  scene.add(bubble);
}
createBubble();


/*--------------------
Plane
--------------------*/
const createPlane = () => {
  const planeGeometry = new THREE.PlaneBufferGeometry( 2000, 2000 );
  const planeMaterial = new THREE.ShadowMaterial({
    opacity: 0.15
  });
  const plane = new THREE.Mesh( planeGeometry, planeMaterial );
  plane.position.y = -150;
  plane.position.x = 0;
  plane.position.z = 0;
  plane.rotation.x = Math.PI / 180 * -90;
  plane.receiveShadow = true;
  scene.add(plane);
}
createPlane();


/*--------------------
Map
--------------------*/
const map = (num, in_min, in_max, out_min, out_max) => {
  return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


/*--------------------
Distance
--------------------*/
const distance = (a, b) => {
  const dx = a.x - b.x;
  const dy = a.y - b.y;
  const d = Math.sqrt( dx * dx + dy * dy );
  return d;
}


/*--------------------
Mouse
--------------------*/
let mouse = new THREE.Vector2(0, 0);
const onMouseMove = (e) => {
  TweenMax.to(mouse, 0.8, {
    x : ( e.clientX / window.innerWidth ) * 2 - 1,
    y: - ( e.clientY / window.innerHeight ) * 2 + 1,
    ease: Power2.easeOut
  });
  
  raycaster.setFromCamera( mouse, camera );
  let intersects = raycaster.intersectObjects( scene.children );

  try{
    if ( intersects.length > 0 ) {
      if ( INTERSECTED != intersects[ 0 ].object ) {

        if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );

        INTERSECTED = intersects[ 0 ].object;
        INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
        INTERSECTED.material.emissive.setHex( 0x000000 );
        document.body.style.cursor = 'pointer';
      }
    } else {
      if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
      INTERSECTED = null;
      document.body.style.cursor = 'auto';
    }
  }catch(e){
    
  }
};
['mousemove', 'touchmove'].forEach(event => {
  window.addEventListener(event, onMouseMove);  
});


/*--------------------
Spring
--------------------*/
let spring = {
  scale: 1
};
const clicking = {
  down: () => {
    mouseDown = true;
  },
  up: () => {
    mouseDown = false;
  }
};
['mousedown', 'touchstart'].forEach(event => {
  window.addEventListener(event, clicking.down);
});
['mouseup', 'touchend'].forEach(event => {
  window.addEventListener(event, clicking.up);
});


/*--------------------
Resize
--------------------*/
const onResize = () => {
  canvas.style.width = '';
  canvas.style.height = '';
  width = canvas.offsetWidth;
  height = canvas.offsetHeight;
  camera.aspect = width / height;
  camera.updateProjectionMatrix(); 
  maxDist = distance(mouse, {x: width / 2, y: height / 2});
  renderer.setSize(width, height);
}
let resizeTm;
window.addEventListener('resize', function(){
  resizeTm = clearTimeout(resizeTm);
  resizeTm = setTimeout(onResize, 200);
});


/*--------------------
Noise
--------------------*/
let dist = new THREE.Vector2(0, 0);
let maxDist = distance(mouse, {x: width / 2, y: height / 2});
const updateVertices = (time) => {
  dist = distance(mouse, {x: width / 2, y: height / 2});
  dist /= maxDist;
  dist = map(dist, 1, 0, 0, 1);
  for(let i = 0; i < bubbleGeometry.vertices.length; i++) {
    let vector = bubbleGeometry.vertices[i];
    vector.copy(vector.original);
    let perlin = noise.simplex3(
      (vector.x * 0.006) + (time * 0.0005),
      (vector.y * 0.006) + (time * 0.0005),
      (vector.z * 0.006)
    );
    
    let ratio = ((perlin * 0.3 * (howMuch + 0.1)) + 0.9);
    vector.multiplyScalar(ratio);
  }
  bubbleGeometry.verticesNeedUpdate = true;
}

/*--------------------
Animate
--------------------*/
const render = (a) => {
  step +=1;
  requestAnimationFrame(render);
  
  //bubble.scale.set(spring.scale, spring.scale, spring.scale);
  updateVertices(a);
  renderer.clear();
  renderer.render(scene, camera);
  
  //Activate on mouse down
  if(mouseDown && howMuch < howMuchLimit)
    howMuch += 0.01;
  else if (howMuch > 0)
    howMuch -= 0.01;
  
  if(INTERSECTED){
    if(rippleAmount < 10)
      rippleAmount += 0.05;
  }else if(rippleAmount > 0)
      rippleAmount -= 0.05;
  
  doRipple();

}
requestAnimationFrame(render);
renderer.render(scene, camera);

/*--------------------
Helpers
--------------------*/

function fbm(p) {
  var result = noise.simplex3(p._x, p._y, p._z);
  return result;
}

function addPoint(arr) {
  var r = new Point(0, 0, 0);
  var len = arr.length;
  for (var i = 0; i < len; i += 1) {
    r._x += arr[i]._x;
    r._y += arr[i]._y;
    r._z += arr[i]._z;
  }

  return r;
}

function Point(_x=0, _y=0, _z=0) {
  this._x = _x;
  this._y = _y;
  this._z = _z;
}

function ripple(p) {
  var q = new Point(fbm(addPoint([p, new Point(0, 0, 0)])), 
                    fbm(addPoint([p, new Point(0, 1, 0)])),
                    fbm(addPoint([p, new Point(0, 0, 1)])));

  return fbm(addPoint([p, new Point(0.5 * q._x, 0.5 * q._y, 0.5 * q._z)]));
}

function doRipple(){
  //ripple
  for (var i = 0; i < bubbleGeometry.vertices.length; i += 1) {
    var vertex = bubbleGeometry.vertices[i];

    // var value = pn.noise((vertex.x + step)/ 10, vertex.y / 10, vertex.z / 10);

    var value = ripple(new Point((vertex.x + step) / 100.0), vertex.y / 100.0, vertex.z / 100.0);

    vertex.x = sphereVerticesArray[i].x + sphereVerticesNormArray[i].x * value * rippleAmount;
    vertex.y = sphereVerticesArray[i].y + sphereVerticesNormArray[i].y * value * rippleAmount;
    vertex.z = sphereVerticesArray[i].z + sphereVerticesNormArray[i].z * value * rippleAmount;
  }
  bubbleGeometry.computeFaceNormals();
  bubbleGeometry.computeVertexNormals();

  bubbleGeometry.verticesNeedUpdate = true;
  bubbleGeometry.normalsNeedUpdate = true;
}
/*--------------------
安装程序
--------------------*/
console.clear();
const canvas=document.querySelector(“#bubble”);
//摇摆
让mouseDown=false;
让多少=0;
设howMuchLimit=0.25;
//涟漪
设rippleAmount=0;
让rippleRatio=5;
设阶跃=0;
设sphereVerticesArray=[];
设SphereVerticesNormalArray=[];
//雷卡斯特
让雷卡斯特;
设相交=空;
让宽度=canvas.offsetWidth,
高度=canvas.offsetHeight;
const renderer=new THREE.WebGLRenderer({
画布:画布,
反别名:是的,
阿尔法:是的
});
const scene=new THREE.scene();
常量设置=()=>{
renderer.setPixelRatio(window.devicePixelRatio);
设置大小(宽度、高度);
setClearColor(0xebebebebebeb,0);
renderer.shadowMap.enabled=true;
renderer.shadowMapSoft=true;
scene.fog=新的3.fog(0x000000,10950);
const aspectRatio=宽度/高度;
常数视野=100;
近平面常数=0.1;
常数farPlane=10000;
摄像机=新的三视角摄像机(
视野,
aspectRatio,
近平面,
远平面
);
raycaster=new-THREE.raycaster();
摄像机位置x=0;
摄像机位置y=0;
摄像机位置z=300;
}
设置();
/*--------------------
灯
--------------------*/
让光,阴影,光2;
常量createLights=()=>{
半球光=新的三个半球光(0xffffff,0x000000,.5)
阴影光=新的三方向光(0x666666,.4);
阴影灯。位置。设置(0450350);
shadowLight.castShadow=true;
shadowLight.shadow.camera.left=-650;
shadowLight.shadow.camera.right=650;
shadowLight.shadow.camera.top=650;
shadowLight.shadow.camera.bottom=-650;
shadowLight.shadow.camera.near=1;
shadowLight.shadow.camera.far=1000;
shadowLight.shadow.mapSize.width=4096;
shadowLight.shadow.mapSize.height=4096;
light2=新的三方向光(0x666666,.25);
light2.位置设置(-600350350);
light3=新的三方向灯(0x666666,.15);
light3.位置设置(0,-250,300);
场景。添加(半球灯光);
场景。添加(阴影灯);
场景。添加(light2);
场景。添加(light3);
}
createLights();
/*--------------------
泡泡
--------------------*/
常数顶点=宽度>575?80 : 40;
恒量气泡几何=新的三点球面法(150,顶点,顶点);
让泡沫;
常量CreateBuble=()=>{
对于(设i=0;i{
const planeGeometry=新的三个平面几何体(2000,2000);
const planeMaterial=新的三点阴影材质({
不透明度:0.15
});
const plane=新的三个网格(平面几何体、平面材质);
平面位置y=-150;
平面位置x=0;
平面位置z=0;
平面旋转x=Math.PI/180*-90;
plane.receiveShadow=true;
场景。添加(平面);
}
createPlane();
/*--------------------
地图
--------------------*/
常量映射=(num、in\u min、in\u max、out\u min、out\u max)=>{
返回(num-in\u min)*(out\u max-out\u min)/(in\u max-in\u min)+out\u min;
}
/*--------------------
距离
--------------------*/
常数距离=(a,b)=>{
常数dx=a.x-b.x;
常数dy=a.y-b.y;
常数d=数学sqrt(dx*dx+dy*dy);
返回d;
}
/*--------------------
老鼠
--------------------*/
让鼠标=新的三个向量2(0,0);
const onMouseMove=(e)=>{
TweenMax.至(鼠标,0.8{
x:(e.clientX/window.innerWidth)*2-1,
y:-(e.clientY/window.innerHeight)*2+1,
ease:Power2.easeOut
});
raycaster.setFromCamera(鼠标、相机);
让intersects=raycaster.intersectObjects(scene.children);
试一试{
如果(相交长度>0){
if(相交!=相交[0]。对象){
如果(相交)相交.material.emissive.setHex(相交.currentHex);
相交=相交[0]。对象;
INTERSECTED.currentHex=INTERSECTED.material.emissive.getHex();
相交。材质。发射。setHex(0x000000);
document.body.style.cursor='pointer';
}
}否则{
如果(相交)相交.material.emissive.setHex(相交.currentHex);
相交=空;
document.body.style.cursor='auto';
}
}捕获(e){
}
};
['mousemove','touchmove'].forEach(事件=>{
addEventListener(事件,onMouseMove);
});
/*--------------------
春天
--------------------*/
让弹簧={
比例:1
};
常量单击={
向下:()=>{
mouseDown=true;
},
向上:()=>{
mouseDown=false;
}
};
['mousedown','touchstart'].forEach(事件=>{
window.addEventListener(事件,单击.down);
});
['mouseup','touchend'].forEach(事件=>{
window.addEventListener(事件,单击.up);
});
/*--------------------
调整大小
--------------------*/
常量onResize=()=>{
C