已拥有 3d 台式机小屋

Published on
/
/趣玩前端
<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <title>3d台式机小屋</title>
    <style>
      *,
      *::after,
      *::before {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        outline: none;
        font-family: monospace;
      }
      body {
        overflow: hidden;
        background-color: #d2cfc8;
        cursor: grab;
      }
      .webgl,
      #loader {
        position: fixed;
        top: 0;
        left: 0;
      }
      #loader {
        display: grid;
        place-content: center;
        width: 100%;
        height: 100%;
        background-color: #faedcd;
      }
    </style>
  </head>
  <body>
    <canvas class="webgl"></canvas>
    <div id="loader">
      <h1>Loading</h1>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r124/three.min.js"></script>
    <script src="https://unpkg.com/three@0.126.0/examples/js/loaders/GLTFLoader.js"></script>
    <script src="https://unpkg.com/three@0.126.0/examples/js/controls/OrbitControls.js"></script>
    <script>
      const loading = document.querySelector('#loader');
      const canvas = document.querySelector('.webgl');
      const scene = new THREE.Scene();
      const textureLoader = new THREE.TextureLoader();
      const sizes = { width: window.innerWidth, height: window.innerHeight };
      const camera = new THREE.PerspectiveCamera(
        10,
        sizes.width / sizes.height,
        0.1,
        100
      );
      camera.position.x = 8;
      camera.position.y = 4;
      camera.position.z = 15;
      scene.add(camera);
      const controls = new THREE.OrbitControls(camera, canvas);
      controls.enableDamping = true;
      controls.enableZoom = true;
      controls.enablePan = true;
      controls.minDistance = 21;
      controls.maxDistance = 50;
      controls.minPolarAngle = Math.PI / 5;
      controls.maxPolarAngle = Math.PI / 2;
      const renderer = new THREE.WebGLRenderer({
        canvas: canvas,
        antialias: true,
        alpha: true,
      });
      renderer.setSize(sizes.width, sizes.height);
      renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
      renderer.outputEncoding = THREE.sRGBEncoding;
      const bakedTexture = textureLoader.load(
        'https://www.fecoder.cn/code-fun/baked.jpg'
      );
      bakedTexture.flipY = false;
      bakedTexture.encoding = THREE.sRGBEncoding;
      const bakedMaterial = new THREE.MeshBasicMaterial({ map: bakedTexture });
      const loader = new THREE.GLTFLoader();
      loader.load(
        'https://www.fecoder.cn/code-fun/model.glb',
        (gltf) => {
          const model = gltf.scene;
          model.traverse((child) => (child.material = bakedMaterial));
          scene.add(model);
          scene.position.set(0, 0.2, 0);
          loading.style.display = 'none';
        },
        (xhr) => {
          console.log((xhr.loaded / xhr.total) * 100 + '% loaded');
        }
      );
      window.addEventListener('resize', () => {
        sizes.width = window.innerWidth;
        sizes.height = window.innerHeight;
        camera.aspect = sizes.width / sizes.height;
        camera.updateProjectionMatrix();
        renderer.setSize(sizes.width, sizes.height);
        renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
      });
      var minPan = new THREE.Vector3(-2, -0.5, -2);
      var maxPan = new THREE.Vector3(2, 0.5, 2);
      const tick = () => {
        controls.update();
        controls.target.clamp(minPan, maxPan);
        renderer.render(scene, camera);
        window.requestAnimationFrame(tick);
      };
      tick();
    </script>
  </body>
</html>