VibeCoderzVibeCoderz
All Prompts
Precision Engineering WebGL Feature Section preview
featuresectioninteractivewebglanimatedresponsiveproducthover

Precision Engineering WebGL Feature Section

Секция с WebGL-анимацией для демонстрации точной инженерии. Интерактивные элементы, карточки с ховером. Идеально для премиум-продуктов.

Prompt

<section id="precision-engineering" class="bg-[#26221E] text-[#F2EFEA] py-32 relative overflow-hidden"
  style="font-family: 'Inter', sans-serif;">
  <!-- Component-Specific Styles -->
  <style>
    .card-flashlight {
      position: relative;
      background: rgba(255, 255, 255, 0.03);
      border: 1px solid rgba(255, 255, 255, 0.05);
      transition: transform 0.3s ease;
    }

    .card-flashlight::before {
      content: "";
      position: absolute;
      inset: 0;
      background: radial-gradient(600px circle at var(--mouse-x, 0) var(--mouse-y, 0), rgba(255, 255, 255, 0.08), transparent 40%);
      z-index: 0;
      opacity: 0;
      transition: opacity 0.4s ease;
      pointer-events: none;
    }

    .card-flashlight::after {
      content: "";
      position: absolute;
      inset: 0;
      padding: 1px;
      border-radius: inherit;
      background: radial-gradient(400px circle at var(--mouse-x, 0) var(--mouse-y, 0), rgba(255, 255, 255, 0.4), transparent 40%);
      -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
      -webkit-mask-composite: xor;
      mask-composite: exclude;
      z-index: 1;
      opacity: 0;
      transition: opacity 0.4s ease;
      pointer-events: none;
    }

    .card-flashlight:hover::before,
    .card-flashlight:hover::after {
      opacity: 1;
    }

    .card-content {
      position: relative;
      z-index: 2;
    }
  </style>

  <div class="max-w-[88rem] mx-auto px-6 lg:px-12 relative z-10">
    <!-- Header -->
    <div class="flex justify-between items-end mb-20 border-b border-white/10 pb-8">
      <h2 class="text-5xl md:text-6xl tracking-tighter font-light"
        style="font-family: 'Plus Jakarta Sans', sans-serif;">Precision<br>Engineering</h2>
      <p class="text-xl tracking-tight opacity-50 font-light" style="font-family: 'Plus Jakarta Sans', sans-serif;">
        SPEC_089</p>
    </div>

    <div class="grid grid-cols-1 lg:grid-cols-3 gap-12 lg:gap-8 items-center">
      <!-- Left Column: Series -->
      <div class="space-y-6 text-sm font-medium tracking-tight">
        <p class="opacity-40 text-xs uppercase mb-8" style="font-family: 'Geist', sans-serif;">Series Classification</p>
        <div
          class="flex items-center gap-4 group cursor-pointer border-b border-white/5 pb-4 hover:border-white/30 transition-colors">
          <span class="opacity-40 text-xs w-6">01</span>
          <span class="opacity-70 group-hover:opacity-100 transition-opacity">Kinetic Lounge</span>
        </div>
        <div
          class="flex items-center gap-4 group cursor-pointer border-b border-white/5 pb-4 hover:border-white/30 transition-colors">
          <span class="opacity-40 text-xs w-6">02</span>
          <span class="opacity-70 group-hover:opacity-100 transition-opacity">Minimalist Rocker</span>
        </div>
        <div
          class="flex items-center gap-4 group cursor-pointer border-b border-white/5 pb-4 hover:border-white/30 transition-colors">
          <span class="opacity-40 text-xs w-6">03</span>
          <span class="opacity-70 group-hover:opacity-100 transition-opacity">Ergo-Task Hybrid</span>
        </div>
        <div
          class="flex items-center gap-4 group cursor-pointer border-b border-white/5 pb-4 hover:border-white/30 transition-colors">
          <span class="opacity-40 text-xs w-6">04</span>
          <span class="opacity-70 group-hover:opacity-100 transition-opacity">Modular Accent</span>
        </div>
      </div>

      <!-- Center Image with WebGL -->
      <div class="card-flashlight p-2 rounded-2xl h-[500px]">
        <div class="card-content w-full h-full rounded-xl overflow-hidden relative">
          <img id="webgl-target" src="https://hoirqrkdgbmvpwutwuwj.supabase.co/storage/v1/object/public/assets/assets/62ec4789-2963-4666-aa09-20586e294364_800w.webp" alt="Chair Detail" class="absolute inset-0 w-full h-full object-cover">
        </div>
      </div>

      <!-- Right Column: Materials -->
      <div class="space-y-6 text-sm font-medium tracking-tight text-right">
        <p class="opacity-40 text-xs uppercase mb-8" style="font-family: 'Geist', sans-serif;">Material Synthesis</p>
        <div
          class="flex items-center justify-end gap-4 group cursor-pointer border-b border-white/5 pb-4 hover:border-white/30 transition-colors">
          <span class="opacity-70 group-hover:opacity-100 transition-opacity">Aero-grade aluminum chassis</span>
          <iconify-icon icon="solar:arrow-right-up-linear"
            class="opacity-0 group-hover:opacity-100 transition-opacity"></iconify-icon>
        </div>
        <div
          class="flex items-center justify-end gap-4 group cursor-pointer border-b border-white/5 pb-4 hover:border-white/30 transition-colors">
          <span class="opacity-70 group-hover:opacity-100 transition-opacity">Thermo-responsive polymer mesh</span>
        </div>
        <div
          class="flex items-center justify-end gap-4 group cursor-pointer border-b border-white/5 pb-4 hover:border-white/30 transition-colors">
          <span class="opacity-70 group-hover:opacity-100 transition-opacity">Sustainably sourced walnut accents</span>
        </div>
        <div
          class="flex items-center justify-end gap-4 group cursor-pointer border-b border-white/5 pb-4 hover:border-white/30 transition-colors">
          <span class="opacity-70 group-hover:opacity-100 transition-opacity">Micro-calibration lumbar system</span>
        </div>
      </div>
    </div>
  </div>

  <script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script>
  <script>
    (function() {
      const section = document.getElementById('precision-engineering');
      const cards = section.querySelectorAll('.card-flashlight');
      cards.forEach(card => {
        card.addEventListener('mousemove', (e) => {
          const rect = card.getBoundingClientRect();
          card.style.setProperty('--mouse-x', `${e.clientX - rect.left}px`);
          card.style.setProperty('--mouse-y', `${e.clientY - rect.top}px`);
        });
      });

      const vs = `attribute vec2 a;varying vec2 v;void main(){v=a*0.5+0.5;gl_Position=vec4(a,0,1);}`;
      const fs = `precision highp float;varying vec2 v;uniform sampler2D t;uniform float p;void main(){float c=4.0,i=floor(v.x*c),s=0.15,d=i*s,l=clamp((p*(1.0+3.0*s)-d),0.0,1.0),e=pow(l-1.0,3.0)+1.0;if(v.y<1.0-e)discard;gl_FragColor=texture2D(t,v);}`;

      const target = document.getElementById('webgl-target');
      const img = new Image();
      img.crossOrigin = "anonymous";
      img.onload = () => {
        const canvas = document.createElement('canvas');
        canvas.width = img.naturalWidth; canvas.height = img.naturalHeight;
        canvas.className = target.className;
        target.parentNode.insertBefore(canvas, target); target.style.display = 'none';
        const gl = canvas.getContext('webgl', { alpha: true });
        if (!gl) return;
        const sh = (type, src) => { const s = gl.createShader(type); gl.shaderSource(s, src); gl.compileShader(s); return s; };
        const pg = gl.createProgram(); gl.attachShader(pg, sh(gl.VERTEX_SHADER, vs)); gl.attachShader(pg, sh(gl.FRAGMENT_SHADER, fs)); gl.linkProgram(pg); gl.useProgram(pg);
        const buf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buf); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]), gl.STATIC_DRAW);
        const al = gl.getAttribLocation(pg, "a"); gl.enableVertexAttribArray(al); gl.vertexAttribPointer(al, 2, gl.FLOAT, false, 0, 0);
        const tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        const up = gl.getUniformLocation(pg, "p");
        let start = null;
        const draw = (now) => {
          if (!start) start = now;
          let prog = Math.min((now - start) / 1200, 1.0);
          gl.viewport(0, 0, canvas.width, canvas.height); gl.clear(gl.COLOR_BUFFER_BIT);
          gl.uniform1f(up, prog); gl.drawArrays(gl.TRIANGLES, 0, 6);
          if (prog < 1) requestAnimationFrame(draw);
        };
        const obs = new IntersectionObserver((es) => { if(es[0].isIntersecting) { requestAnimationFrame(draw); obs.disconnect(); } }, { threshold: 0.1 });
        obs.observe(canvas);
      };
      img.src = target.src;
    })();
  </script>
</section>
All Prompts