液态交互效果网页开发--源自鸿蒙5以及iOS26的灵感

发布于:2025-06-30 ⋅ 阅读:(18) ⋅ 点赞:(0)

首先先来看看最终展示效果

当鼠标靠近“开始探索”的按钮的时候,按钮放大并有微弱光效

鼠标靠近之前会给视窗添加一层接近背景的朦胧感,当鼠标放在视窗上朦胧感消失

技术不复杂,这个网页主要是使用了以下关键技术:

  • HTML5 语义化标签构建页面结构
  • Tailwind CSS v3 实现响应式设计与样式
  • JavaScript 结合 Canvas API 创建液态动画效果
  • Font Awesome 图标增强视觉表现力

核心样式与配色方案

tailwind.config = {
  theme: {
    extend: {
      colors: {
        primary: '#3B82F6',   // 主色调-蓝色
        secondary: '#8B5CF6', // 次色调-紫色
        accent: '#EC4899',    // 强调色-粉色
        dark: '#1E293B',      // 深色背景
      },
      fontFamily: {
        inter: ['Inter', 'sans-serif'],
      },
    },
  }
}

自定义工具类与动画效果

接下来是自定义的工具类和动画,这些是实现液态效果的关键:

@layer utilities {
  .content-auto {
    content-visibility: auto;
  }
  .liquid-blob {
    filter: url(#liquid);
  }
  .text-shadow {
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  }
  .animate-float {
    animation: float 6s ease-in-out infinite;
  }
  .animate-pulse-slow {
    animation: pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  }
}

@keyframes float {
  0% { transform: translateY(0px); }
  50% { transform: translateY(-20px); }
  100% { transform: translateY(0px); }
}

这里定义了几个关键类:

  • .liquid-blob 使用了我在后面定义的 SVG 滤镜,实现液态模糊效果
  • .animate-float 创建了元素上下浮动的动画效果
  • 还有文本阴影和内容可见性优化等实用工具类

页面结构解析

整个页面分为几个主要部分:

  1. 液态效果容器(背景动画)
  2. 拖尾效果容器(鼠标交互反馈)
  3. 内容区域(包含导航、英雄区、特点展示等)
导航栏设计

导航栏采用了简洁现代的设计,在深色背景上使用渐变文字突出品牌名称:

<nav class="flex justify-between items-center mb-20">
  <div class="text-2xl font-bold tracking-tight">
    <span class="text-primary">液态</span><span class="text-secondary">交互</span>
  </div>
  <div class="hidden md:flex space-x-8">
    <a href="#" class="hover:text-primary transition-colors duration-300">首页</a>
    <a href="#" class="hover:text-primary transition-colors duration-300">作品</a>
    <a href="#" class="hover:text-primary transition-colors duration-300">关于</a>
    <a href="#" class="hover:text-primary transition-colors duration-300">联系</a>
  </div>
  <button class="md:hidden text-2xl">
    <i class="fa fa-bars"></i>
  </button>
</nav>

为了更好的展示页面的视觉焦点,使用了动态字体大小和渐变按钮:

<section class="text-center mb-24">
  <h1 class="text-[clamp(2.5rem,5vw,4rem)] font-bold mb-6 leading-tight text-shadow">
    探索<span class="text-primary">液态</span>与<span class="text-secondary">交互</span>的完美融合
  </h1>
  <p class="text-lg md:text-xl text-gray-300 max-w-3xl mx-auto mb-10">
    当鼠标划过屏幕,见证流动的视觉盛宴。每一次移动都创造独特的液态轨迹...
  </p>
  <button class="bg-gradient-to-r from-primary to-secondary px-8 py-3 rounded-full font-medium hover:shadow-lg hover:shadow-primary/20 transition-all duration-300 transform hover:scale-105">
    开始探索
  </button>
</section>

注意text-[clamp(2.5rem,5vw,4rem)]这个动态字体大小设置,它会根据视口宽度自动调整标题大小。

液态背景效果实现

现在进入最核心的部分 —— 液态背景效果的实现。这部分使用 Canvas API 创建了流动的液态 blob 效果。

// 液态背景效果
document.addEventListener('DOMContentLoaded', () => {
  // 创建液态背景
  const liquidContainer = document.getElementById('liquid-container');
  const liquidCanvas = document.createElement('canvas');
  liquidCanvas.id = 'liquid-canvas';
  liquidCanvas.className = 'absolute inset-0';
  liquidContainer.appendChild(liquidCanvas);
  
  const ctx = liquidCanvas.getContext('2d');
  
  // 设置Canvas尺寸
  function resizeCanvas() {
    liquidCanvas.width = window.innerWidth;
    liquidCanvas.height = window.innerHeight;
  }
  
  resizeCanvas();
  window.addEventListener('resize', resizeCanvas);

首先我们创建了 Canvas 元素并设置其尺寸随窗口大小变化,这是实现响应式液态效果的基础。

接下来是液态 blob 的创建和动画逻辑:

  // 液态效果参数
  const blobs = [];
  const blobCount = 8;
  const colors = [
    'rgba(59, 130, 246, 0.5)', // primary
    'rgba(139, 92, 246, 0.5)', // secondary
    'rgba(236, 72, 153, 0.5)'  // accent
  ];
  
  // 创建液滴
  for (let i = 0; i < blobCount; i++) {
    blobs.push({
      x: Math.random() * liquidCanvas.width,
      y: Math.random() * liquidCanvas.height,
      radius: 50 + Math.random() * 100,
      speedX: (Math.random() - 0.5) * 0.5,
      speedY: (Math.random() - 0.5) * 0.5,
      color: colors[Math.floor(Math.random() * colors.length)],
      rotation: Math.random() * Math.PI * 2,
      rotationSpeed: (Math.random() - 0.5) * 0.01
    });
  }

这里我创建了 8 个液态 blob,每个都有随机的位置、大小、移动速度和颜色。注意speedXspeedY使用了(Math.random() - 0.5)来产生正负值,使 blob 可以在两个方向上移动。

动画循环是实现液态效果的核心:

  // 动画循环
  function animate() {
    ctx.clearRect(0, 0, liquidCanvas.width, liquidCanvas.height);
    
    // 绘制背景渐变
    const bgGradient = ctx.createLinearGradient(0, 0, liquidCanvas.width, liquidCanvas.height);
    bgGradient.addColorStop(0, '#1E293B');
    bgGradient.addColorStop(1, '#0F172A');
    ctx.fillStyle = bgGradient;
    ctx.fillRect(0, 0, liquidCanvas.width, liquidCanvas.height);
    
    // 绘制所有液滴
    ctx.save();
    ctx.filter = 'blur(40px)';
    
    blobs.forEach(blob => {
      // 更新位置和旋转
      blob.x += blob.speedX;
      blob.y += blob.speedY;
      blob.rotation += blob.rotationSpeed;
      
      // 边界检查
      if (blob.x < -blob.radius) blob.x = liquidCanvas.width + blob.radius;
      if (blob.x > liquidCanvas.width + blob.radius) blob.x = -blob.radius;
      if (blob.y < -blob.radius) blob.y = liquidCanvas.height + blob.radius;
      if (blob.y > liquidCanvas.height + blob.radius) blob.y = -blob.radius;
      
      // 绘制液滴
      ctx.beginPath();
      ctx.fillStyle = blob.color;
      
      // 创建一个不规则形状
      const points = 8;
      ctx.moveTo(
        blob.x + blob.radius * Math.cos(blob.rotation),
        blob.y + blob.radius * Math.sin(blob.rotation)
      );
      
      for (let i = 1; i < points; i++) {
        const angle = blob.rotation + (i * Math.PI * 2) / points;
        const distance = blob.radius * (0.8 + 0.4 * Math.sin(i * 1.5 + blob.rotation * 0.5));
        
        ctx.lineTo(
          blob.x + distance * Math.cos(angle),
          blob.y + distance * Math.sin(angle)
        );
      }
      
      ctx.closePath();
      ctx.fill();
    });
    
    ctx.restore();
    
    requestAnimationFrame(animate);
  }
  
  animate();

鼠标拖尾交互效果

接下来是鼠标交互的拖尾效果,这是提升用户体验的关键部分:

  // 鼠标拖尾效果
  const trailContainer = document.getElementById('trail-container');
  const trailElements = [];
  const maxTrailElements = 20;
  
  // 创建拖尾元素
  for (let i = 0; i < maxTrailElements; i++) {
    const trail = document.createElement('div');
    trail.className = 'absolute rounded-full liquid-blob';
    trail.style.width = `${10 + i * 1.5}px`;
    trail.style.height = `${10 + i * 1.5}px`;
    trail.style.opacity = '0';
    trail.style.transition = `opacity 0.5s ease, transform 0.5s ease`;
    trail.style.transform = 'translate(-50%, -50%) scale(0)';
    
    // 随机颜色
    const color = colors[Math.floor(Math.random() * colors.length)];
    trail.style.backgroundColor = color.replace('0.5', '0.8');
    
    trailContainer.appendChild(trail);
    trailElements.push(trail);
  }

这里我们创建了 20 个圆形元素作为拖尾,每个都有不同的大小和随机颜色。通过 CSS 过渡效果实现淡入淡出和缩放动画。

当然大家可以在我代码的基础上进一步优化,比如说,可以调整blobCount参数改变背景中液态 blob 的数量或者修改拖尾元素的数量和动画参数以获得不同的交互效果,当然又或者去扩展颜色数组以添加更多颜色选项。

完整源代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>液态交互效果网页</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#3B82F6',
            secondary: '#8B5CF6',
            accent: '#EC4899',
            dark: '#1E293B',
          },
          fontFamily: {
            inter: ['Inter', 'sans-serif'],
          },
        },
      }
    }
  </script>
  <style type="text/tailwindcss">
    @layer utilities {
      .content-auto {
        content-visibility: auto;
      }
      .liquid-blob {
        filter: url(#liquid);
      }
      .text-shadow {
        text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
      }
      .animate-float {
        animation: float 6s ease-in-out infinite;
      }
      .animate-pulse-slow {
        animation: pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
      }
    }

    @keyframes float {
      0% { transform: translateY(0px); }
      50% { transform: translateY(-20px); }
      100% { transform: translateY(0px); }
    }
  </style>
</head>
<body class="font-inter bg-gradient-to-br from-dark to-gray-900 min-h-screen text-white overflow-x-hidden">
  <!-- 液态效果容器 -->
  <div id="liquid-container" class="fixed inset-0 z-0"></div>
  
  <!-- 拖尾效果容器 -->
  <div id="trail-container" class="fixed inset-0 pointer-events-none z-10"></div>
  
  <!-- 内容区域 -->
  <main class="relative z-20 px-6 py-12 max-w-7xl mx-auto">
    <!-- 导航栏 -->
    <nav class="flex justify-between items-center mb-20">
      <div class="text-2xl font-bold tracking-tight">
        <span class="text-primary">液态</span><span class="text-secondary">交互</span>
      </div>
      <div class="hidden md:flex space-x-8">
        <a href="#" class="hover:text-primary transition-colors duration-300">首页</a>
        <a href="#" class="hover:text-primary transition-colors duration-300">作品</a>
        <a href="#" class="hover:text-primary transition-colors duration-300">关于</a>
        <a href="#" class="hover:text-primary transition-colors duration-300">联系</a>
      </div>
      <button class="md:hidden text-2xl">
        <i class="fa fa-bars"></i>
      </button>
    </nav>
    
    <!-- 英雄区域 -->
    <section class="text-center mb-24">
      <h1 class="text-[clamp(2.5rem,5vw,4rem)] font-bold mb-6 leading-tight text-shadow">
        探索<span class="text-primary">液态</span>与<span class="text-secondary">交互</span>的完美融合
      </h1>
      <p class="text-lg md:text-xl text-gray-300 max-w-3xl mx-auto mb-10">
        当鼠标划过屏幕,见证流动的视觉盛宴。每一次移动都创造独特的液态轨迹,感受数字艺术与交互设计的奇妙结合。
      </p>
      <button class="bg-gradient-to-r from-primary to-secondary px-8 py-3 rounded-full font-medium hover:shadow-lg hover:shadow-primary/20 transition-all duration-300 transform hover:scale-105">
        开始探索
      </button>
    </section>
    
    <!-- 特点展示 -->
    <section class="grid grid-cols-1 md:grid-cols-3 gap-8 mb-24">
      <div class="bg-gray-800/50 backdrop-blur-md p-8 rounded-2xl border border-gray-700/50 hover:border-primary/30 transition-all duration-300 hover:shadow-xl hover:shadow-primary/5 group">
        <div class="w-16 h-16 bg-primary/20 rounded-full flex items-center justify-center mb-6 group-hover:bg-primary/30 transition-colors duration-300">
          <i class="fa fa-tint text-primary text-2xl"></i>
        </div>
        <h3 class="text-xl font-bold mb-3">流畅液态效果</h3>
        <p class="text-gray-400">基于WebGL的高性能液态渲染,实现丝滑流畅的视觉体验。</p>
      </div>
      
      <div class="bg-gray-800/50 backdrop-blur-md p-8 rounded-2xl border border-gray-700/50 hover:border-secondary/30 transition-all duration-300 hover:shadow-xl hover:shadow-secondary/5 group">
        <div class="w-16 h-16 bg-secondary/20 rounded-full flex items-center justify-center mb-6 group-hover:bg-secondary/30 transition-colors duration-300">
          <i class="fa fa-mouse-pointer text-secondary text-2xl"></i>
        </div>
        <h3 class="text-xl font-bold mb-3">鼠标跟随交互</h3>
        <p class="text-gray-400">智能算法分析鼠标轨迹,创造自然而富有创意的拖尾效果。</p>
      </div>
      
      <div class="bg-gray-800/50 backdrop-blur-md p-8 rounded-2xl border border-gray-700/50 hover:border-accent/30 transition-all duration-300 hover:shadow-xl hover:shadow-accent/5 group">
        <div class="w-16 h-16 bg-accent/20 rounded-full flex items-center justify-center mb-6 group-hover:bg-accent/30 transition-colors duration-300">
          <i class="fa fa-paint-brush text-accent text-2xl"></i>
        </div>
        <h3 class="text-xl font-bold mb-3">色彩动态融合</h3>
        <p class="text-gray-400">多种渐变色系随鼠标移动动态混合,创造无限可能的视觉效果。</p>
      </div>
    </section>
    
    <!-- 示例展示 -->
    <section class="mb-24">
      <h2 class="text-3xl font-bold mb-12 text-center">互动示例</h2>
      <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
        <div class="bg-gray-800/30 backdrop-blur-sm rounded-2xl overflow-hidden group">
          <div class="h-64 relative overflow-hidden">
            <div class="absolute inset-0 bg-gradient-to-r from-primary/30 to-secondary/30"></div>
            <img src="https://picsum.photos/seed/liquid1/800/600" alt="液态交互效果示例" class="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110">
          </div>
          <div class="p-6">
            <h3 class="text-xl font-bold mb-2">流体粒子交互</h3>
            <p class="text-gray-400">体验粒子系统如何响应鼠标移动,创造流动的视觉效果。</p>
          </div>
        </div>
        
        <div class="bg-gray-800/30 backdrop-blur-sm rounded-2xl overflow-hidden group">
          <div class="h-64 relative overflow-hidden">
            <div class="absolute inset-0 bg-gradient-to-r from-secondary/30 to-accent/30"></div>
            <img src="https://picsum.photos/seed/liquid2/800/600" alt="液态色彩混合示例" class="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110">
          </div>
          <div class="p-6">
            <h3 class="text-xl font-bold mb-2">色彩融合艺术</h3>
            <p class="text-gray-400">观察不同颜色如何在鼠标移动时自然混合,形成独特的视觉艺术。</p>
          </div>
        </div>
      </div>
    </section>
    
    <!-- 页脚 -->
    <footer class="pt-12 pb-6 border-t border-gray-800">
      <div class="flex flex-col md:flex-row justify-between items-center">
        <div class="mb-6 md:mb-0">
          <div class="text-xl font-bold mb-2">
            <span class="text-primary">液态</span><span class="text-secondary">交互</span>
          </div>
          <p class="text-gray-500 text-sm">探索数字世界的流体之美</p>
        </div>
        
        <div class="flex space-x-6 mb-6 md:mb-0">
          <a href="#" class="text-gray-400 hover:text-primary transition-colors duration-300">
            <i class="fa fa-twitter"></i>
          </a>
          <a href="#" class="text-gray-400 hover:text-primary transition-colors duration-300">
            <i class="fa fa-instagram"></i>
          </a>
          <a href="#" class="text-gray-400 hover:text-primary transition-colors duration-300">
            <i class="fa fa-dribbble"></i>
          </a>
          <a href="#" class="text-gray-400 hover:text-primary transition-colors duration-300">
            <i class="fa fa-github"></i>
          </a>
        </div>
        
        <div>
          <p class="text-gray-500 text-sm">&copy; 2025 液态交互. 保留所有权利.</p>
        </div>
      </div>
    </footer>
  </main>
  
  <!-- 液态效果滤镜 -->
  <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
    <filter id="liquid">
      <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
      <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -7" result="liquid" />
      <feComposite in="SourceGraphic" in2="liquid" operator="over" />
    </filter>
  </svg>

  <script>
    // 液态背景效果
    document.addEventListener('DOMContentLoaded', () => {
      // 创建液态背景
      const liquidContainer = document.getElementById('liquid-container');
      const liquidCanvas = document.createElement('canvas');
      liquidCanvas.id = 'liquid-canvas';
      liquidCanvas.className = 'absolute inset-0';
      liquidContainer.appendChild(liquidCanvas);
      
      const ctx = liquidCanvas.getContext('2d');
      
      // 设置Canvas尺寸
      function resizeCanvas() {
        liquidCanvas.width = window.innerWidth;
        liquidCanvas.height = window.innerHeight;
      }
      
      resizeCanvas();
      window.addEventListener('resize', resizeCanvas);
      
      // 液态效果参数
      const blobs = [];
      const blobCount = 8;
      const colors = [
        'rgba(59, 130, 246, 0.5)', // primary
        'rgba(139, 92, 246, 0.5)', // secondary
        'rgba(236, 72, 153, 0.5)'  // accent
      ];
      
      // 创建液滴
      for (let i = 0; i < blobCount; i++) {
        blobs.push({
          x: Math.random() * liquidCanvas.width,
          y: Math.random() * liquidCanvas.height,
          radius: 50 + Math.random() * 100,
          speedX: (Math.random() - 0.5) * 0.5,
          speedY: (Math.random() - 0.5) * 0.5,
          color: colors[Math.floor(Math.random() * colors.length)],
          rotation: Math.random() * Math.PI * 2,
          rotationSpeed: (Math.random() - 0.5) * 0.01
        });
      }
      
      // 动画循环
      function animate() {
        ctx.clearRect(0, 0, liquidCanvas.width, liquidCanvas.height);
        
        // 绘制背景渐变
        const bgGradient = ctx.createLinearGradient(0, 0, liquidCanvas.width, liquidCanvas.height);
        bgGradient.addColorStop(0, '#1E293B');
        bgGradient.addColorStop(1, '#0F172A');
        ctx.fillStyle = bgGradient;
        ctx.fillRect(0, 0, liquidCanvas.width, liquidCanvas.height);
        
        // 绘制所有液滴
        ctx.save();
        ctx.filter = 'blur(40px)';
        
        blobs.forEach(blob => {
          // 更新位置和旋转
          blob.x += blob.speedX;
          blob.y += blob.speedY;
          blob.rotation += blob.rotationSpeed;
          
          // 边界检查
          if (blob.x < -blob.radius) blob.x = liquidCanvas.width + blob.radius;
          if (blob.x > liquidCanvas.width + blob.radius) blob.x = -blob.radius;
          if (blob.y < -blob.radius) blob.y = liquidCanvas.height + blob.radius;
          if (blob.y > liquidCanvas.height + blob.radius) blob.y = -blob.radius;
          
          // 绘制液滴
          ctx.beginPath();
          ctx.fillStyle = blob.color;
          
          // 创建一个不规则形状
          const points = 8;
          ctx.moveTo(
            blob.x + blob.radius * Math.cos(blob.rotation),
            blob.y + blob.radius * Math.sin(blob.rotation)
          );
          
          for (let i = 1; i < points; i++) {
            const angle = blob.rotation + (i * Math.PI * 2) / points;
            const distance = blob.radius * (0.8 + 0.4 * Math.sin(i * 1.5 + blob.rotation * 0.5));
            
            ctx.lineTo(
              blob.x + distance * Math.cos(angle),
              blob.y + distance * Math.sin(angle)
            );
          }
          
          ctx.closePath();
          ctx.fill();
        });
        
        ctx.restore();
        
        requestAnimationFrame(animate);
      }
      
      animate();
      
      // 鼠标拖尾效果
      const trailContainer = document.getElementById('trail-container');
      const trailElements = [];
      const maxTrailElements = 20;
      
      // 创建拖尾元素
      for (let i = 0; i < maxTrailElements; i++) {
        const trail = document.createElement('div');
        trail.className = 'absolute rounded-full liquid-blob';
        trail.style.width = `${10 + i * 1.5}px`;
        trail.style.height = `${10 + i * 1.5}px`;
        trail.style.opacity = '0';
        trail.style.transition = `opacity 0.5s ease, transform 0.5s ease`;
        trail.style.transform = 'translate(-50%, -50%) scale(0)';
        
        // 随机颜色
        const color = colors[Math.floor(Math.random() * colors.length)];
        trail.style.backgroundColor = color.replace('0.5', '0.8');
        
        trailContainer.appendChild(trail);
        trailElements.push(trail);
      }
      
      // 鼠标移动事件
      let lastX = 0;
      let lastY = 0;
      
      document.addEventListener('mousemove', (e) => {
        const x = e.clientX;
        const y = e.clientY;
        
        // 计算移动速度
        const speed = Math.sqrt(
          Math.pow(x - lastX, 2) + Math.pow(y - lastY, 2)
        );
        
        lastX = x;
        lastY = y;
        
        // 更新拖尾元素
        trailElements.forEach((trail, index) => {
          const delay = index * 0.05;
          
          setTimeout(() => {
            trail.style.left = `${x}px`;
            trail.style.top = `${y}px`;
            trail.style.opacity = '1';
            trail.style.transform = `translate(-50%, -50%) scale(${1 - index * 0.05})`;
            
            // 淡出效果
            setTimeout(() => {
              trail.style.opacity = '0';
              trail.style.transform = 'translate(-50%, -50%) scale(0)';
            }, 300);
          }, delay * 100);
        });
      });
      
      // 触摸设备支持
      document.addEventListener('touchmove', (e) => {
        if (e.touches.length > 0) {
          const touch = e.touches[0];
          const x = touch.clientX;
          const y = touch.clientY;
          
          // 模拟鼠标移动事件
          const mouseEvent = new MouseEvent('mousemove', {
            clientX: x,
            clientY: y
          });
          
          document.dispatchEvent(mouseEvent);
          
          // 防止页面滚动
          e.preventDefault();
        }
      }, { passive: false });
    });
  </script>
</body>
</html>


网站公告

今日签到

点亮在社区的每一天
去签到