three+gsap实现webgl波浪涟漪全屏图片幻灯片过渡动画效果代码

代码语言:html

所属分类:幻灯片

代码描述:three+gsap实现webgl波浪涟漪全屏图片幻灯片过渡动画效果代码,可按h键进行更高级的参数设置。

代码标签: three gsap webgl 波浪 涟漪 全屏 图片 幻灯片 过渡 动画

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

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

<head>
  <meta charset="UTF-8">
  
  
  
<style>
@import url("https://fonts.cdnfonts.com/css/pp-neue-montreal");

@font-face {
  font-family: "PPSupplyMono";
  src: url("//repo.bfw.wiki/bfwrepo/font/PPSupplyMono-Regular.ttf")
    format("truetype");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

:root {
  --font-mono: "PPSupplyMono", monospace;
  --font-sans: "PP Neue Montreal", sans-serif;
  --color-bg: #000;
  --color-text: #fff;
  --color-text-muted: rgba(255, 255, 255, 0.8);
  --color-text-light: rgba(255, 255, 255, 0.6);
  --color-accent: #fff;
  --font-size-mono: clamp(10px, 1.2vw, 12px);
  --spacing-sm: 1rem;
  --spacing-md: 2rem;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: var(--font-sans);
  background: var(--color-bg);
  overflow: hidden;
  color: var(--color-text);
  cursor: pointer;
}

.slider-wrapper {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

.webgl-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* Current slide number at middle left - UPDATED: 12px uppercase */
.slide-number {
  position: absolute;
  top: 50%;
  left: var(--spacing-md);
  transform: translateY(-50%);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text);
  z-index: 3;
  letter-spacing: 1px;
  text-transform: uppercase;
}

/* Total slides at middle right - UPDATED: 12px uppercase */
.slide-total {
  position: absolute;
  top: 50%;
  right: var(--spacing-md);
  transform: translateY(-50%);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text);
  z-index: 3;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.slides-navigation {
  position: absolute;
  bottom: var(--spacing-md);
  left: var(--spacing-md);
  right: var(--spacing-md);
  display: flex;
  gap: 0;
  z-index: 3;
  pointer-events: all;
}

.slide-nav-item {
  display: flex;
  flex-direction: column;
  cursor: pointer;
  padding: var(--spacing-sm);
  flex: 1;
  border: none;
  background: none;
}

.slide-progress-line {
  width: 100%;
  height: 2px;
  background: rgba(255, 255, 255, 0.2);
  margin-bottom: 8px;
  border-radius: 1px;
  overflow: hidden;
}

.slide-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--color-accent);
  transition: width 0.1s ease, opacity 0.3s ease;
  border-radius: 1px;
}

.slide-nav-title {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-text-muted);
  font-weight: 600;
  transition: color 0.3s ease;
}

.slide-nav-item.active .slide-nav-title {
  color: var(--color-text);
}

.help-text {
  position: absolute;
  top: var(--spacing-md);
  left: var(--spacing-md);
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  color: var(--color-text-muted);
  z-index: 3;
}

/* Tweakpane Styling */
.tp-dfwv {
  position: fixed !important;
  top: 20px !important;
  right: 20px !important;
  z-index: 1000 !important;
  max-width: 320px !important;
  background: rgba(0, 0, 0, 0.9) !important;
  -webkit-backdrop-filter: blur(20px) !important;
          backdrop-filter: blur(20px) !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  border-radius: 8px !important;
}

.tp-dfwv .tp-btnv_b {
  background: rgba(255, 255, 255, 0.1) !important;
  border: 1px solid rgba(255, 255, 255, 0.2) !important;
  color: #ffffff !important;
  font-family: var(--font-mono) !important;
  border-radius: 4px !important;
}

.tp-dfwv .tp-btnv_b:hover {
  background: rgba(255, 255, 255, 0.2) !important;
}

