three打造3D幕布垂帘撩动交互效果

代码语言:html

所属分类:三维

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">

<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Montserrat'>
<style>
body {
  margin: 0;
  height: 100%;
  font-family: 'Montserrat', sans-serif;
  background-image: radial-gradient(circle, #ffffff, #aaaaaa);
}
canvas {
  position: fixed;
  top: 0;
  bottom: 0;
  z-index: 1;
}
h1 {
  font-size: 50px;
  text-align: center;
  width: 60%;
  margin: 0 auto;
  padding-top: 10%;
}
p {
  font-size: 30px;
  text-align: center;
  width: 50%;
  margin: 1em auto 0;
}
</style>

</head>
<body translate="no">
<canvas id="canvas"></canvas>
<h1>What's behind the curtain ?</h1>
<p>This funny interactive curtain is made with ThreeJS, polylines and verlet constraints (adapted from verlet-js).</p>

<script type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/three.109.js"></script>
<script type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/chroma.min.js"></script>
<script type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/verlet-1.0.0.min.js"></script>
<script >
function App() {
  const conf = {
    el: 'canvas',
    gravity: -0.3,
    nx: 60,
    ny: 40,
    size: 1.5,
    mouseRadius: 10,
    mouseStrength: 0.4 };


  let renderer, scene, camera;
  let width, height;
  const { randFloat: rnd, randFloatSpread: rndFS } = THREE.Math;

  const mouse = new THREE.Vector2(),oldMouse = new THREE.Vector2();
  const verlet = new VerletJS(),polylines = [];
  const uCx = { value: 0 },uCy = { value: 0 };

  init();

  function init() {
    renderer = new THREE.WebGLRenderer({ canvas: document.getElementById(conf.el), antialias: true, alpha: true });
    camera = new THREE.PerspectiveCamera();

    verlet.width = 256;
    verlet.height = 256;

    updateSize();
    window.addEventListener('resize', updateSize, false);

    initScene();
    initListeners();
    animate();
  }

  function initScene() {
    scene = new THREE.Scene();
    verlet.gravity = new Vec2(0, conf.gravity);

    initCurtain();
  }

  function initCurtain() {
    const material = new THREE.ShaderMaterial({
      transparent: true,
      uniforms: {
        uCx, uCy,
        uSize: { value: conf.size / conf.nx } },

      vertexShader: `
        uniform float uCx;
        uniform float uCy;
        uniform float uSize;
        attribute vec3 color;
        attribute vec3 next;
        attribute vec3 prev;
        attribute float side;

        varying vec4 vColor;

        void main() {
          vec3 pos = vec3(position.x * uCx, position.y * uCy, 0.0);
          vec2 sprev = vec2(prev.x * uCx, prev.y * uCy);
          vec2 snext = vec2(next.x * uCx, next.y * uCy);

          vec2 tangent = normalize(snext - sprev);
          vec2 normal = vec2(-tangent.y, tangent.x);

          float dist = length(snext - sprev);
          normal *= smoothstep(0.0, 0.02, dist);

          vColor = vec4(color, 1.0 - smoothstep(0.5, 1.0, uv.y) * 0.5);

          normal *= uSize;// * (1.0 - uv.y);
          pos.xy -= normal * side;

          gl_Position = vec4(pos, 1.0);
        }
      `,
      fragmentShader: `
        varying vec4 vColor;
        void main() {
          gl_FragColor = vColor;
        }
      ` });


    const dx = verlet.width / conf.nx,dy = -verlet.height / conf.ny;
    const ox = -dx * (conf.nx / 2 - 0.5),oy = verlet.height / 2 - dy / 2;
    // const cscale = chroma.scale([chroma.random(), chroma.random()]);
    const cscale = chroma.scale([0x09256f, 0x6efec8]);
    for (let i = 0; i < conf.nx; i++) {
      const points = [];
      const vpoints = [];
      for (let j = 0; j < conf.ny; j++) {
        const x = ox + i * dx,y = oy + j * dy;
        points.push(new THREE.Vector3(x, y, 0));
        vpoints.push(new Vec2(x, y));
      }
      const polyline = new Polyline({ points, color1: cscale(rnd(0, 1)), color2: cscale(rnd(0, 1)) });
      polylines.push(polyline);

      polyline.segment = verlet.lineSegments(vpoints, 5);
      polyline.segment.pin(0);
      polyline.segment.particles.forEach(p => {p.pos.x += rndFS(10);});

      const mesh = new THREE.Mesh(polyline.geometry, material);
      scene.add(mesh);
    }
  }

  function updatePoints() {
    polylines.forEach(line => {
      for (let i = 0; i < line.points.length; i++) {
        const p = line.segment.particles[i].pos;
        line.points[i].x = p.x;
        line.points[i].y = p.y;
      }
      line.updateGeometry();
    });
  }

  function updateColors() {
    const c1 = chroma.random(),c2 = chroma.random();
    const cscale = chroma.scale([c1, c2]);
    console.log(c1.hex(), c2.hex());
    // #21a25f #a0fa42
    // #09256f #6efec8
    polylines.forEach(line => {
      line.color1 = cscale(rnd(0, 1));
      line.color2 = cscale(rnd(0, 1));
      const cscale1 = chroma.scale([line.color1, line.color2]);
      const colors = line.geometry.attributes.color.array;
      const c = new THREE.Color();
      f.........完整代码请登录后点击上方下载按钮下载查看

网友评论0