gsap+three实现鼠标滚动tab切换丝带跟随扭动动画背景效果代码

代码语言:html

所属分类:选项卡

代码描述:gsap+three实现鼠标滚动tab切换丝带跟随扭动动画背景效果代码,顶部指示条显示当前tab位置,通过点击或滚动鼠标切换tab更换纽带。

代码标签: gsap three 鼠标 滚动 tab 切换 丝带 跟随 扭动 动画 背景

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

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">

  

    <style>

      :root {
        --c0: white;
        --c8: #494942;
        --c9: #31312c;
        --c10: #181816;
        --c11: black;
        --filter-01:url(#turbulence-effect);
      }
      ::-webkit-scrollbar {
        width: 8px;
        height: 3px;
        background-color: var(--c11);
      }
      ::-webkit-scrollbar-thumb {
        height: 50px;
        background-color: var(--c0);
        border-radius: 0px;
      }
      ::-webkit-scrollbar-button {
        background-color: var(--c8);
        display: none;
      }
      ::-webkit-scrollbar-track {
        background-color: var(--c8);
      }
      ::-webkit-scrollbar-track-piece {
        background-color: var(--c8);
      }

      ::-webkit-scrollbar-corner {
        background-color: var(--c9);
      }
      ::-webkit-resizer {
        background-color: var(--c9);
      }
      * {
        box-sizing: border-box;
        font-family: sans-serif;
      }

      html, body {
        height: 100%;
        width: 100%;
        margin: 0;
        padding: 0;
        user-select:none;
      }

      body {
        margin: 0;
        overflow-x: hidden;
        background: #000;
      }

      a {
        color:#fff;
        text-decoration:none;
        font-size : 12px;
        font-weight:bold;
      }

      nav {
        position:absolute;
        z-index:6;
        top:30rem;
      }

      menu{
        position: fixed;
        top: 1rem;
        left: 0;
        width: 100%;
        text-align: center;
        z-index: 1000;      
      }

      menu ul{
        list-style-type: none;
        display: inline-flex;
        justify-content: center;
      }

      menu ul li{
        display: inline;
        margin:.3rem;
        padding:.7rem 1rem;
        border-radius: .4rem;
        background : rgba(0,0,0,0.5);
      }
      #underline {
        position: fixed;
        top: 0;
        height: 6px;
        background: white;
        border-bottom: solid 1px #f00;
        width: 0;
        transform-origin: left center;
        pointer-events: none;
        transition: width 0.3s ease, left 0.3s ease;
      }
      .scrollTarget {
        position: absolute;
        height: 600%; /* Adjusted to match the number of sections */
        width: 100%;
        top: 0;
        z-index: 0;
      }

      .experience {
        display: block;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 2;
      }

      main {
        position: relative;
        width: 100%;
        height: 100%;
        z-index: 3;
      }

      section.panel {
        padding-top: 60px; 
        position: relative;
        display: block;
        width: 100%;
        height: 100vh; /* Ensure each section takes the full viewport height */
        border-bottom: solid 1px rgba(255,255,255,0.1);
        z-index: 4;
      }

      .panel p {
        font-size: 16px;
        color: #fff;
        padding: 10vw;
      }

    </style>
  </head>
  <body>
    <nav>
      <menu>
        <ul>
          <li><a href="#section-1">Section 1</a></li>
          <li><a href="#section-2">Section 2</a></li>
          <li><a href="#section-3">Section 3</a></li>
          <li><a href="#section-4">Section 4</a></li>
          <li><a href="#section-5">Section 5</a></li>
          <li><a href="#section-6">Section 6</a></li>
        </ul>
      </menu>
      <div id="underline"></div>
    </nav>
    <main>

      <section class="panel" id="section-1"><p>Section 1</p></section>
      <section class="panel" id="section-2"><p>Section 2</p></section>
      <section class="panel" id="section-3"><p>Section 3</p></section>
      <section class="panel" id="section-4"><p>Section 4</p></section>
      <section class="panel" id="section-5"><p>Section 5</p></section>
      <section class="panel" id="section-6"><p>Section 6</p></section>

    </main>

    <div class="scrollTarget"></div>
    <canvas class="experience"></canvas>

<script type="importmap">
  {
    "imports": {
      "three": "//repo.bfw.wiki/bfwrepo/js/module/three/build/164/three.module.js",
      "three/addons/": "//repo.bfw.wiki/bfwrepo/js/module/three/examples/164/jsm/"
    }
  }
