紫色

紫色

  • 示例
  • HTML
  • CSS
  • JS

更多有趣示例 尽在小红砖社区

示例

HTML



<a href="https://github.com/vaneenige/three.phenomenon" target="_blank">THREE.Phenomenona>

CSS

html,
body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;

  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  letter-spacing: 0;
  font-style: normal;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

canvas {
  position: fixed;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
}

a {
  position: fixed;
  margin: 16px;
  font-size: 14px;
  font-weight: 500;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  border-radius: 0;
  cursor: pointer;
  outline: none;
  padding: 8px 20px;
  border: 2px solid #E2A9E5;
  color: #E2A9E5;
  z-index: 1;
  font-weight: bold;
}

a:hover,
a:focus {
  color: white;
  background-color: #FFD700;
}

JS

function getArrayWithNoise(array, noise) {
  return array.map(item => item + getRandomBetween(noise));
}

function getRandomBetween(value) {
  const floor = -value;
  return floor + Math.random() * value * 2;
}

let instance;

function createInstance() {
  const duration = 0.7;

  const geometry = new THREE.IcosahedronGeometry(0.8, 0);

  // const multiplier = 50;

  const material = new THREE.MeshPhongMaterial({
    color: "#E2A9E5",
    emissive: "#632C65",
    flatShading: true,
    shininess: 100
  });

  const castShadow = true;

  const S = 20;
  const positions = [];
  for (let z = -S; z < S; z += 1) {
    for (let x = -S; x < S; x += 1) {
      positions.push(x, z);
    }
  }
   
  const multiplier = positions.length / 2;

  const attributes = [
    {
      name: "aPositionStart",
      size: 3,
      data: i => [positions[i * 2], 0, positions[i * 2 + 1]]
    },
    {
      name: "aControlPointOne",
      data: i => [positions[i * 2], 0, positions[i * 2 + 1]],
      size: 3
    },
    {
      name: "aControlPointTwo",
      data: i => [positions[i * 2], 0, positions[i * 2 + 1]],
      size: 3
    },
    {
      name: "aPositionEnd",
      size: 3,
      data: i => [positions[i * 2], 0, positions[i * 2 + 1]]
    },
    {
      name: "aOffset",
      data: i => [i * ((1 - duration) / (multiplier - 1))],
      size: 1
    }
  ];

  const uniforms = {
    time: {
      value: 0.25
    }
  };

  const vertex = `
    attribute vec3 aPositionStart;
    attribute vec3 aControlPointOne;
    attribute vec3 aControlPointTwo;
    attribute vec3 aPositionEnd;
    attribute float aOffset;
    uniform float time;

    float easeInOutSin(float t){
      return (1.0 + sin(${Math.PI} * t - ${Math.PI} / 2.0)) / 2.0;
    }

    vec4 quatFromAxisAngle(vec3 axis, float angle) {
      float halfAngle = angle * 0.5;
      return vec4(axis.xyz * sin(halfAngle), cos(halfAngle));
    }

    vec3 rotateVector(vec4 q, vec3 v) {
      return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
    }

    vec3 bezier4(vec3 a, vec3 b, vec3 c, vec3 d, float t) {
      return mix(mix(mix(a, b, t), mix(b, c, t), t), mix(mix(b, c, t), mix(c, d, t), t), t);
    }

    void main(){
      float tProgress = easeInOutSin(min(1.0, max(0.0, (time - aOffset)) / ${duration}));
      vec4 quatX = quatFromAxisAngle(vec3(1.0, 0.0, 0.0), -10.0 * tProgress);
      vec4 quatY = quatFromAxisAngle(vec3(0.0, 0.0, 0.0), -5.0 * tProgress);
      vec3 basePosition = rotateVector(quatX, rotateVector(quatY, position));
      vec3 newPosition = bezier4(aPositionStart, aControlPointOne, aControlPointTwo, aPositionEnd, tProgress);
      float scale = tProgress * 2.0 - 1.0;
      scale = 1.0 - scale * scale;
      basePosition *= scale;
      gl_Position = basePosition + newPosition;
    }
  `;

  //      vNormal = rotateVector(quatX, vNormal);
  instance = new THREE.Phenomenon({
    geometry,
    multiplier,
    material,
    castShadow,
    attributes,
    uniforms,
    vertex
  });

  scene.add(instance.mesh);
}

// Base structure --

const renderer = new THREE.WebGLRenderer({
  antialias: true
});

renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;

renderer.setClearColor(0xFFD700, 0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(1);

document.querySelector("body").appendChild(renderer.domElement);

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(
  40,
  window.innerWidth / window.innerHeight,
  0.1,
  10000
);
camera.position.set(0, 20 * 1, 35 * 1);
camera.lookAt(scene.position);
scene.add(camera);

const ambientLight = new THREE.AmbientLight("#FFD700", 0.1);
scene.add(ambientLight);

const plane = new THREE.Mesh(
  new THREE.PlaneGeometry(1000, 1000),
  new THREE.MeshPhongMaterial({
    emissive: "#4B384C"
  })
);
plane.receiveShadow = true;
plane.position.y = -15;
plane.rotation.x = Math.PI * -0.5;
scene.add(plane);

const light = new THREE.SpotLight(0xffffff, 3, 80, Math.PI * 0.25, 1, 2);
light.position.set(0, 40, 0);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
light.shadow.camera.near = 0.5;
light.shadow.camera.far = 31;

scene.add(light);

function animate() {
  requestAnimationFrame(animate);
  if (instance.uniforms.time.value >= 1) {
    instance.uniforms.time.value = 0;
  }
  instance.uniforms.time.value += 1 / (6 * 60);
  renderer.render(scene, camera);
}

createInstance();
animate();

window.addEventListener(
  "resize",
  () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

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

你可能感兴趣的:(#,场景模型)