@media (max-width: 600px) {
  .slides-navigation {
    bottom: var(--spacing-sm);
    left: var(--spacing-sm);
    right: var(--spacing-sm);
  }

  .slide-nav-item {
    padding: 0.75rem;
  }

  .help-text {
    top: var(--spacing-sm);
    left: var(--spacing-sm);
  }

  .slide-number {
    left: var(--spacing-sm);
  }

  .slide-total {
    right: var(--spacing-sm);
  }

  .tp-dfwv {
    top: 10px !important;
    right: 10px !important;
    max-width: 280px !important;
  }
}

/* Preloader styles */
.slider-wrapper {
  opacity: 0;
  transition: opacity 1.5s ease-in;
  pointer-events: none;
}

.slider-wrapper.loaded {
  opacity: 1;
  pointer-events: auto;
}
</style>



  
  
</head>

<body translate="no">
  <main class="slider-wrapper">
  <canvas class="webgl-canvas"></canvas>
  <span class="slide-number" id="slideNumber">01</span>
  <span class="slide-total" id="slideTotal">06</span>
  <span class="help-text">
    H: Toggle Settings • Space/→: Next • ←: Previous • Click to Advance
  </span>
  <nav class="slides-navigation" id="slidesNav">

  </nav>
</main>
      <script type="importmap">
{
 "imports":{
    "three":"//repo.bfw.wiki/bfwrepo/js/module/three/build/165/three.module.js"
   
 }
}

</script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/gsap.3.13.0.js"></script>
    <script type="module">
// ========================================
// PRELOADER
// ========================================
class SliderLoadingManager {
  constructor() {
    this.overlay = null;
    this.canvas = null;
    this.ctx = null;
    this.animationId = null;
    this.startTime = null;
    this.duration = 3000;
    this.createLoadingScreen();
  }

  createLoadingScreen() {
    this.overlay = document.createElement("div");
    this.overlay.style.cssText = `
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: #000000;
      display: flex;
      justify-content: center;
      align-items: center;
      z-index: 10000;
    `;

    this.canvas = document.createElement("canvas");
    this.canvas.width = 300;
    this.canvas.height = 300;

    this.ctx = this.canvas.getContext("2d");
    this.overlay.appendChild(this.canvas);
    document.body.appendChild(this.overlay);

    this.startAnimation();
  }

  startAnimation() {
    const centerX = this.canvas.width / 2;
    const centerY = this.canvas.height / 2;
    let time = 0;
    let lastTime = 0;

    const dotRings = [
    { radius: 20, count: 8 },
    { radius: 35, count: 12 },
    { radius: 50, count: 16 },
    { radius: 65, count: 20 },
    { radius: 80, count: 24 }];


    const colors = {
      primary: "#ffffff",
      accent: "#dddddd" };


    const easeInOutSine = t => {
      return -(Math.cos(Math.PI * t) - 1) / 2;
    };

    const easeInOutCubic = t => {
      return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
    };

    const smoothstep = (edge0, edge1, x) => {
      const t = Math.max(0, Math.min(1, (x - edge0) / (edge1 - edge0)));
      return t * t * (3 - 2 * t);
    };

    const hexToRgb = hex => {
      if (hex.startsWith("#")) {
        return [
        parseInt(hex.slice(1, 3), 16),
        parseInt(hex.slice(3, 5), 16),
        parseInt(hex.slice(5, 7), 16)];

      }
      const match = hex.match(/\d+/g);
      return match ?
      [parseInt(match[0]), parseInt(match[1]), parseInt(match[2])] :
      [255, 255, 255];
    };

    const interpolateColor = (color1, color2, t, opacity = 1) => {
      const rgb1 = hexToRgb(color1);
      const rgb2 = hexToRgb(color2);
      const r = Math.round(rgb1[0] + (rgb2[0] - rgb1[0]) * t);
      const g = Math.round(rgb1[1] + (rgb2[1] - rgb1[1]) * t);
      const b = Math.round(rgb1[2] + (rgb2[2] - rgb1[2]) * t);
      return `rgba(${r}, ${g}, ${b}, ${opacity})`;
    };

    const animate = timestamp => {
      if (!this.startTime) this.startTime = timestamp;

      if (!lastTime) lastTime = timestamp;
      const deltaTime = timestamp - lastTime;
      lastTime = timestamp;
      time += deltaTime * 0.001;

      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

      this.ctx.beginPath();
      this.ctx.arc(centerX, centerY, 3, 0, Math.PI * 2);
      const rgb = hexToRgb(colors.primary);
      this.ctx.fillStyle = `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.9)`;
      this.ctx.fill();

      dotRings.forEach((ring, ringIndex) => {
        for (let i = 0; i < ring.count; i++) {
          const angle = i / ring.count * Math.PI * 2;
          const pulseTime = time * 2 - ringIndex * 0.4;
          const radiusPulse =
          easeInOutSine((Math.sin(pulseTime) + 1) / 2) * 6 - 3;
          const x = centerX + Math.cos(angle) * (ring.radius + radiusPulse);
          const y = centerY + Math.sin(angle) * (ring.radius + radiusPulse);

          const opacityPhase = (Math.sin(pulseTime + i * 0.2) + 1) / 2;
          const opacityBase = 0.3 + easeInOutSine(opacityPhase) * 0.7;
          const highlightPhase = (Math.sin(pulseTime) + 1) / 2;
          const highlightIntensity = easeInOutCubic(highlightPhase);

          this.ctx.beginPath();
          this.ctx.arc(x, y, 2, 0, Math.PI * 2);
          const colorBlend = smoothstep(0.2, 0.8, highlightIntensity);
          this.ctx.fillStyle = interpolateColor(
          colors.primary,
          colors.accent,
          colorBlend,
          opacityBase);

          this.ctx.fill();
        }
      });

      if (timestamp - this.startTime >= this.duration) {
        this.complete();
        return;
      }

      this.animationId = requestAnimationFrame(animate);
    };

    this.animationId = requestAnimationFrame(animate);
  }

