前端嘛 Logo
前端嘛
好酷炫的 3D 小蜜蜂

好酷炫的 3D 小蜜蜂

<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <title>好酷炫的 3D 小蜜蜂</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script type="module">
      import * as THREE from "https://cdn.skypack.dev/three@0.129.0/build/three.module.js";
      import { GLTFLoader } from "https://cdn.skypack.dev/three@0.129.0/examples/jsm/loaders/GLTFLoader.js";
      import { gsap } from "https://cdn.skypack.dev/gsap";

      const camera = new THREE.PerspectiveCamera(
        10,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      camera.position.z = 13;

      const scene = new THREE.Scene();
      let bee;
      let mixer;
      const loader = new GLTFLoader();

      // Fixed GLB URL - using raw.githubusercontent.com which serves with proper CORS headers
      loader.load(
        "https://fecoder-pic-1302080640.cos.ap-nanjing.myqcloud.com/demon_bee_full_texture.glb",
        function (gltf) {
          bee = gltf.scene;
          scene.add(bee);

          mixer = new THREE.AnimationMixer(bee);
          mixer.clipAction(gltf.animations[0]).play();
          modelMove();
        },
        function (xhr) {
          // Progress callback
          console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
        },
        function (error) {
          // Error callback
          console.error("Error loading model:", error);
        }
      );

      const renderer = new THREE.WebGLRenderer({ alpha: true });
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.getElementById("container3D").appendChild(renderer.domElement);

      // light
      const ambientLight = new THREE.AmbientLight(0xffffff, 1.3);
      scene.add(ambientLight);

      const topLight = new THREE.DirectionalLight(0xffffff, 1);
      topLight.position.set(500, 500, 500);
      scene.add(topLight);

      const reRender3D = () => {
        requestAnimationFrame(reRender3D);
        renderer.render(scene, camera);
        if (mixer) mixer.update(0.02);
      };
      reRender3D();

      let arrPositionModel = [
        {
          id: "banner",
          position: { x: 0, y: -1, z: 0 },
          rotation: { x: 0, y: 1.5, z: 0 },
        },
        {
          id: "intro",
          position: { x: 1, y: -1, z: -5 },
          rotation: { x: 0.5, y: -0.5, z: 0.5 },
        },
        {
          id: "description",
          position: { x: -1, y: -1, z: -5 },
          rotation: { x: 0, y: 0.5, z: 0.2 },
        },
        {
          id: "contact",
          position: { x: 0.45, y: -2, z: -10 },
          rotation: { x: 0.2, y: -0.5, z: -0.2 },
        },
      ];

      const modelMove = () => {
        const sections = document.querySelectorAll(".section");
        let currentSection;
        sections.forEach((section) => {
          const rect = section.getBoundingClientRect();
          if (rect.top <= window.innerHeight / 3) {
            currentSection = section.id;
          }
        });
        let position_active = arrPositionModel.findIndex(
          (val) => val.id == currentSection
        );
        if (position_active >= 0) {
          let new_coordinates = arrPositionModel[position_active];
          gsap.to(bee.position, {
            x: new_coordinates.position.x,
            y: new_coordinates.position.y,
            z: new_coordinates.position.z,
            duration: 3,
            ease: "power1.out",
          });
          gsap.to(bee.rotation, {
            x: new_coordinates.rotation.x,
            y: new_coordinates.rotation.y,
            z: new_coordinates.rotation.z,
            duration: 3,
            ease: "power1.out",
          });
        }
      };

      window.addEventListener("scroll", () => {
        if (bee) {
          modelMove();
        }
      });

      window.addEventListener("resize", () => {
        renderer.setSize(window.innerWidth, window.innerHeight);
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
      });
    </script>
    <link
      rel="stylesheet"
      href="https://public.codepenassets.com/css/normalize-5.0.0.min.css"
    />
    <style>
      @import url("https://fonts.cdnfonts.com/css/devil-breeze");
      @import url("https://fonts.cdnfonts.com/css/poppins");
      @import url("https://fonts.cdnfonts.com/css/bimbo");

      body {
        margin: 0;
        font-family: "Montserrat", sans-serif;
        background-color: #1b1b1b;
        color: #eef8ce;
        font-family: "Poppins", sans-serif;
        font-size: 14px;
        background-image: url(https://assets.codepen.io/453571/bg.avif),
          repeating-linear-gradient(
            to right,
            transparent 0 500px,
            #73814b33 500px 501px
          );
        background-size: 100%;
      }
      *::-webkit-scrollbar {
        width: 0;
      }

      * {
        padding: 0;
        margin: 0;
        list-style: none;
        box-sizing: border-box;
      }
      .section {
        width: 100%;
        min-height: 100vh;
        position: relative;
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .content-fit {
        width: min(1200px, 90vw);
        margin: auto;
        min-height: 100vh;
        position: relative;
        padding-block: 10em;
      }
      header {
        padding-block: 1em;
        position: fixed;
        top: 0;
        width: 100%;
        z-index: 10px;
        -webkit-backdrop-filter: blur(20px);
        backdrop-filter: blur(20px);
        z-index: 100;
        background-color: #1b1b1b11;
        background-image: repeating-linear-gradient(
          to right,
          transparent 0 500px,
          #eee1 500px 501px
        );
      }
      header .content-fit {
        display: flex;
        justify-content: space-between;
        align-items: center;
        min-height: unset !important;
        padding-block: unset !important;
      }
      header .content-fit nav ul {
        display: flex;
        gap: 2em;
      }

      #banner .title {
        color: #d1ff48;
        font-size: 11em;
        font-family: "devil breeze";
        font-weight: bold;
        position: relative;
        overflow: visible;
        text-align: center;
      }
      #banner .title::before {
        content: attr(data-before);
        position: absolute;
        z-index: -1;
        color: oklch(0.78 0.17 80.01 / 0.19);
        -webkit-mask: linear-gradient(
          to bottom,
          #000 -80%,
          oklch(0 0 0/0),
          #000,
          oklch(0 0 0/0) 200%
        );
        mask: linear-gradient(
          to bottom,
          #000 -80%,
          oklch(0 0 0/0),
          #000,
          oklch(0 0 0/0) 200%
        );
        transform: scaleY(-1) translateY(-0.44lh);
      }
      .section .decorate {
        position: fixed;
        z-index: -100;
        pointer-events: none;
      }
      #intro .content-fit {
        display: flex;
        gap: 30%;
        justify-content: space-between;
        align-items: center;
      }
      .section .number {
        font-family: "devil breeze";
        font-size: 15em;
        font-weight: bold;
      }
      .section .content-fit .title {
        font-family: "devil breeze";
        font-size: 5em;
        font-weight: bold;
      }
      #description .content-fit {
        padding-right: 30%;
      }
      #description .number {
        font-size: 5em;
      }
      #description .title {
        font-size: 7em;
        font-weight: 500;
      }
      #contact .content-fit {
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        text-align: center;
      }
      #contact table {
        width: min(800px, 90vw);
        padding-top: 2em;
        font-size: 2em;
        margin: auto;
      }
      #contact table td {
        padding-block: 0.5em;
        border-bottom: 1px dashed #445022;
      }
      #contact table td:nth-child(1) {
        text-align: left;
        font-weight: 500;
      }
      #contact table td:nth-child(2) {
        text-align: right;
        font-weight: 200;
      }
      #contact .sign {
        font-size: 10em;
      }
      #container3D {
        position: fixed;
        inset: 0;
        /* background-color: red; */
        z-index: 100;
        pointer-events: none;
      }
      @media screen and (max-width: 1023px) {
        #banner .title {
          font-size: 5em;
        }
        #intro .content-fit {
          flex-direction: column;
        }
      }
      @media screen and (max-width: 767px) {
        #banner .title {
          font-size: 3em;
        }
        #intro .content-fit {
          flex-direction: column;
        }
        .section .number {
          font-size: 5em;
        }
        .section .content-fit .title {
          font-size: 2em;
        }
        #description .content-fit {
          padding-right: 0;
        }
        #contact table {
          font-size: 1em;
        }
        #contact .sign {
          font-size: 2em;
        }
        #container3D {
          position: sticky;
        }
      }
    </style>
  </head>

  <body>
    <header>
      <div class="content-fit">
        <div class="logo">DDX</div>
        <nav>
          <ul>
            <li>Contacts</li>
            <li>Category</li>
            <li>Login</li>
          </ul>
        </nav>
      </div>
    </header>
    <div class="section" id="banner">
      <div class="content-fit">
        <div class="title" data-before="3D ANIMATION">3D ANIMATION</div>
      </div>
      <img
        src="https://assets.codepen.io/453571/flower.png"
        class="decorate"
        alt=""
        style="width: 50vw; bottom: 0; right: 0"
      />
      <img
        src="https://assets.codepen.io/453571/leaf.png"
        class="decorate"
        alt=""
        style="width: 30vw; bottom: 0; left: 0"
      />
    </div>
    <div class="section" id="intro">
      <div class="content-fit">
        <div class="number">01</div>
        <div class="des">
          <div class="title">3d animation design for website</div>
          <p>
            Lorem ipsum dolor sit, amet consectetur adipisicing elit.
            Voluptatibus voluptas a porro libero recusandae quae, aut ratione,
            incidunt laborum, necessitatibus similique enim doloremque ex.
            Laudantium obcaecati aspernatur doloremque illo beatae, maxime hic
            itaque consequatur nisi accusantium veritatis, voluptatem ratione!
            Placeat numquam nisi reiciendis harum quibusdam tempore eaque
            deleniti accusantium, veniam quae eos sed, asperiores laborum
            corporis odit mollitia consequatur adipisci? Quibusdam quis eos
            debitis non esse blanditiis laudantium rerum odit tempora? Corrupti
            maiores velit consequuntur cupiditate reiciendis similique provident
            repudiandae.
          </p>
        </div>
      </div>
    </div>
    <div class="section" id="description">
      <div class="content-fit">
        <div class="number">02</div>
        <div class="des">
          <div class="title">DEN DX</div>
          <p>
            Lorem ipsum dolor sit, amet consectetur adipisicing elit.
            Voluptatibus voluptas a porro libero recusandae quae, aut ratione,
            incidunt laborum, necessitatibus similique enim doloremque ex.
            Laudantium obcaecati aspernatur doloremque illo beatae, maxime hic
            itaque consequatur nisi accusantium veritatis, voluptatem ratione!
            Placeat numquam nisi reiciendis harum quibusdam tempore eaque
            deleniti accusantium, veniam quae eos sed, asperiores laborum
            corporis odit mollitia consequatur adipisci? Quibusdam quis eos
            debitis non esse blanditiis laudantium rerum odit tempora? Corrupti
            maiores velit consequuntur cupiditate reiciendis similique provident
            repudiandae.
          </p>
        </div>
      </div>
      <img
        src="https://assets.codepen.io/453571/leaf1.png"
        class="decorate"
        alt=""
        style="width: 70vw; bottom: 0; right: 0"
      />
    </div>
    <div class="section" id="contact">
      <div class="content-fit">
        <div class="number">03</div>
        <div class="des">
          <div class="title">CONTACT</div>
          <table>
            <tr>
              <td>Email</td>
              <td>test@gmail.com</td>
            </tr>
            <tr>
              <td>Phone</td>
              <td>+841.231.235</td>
            </tr>
            <tr>
              <td>Website</td>
              <td>example.com</td>
            </tr>
          </table>
          <div class="sign">Den DX</div>
        </div>
      </div>
    </div>
    <div id="container3D"></div>
  </body>
</html>