</script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/gsap.3.12.2.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/ScrollTrigger.3.12.5.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/ScrollToPlugin3.min.js"></script>
    <script type="module">
      import * as THREE from 'three';
      import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
      import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
      import { FontLoader } from 'three/addons/loaders/FontLoader.js';
      import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
      import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
      import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
      import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
      import { GlitchPass } from 'three/addons/postprocessing/GlitchPass.js';


      gsap.registerPlugin(ScrollTrigger);
      gsap.registerPlugin(ScrollToPlugin);

      document.addEventListener("DOMContentLoaded", function() {
        const menuLinks = document.querySelectorAll('menu ul li a');
        const underline = document.getElementById('underline');

        function updateUnderline(target) {
          const linkRect = target.getBoundingClientRect();
          const menuRect = target.closest('menu').getBoundingClientRect();

          gsap.to(underline, {
            duration: 0.3,
            width: linkRect.width,
            left: linkRect.left - menuRect.left,
            ease: "power3.out"
          });
        }

        menuLinks.forEach(link => {
          link.addEventListener('click', function(e) {
            e.preventDefault(); 
            const targetId = this.getAttribute('href');
            gsap.to(window, {
              duration: 1, 
              scrollTo: targetId,
              onComplete: () => {
                updateUnderline(this);
              }
            });
          });
        });

        // Update underline on scroll
        window.addEventListener('scroll', function() {
          const fromTop = window.scrollY + 60; // 60 to account for the fixed nav height

          menuLinks.forEach(link => {
            const section = document.querySelector(link.getAttribute('href'));
            if (
              section.offsetTop <= fromTop &&
              section.offsetTop + section.offsetHeight > fromTop
            ) {
              updateUnderline(link);
            }
          });
        });

        // Initialize underline position
        if (menuLinks.length > 0) {
          updateUnderline(menuLinks[0]);
        }
      });


      const scene = new THREE.Scene();
      scene.fog = new THREE.Fog(0x000000, -800, 800);

      const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      const renderer = new THREE.WebGLRenderer({ 
        antialias: true, 
        canvas: document.querySelector('.experience'),
        shadowMapEnabled: true,
        shadowMapType: THREE.PCFSoftShadowMap
      });
      renderer.setSize(window.innerWidth, window.innerHeight);

      const points = [
        new THREE.Vector3(0, 0, 0),
        new THREE.Vector3(5, -5, 100),
        new THREE.Vector3(20, 0, 200),
        new THREE.Vector3(30, -10, 300),
        new THREE.Vector3(0, 0, 400),
        new THREE.Vector3(5, 5, 500),
        new THREE.Vector3(-5, 5, 600),
        new THREE.Vector3(5, -5, 700),
      ];
      const path = new THREE.CatmullRomCurve3(points);
      const initialPoint = path.getPointAt(0);
      const initialLookAtPoint = path.getPointAt(0.01);

      camera.position.copy(initialPoint);
      camera.lookAt(initialLookAtPoint);      

      let composer, params = {
        exposure: .3,
        bloomStrength: .7,
        bloomThreshold: 0,
        bloomRadius: 0
      };
      const renderScene = new RenderPass(scene, camera);

      // ---------------
      // bloomPass, noisePass, scanLinePass 
      // ---------------

      const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
      bloomPass.renderToScreen = true;
      bloomPass.threshold = params.bloomThreshold;
      bloomPass.strength = params.bloomStrength;
      bloomPass.radius = params.bloomRadius;

      composer = new EffectComposer(renderer);
      composer.setSize(window.innerWidth, window.innerHeight);
      composer.addPass(renderScene);
      composer.addPass(bloomPass);

      let noisePass;
      const noiseShader = {
        uniforms: {
          'tDiffuse': { value: null },
          'amount': { value: 0.05 }
        },
        vertexShader: `
          varying vec2 vUv;
          void main() {
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
          }
        `,
        fragmentShader: `
          uniform sampler2D tDiffuse;
          uniform float amount;
          varying vec2 vUv;
          float rand(vec2 co) {
            return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
          }
          void main() {
            vec4 color = texture2D(tDiffuse, vUv);
            float noise = rand(gl_FragCoord.xy) * amount;
            gl_FragColor = vec4(color.rgb + noise, color.a);
          }
        `
      };

      noisePass = new ShaderPass(noiseShader);
      composer.addPass(noisePass);

      const scanLinePass = new ShaderPass({
        uniforms: {
          "tDiffuse": { value: null },
          "time": { value: 0.0 },
          "lineHeight": { value: 4.0 },
          "lineSpacing": { value: 2.0 },
          "opacity": { value: 0.1 }
        },
        vertexShader: `
          varying vec2 vUv;
          void main() {
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
          }
        `,
        fragmentShader: `
          uniform sampler2D tDiffuse;
          uniform float time;
          uniform float lineHeight;
          uniform float lineSpacing;
          uniform float opacity;
          varying vec2 vUv;

          void main() {
            vec4 color = texture2D(tDiffuse, vUv);
            float scanline = step(lineSpacing, mod(gl_FragCoord.y, lineHeight)) * opacity;
            color.rgb += scanline;
            gl_FragColor = color;
          }
        `,
        blending: THREE.AdditiveBlending
      });
      composer.addPass(scanLinePass);

      // ---------------
      // shaderMat.........完整代码请登录后点击上方下载按钮下载查看

网友评论0