  complete() {
    if (this.animationId) {
      cancelAnimationFrame(this.animationId);
    }

    if (this.overlay) {
      this.overlay.style.opacity = "0";
      this.overlay.style.transition = "opacity 0.8s ease";
      setTimeout(() => {
        this.overlay?.remove();

        setTimeout(() => {
          const sliderWrapper = document.querySelector(".slider-wrapper");
          if (sliderWrapper) {
            sliderWrapper.classList.add("loaded");
          }
        }, 500);
      }, 800);
    }
  }}


// Initialize preloader
document.addEventListener("DOMContentLoaded", function () {
  const loadingManager = new SliderLoadingManager();
});

// ========================================
// VISUAL EFFECTS SLIDER CONFIGURATION
// ========================================

const SLIDER_CONFIG = {
  // Core settings
  settings: {
    // Timing settings
    transitionDuration: 2.5,
    autoSlideSpeed: 5000,
    // Current state
    currentEffect: "glass",
    currentEffectPreset: "Default",
    // Global settings that affect all effects
    globalIntensity: 1.0,
    speedMultiplier: 1.0,
    distortionStrength: 1.0,
    colorEnhancement: 1.0,
    // Effect-specific settings (will be overridden by presets)
    glassRefractionStrength: 1.0,
    glassChromaticAberration: 1.0,
    glassBubbleClarity: 1.0,
    glassEdgeGlow: 1.0,
    glassLiquidFlow: 1.0,
    frostIntensity: 1.5,
    frostCrystalSize: 1.0,
    frostIceCoverage: 1.0,
    frostTemperature: 1.0,
    frostTexture: 1.0,
    rippleFrequency: 25.0,
    rippleAmplitude: 0.08,
    rippleWaveSpeed: 1.0,
    rippleRippleCount: 1.0,
    rippleDecay: 1.0,
    plasmaIntensity: 1.2,
    plasmaSpeed: 0.8,
    plasmaEnergyIntensity: 0.4,
    plasmaContrastBoost: 0.3,
    plasmaTurbulence: 1.0,
    timeshiftDistortion: 1.6,
    timeshiftBlur: 1.5,
    timeshiftFlow: 1.4,
    timeshiftChromatic: 1.5,
    timeshiftTurbulence: 1.4 },

  // Effect-specific presets
  effectPresets: {
    glass: {
      Subtle: {
        glassRefractionStrength: 0.6,
        glassChromaticAberration: .........完整代码请登录后点击上方下载按钮下载查看

网友评论0