导读:本期聚焦于小伙伴创作的《CSS与D3.js结合实现跟随鼠标游动的小鱼动画完整教程》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《CSS与D3.js结合实现跟随鼠标游动的小鱼动画完整教程》有用,将其分享出去将是对创作者最好的鼓励。

如何使用CSS和D3实现小鱼游动的交互动画

在网页中实现生动的交互动画,常需要将样式控制与数据驱动能力结合。CSS负责流畅的视觉表现,D3.js则提供灵活的数学计算与事件响应。本文将演示如何利用这两者,创建一条在鼠标控制下自由游动的小鱼动画。

核心思路与原理

动画的本质是不断更新元素的位置与形态。在这套方案中,CSS用于定义小鱼的身体、鱼鳍、尾巴等部位的静态样式以及基础的摆动过渡效果。D3.js则承担计算角色,监听鼠标移动事件,实时计算鱼头朝向与身体各部位的偏移量,并通过修改CSS变量或直接更新DOM属性的方式来驱动动画。

关键点在于将小鱼的游动分解为两个层次:

  • 轨迹控制:鱼头跟随鼠标指针移动,身体其他部分按照固定比例延迟跟随,形成波浪式游动效果。
  • 形态变化:鱼鳍和尾巴通过CSS关键帧动画进行周期性的摆动,模拟真实鱼类的游泳姿态。

第一步:构建HTML结构

我们需要一个容器来承载小鱼,并在内部划分出鱼头、鱼身、鱼尾和鱼鳍等部分。每个部分使用独立的<div>或<svg>元素,便于CSS单独控制样式和D3单独操作属性。

<div id="aquarium">
  <div id="fish">
    <div class="fish-body">
      <div class="head"></div>
      <div class="fin top-fin"></div>
      <div class="fin bottom-fin"></div>
    </div>
    <div class="tail"></div>
  </div>
</div>

为了更精细地控制形状,我们可以在鱼身内部使用内联SVG绘制轮廓,或者直接使用CSS的border-radius组合出鱼形。这里采用纯CSS绘制,以降低依赖。

第二步:使用CSS绘制小鱼样式

鱼身的椭圆形状、鱼头的圆形、鱼鳍的三角形以及尾巴的分叉,都可以通过CSS实现。同时我们利用CSS自定义属性(CSS变量)来存储位置与角度数据,便于D3在运行时动态修改。

#aquarium {
  width: 100vw;
  height: 100vh;
  background: linear-gradient(180deg, #0a2a4a, #0e3a5c);
  position: relative;
  overflow: hidden;
  cursor: none;
}

#fish {
  position: absolute;
  width: 120px;
  height: 60px;
  top: var(--fish-y, 50%);
  left: var(--fish-x, 50%);
  transform: translate(-50%, -50%) rotate(var(--fish-angle, 0deg));
  transition: transform 0.15s ease-out;
}

.fish-body {
  width: 80px;
  height: 40px;
  background: radial-gradient(ellipse at 30% 50%, #ffaa44, #cc7722);
  border-radius: 50%;
  position: relative;
  margin-left: 20px;
}

.head {
  width: 22px;
  height: 22px;
  background: #ffcc66;
  border-radius: 50%;
  position: absolute;
  top: 9px;
  left: -6px;
  box-shadow: 2px 0 4px rgba(0,0,0,0.3);
}

.fin {
  width: 20px;
  height: 12px;
  border-radius: 50% 50% 0 0;
  position: absolute;
  animation: finWave 0.6s ease-in-out infinite alternate;
}

.top-fin {
  background: #ee8822;
  top: -10px;
  left: 30px;
  transform-origin: bottom center;
}

.bottom-fin {
  background: #dd7711;
  bottom: -8px;
  left: 26px;
  transform-origin: top center;
}

.tail {
  width: 30px;
  height: 18px;
  background: #cc7722;
  border-radius: 0 80% 80% 0 / 0 60% 60% 0;
  position: absolute;
  right: -18px;
  top: 11px;
  animation: tailWave 0.4s ease-in-out infinite alternate;
  transform-origin: left center;
}

@keyframes finWave {
  0% { transform: rotate(-15deg) scaleY(1); }
  100% { transform: rotate(15deg) scaleY(0.7); }
}

@keyframes tailWave {
  0% { transform: rotate(-10deg); }
  100% { transform: rotate(10deg); }
}

以上CSS定义了小鱼的基本形态和鱼鳍、尾巴的摆动动画。鱼的整体位置由--fish-x和--fish-y两个CSS变量控制,朝向由--fish-angle变量控制,这些变量将由D3在运行时更新。

第三步:使用D3.js实现交互逻辑

D3负责监听鼠标移动事件,计算鱼头与鼠标之间的夹角,并更新CSS变量。为了让游动更自然,我们加入了平滑跟随算法:鱼不会瞬间跳到鼠标位置,而是以一定的速度逐渐接近。

// 选择容器和小鱼元素
const aquarium = document.getElementById('aquarium');
const fish = document.getElementById('fish');

// 初始化鱼的位置(屏幕中央)
let currentX = window.innerWidth / 2;
let currentY = window.innerHeight / 2;

// 目标位置(鼠标位置)
let targetX = currentX;
let targetY = currentY;

// 跟随系数(0~1之间,越大跟随越快)
const followFactor = 0.08;

// 监听鼠标移动
aquarium.addEventListener('mousemove', function(event) {
  targetX = event.clientX;
  targetY = event.clientY;
});

// 更新函数,由D3的timer驱动
function updateFish() {
  // 计算当前位置与目标位置的差值
  const dx = targetX - currentX;
  const dy = targetY - currentY;
  
  // 如果距离很小,直接跳到目标点避免抖动
  const distance = Math.sqrt(dx * dx + dy * dy);
  if (distance < 1) {
    currentX = targetX;
    currentY = targetY;
  } else {
    // 渐进式靠近
    currentX += dx * followFactor;
    currentY += dy * followFactor;
  }
  
  // 计算朝向角度(弧度转角度)
  // 注意atan2返回的是弧度,需要转为度,并且CSS的rotate角度以顺时针为正
  let angle = Math.atan2(dy, dx) * (180 / Math.PI);
  
  // 更新CSS变量
  fish.style.setProperty('--fish-x', currentX + 'px');
  fish.style.setProperty('--fish-y', currentY + 'px');
  fish.style.setProperty('--fish-angle', angle + 'deg');
  
  // 继续下一帧
  requestAnimationFrame(updateFish);
}

// 启动动画循环
updateFish();

上面的代码使用原生requestAnimationFrame驱动动画循环,让鱼平滑地跟随鼠标移动,并始终面向鼠标方向。为了更丰富地使用D3特性,我们可以加入比例尺来映射鼠标位置与游动速度之间的关系。

第四步:引入D3的比例尺与插值增强效果

使用D3的scaleLinear创建比例尺,将鼠标距离中心的偏移映射为游动速度,从而影响鱼鳍摆动的频率。同时利用d3.interpolate实现更平滑的颜色或形状过渡。

// 使用D3比例尺将鼠标距离映射为摆动速度倍数
const speedScale = d3.scaleLinear()
  .domain([0, 400])  // 鼠标距离范围(像素)
  .range([1, 2.5]);  // 速度倍数范围

// 监听鼠标移动并更新目标位置
aquarium.addEventListener('mousemove', function(event) {
  targetX = event.clientX;
  targetY = event.clientY;
  
  // 计算鼠标与屏幕中心的距离
  const centerX = window.innerWidth / 2;
  const centerY = window.innerHeight / 2;
  const dist = Math.sqrt(
    Math.pow(event.clientX - centerX, 2) + 
    Math.pow(event.clientY - centerY, 2)
  );
  
  // 根据距离调整鱼鳍摆动动画的速度
  const speedFactor = speedScale(dist);
  const fins = document.querySelectorAll('.fin');
  fins.forEach(function(fin) {
    fin.style.animationDuration = (0.6 / speedFactor) + 's';
  });
  const tail = document.querySelector('.tail');
  tail.style.animationDuration = (0.4 / speedFactor) + 's';
});

// 其余更新逻辑与上文相同

这样一来,当鼠标离鱼越远,鱼鳍和尾巴摆动越快,模拟出鱼加速游动的视觉效果。

第五步:增加水体背景与气泡粒子

为了让场景更生动,可以使用D3在背景中生成随机气泡粒子,缓慢上升,增加沉浸感。

// 生成气泡粒子
const bubbleCount = 30;
const aquariumEl = d3.select('#aquarium');

for (let i = 0; i < bubbleCount; i++) {
  aquariumEl.append('div')
    .attr('class', 'bubble')
    .style('left', Math.random() * 100 + '%')
    .style('bottom', '-20px')
    .style('width', (8 + Math.random() * 16) + 'px')
    .style('height', function() {
      return this.style.width;
    })
    .style('animation-duration', (4 + Math.random() * 6) + 's')
    .style('animation-delay', (Math.random() * 8) + 's');
}
.bubble {
  position: absolute;
  background: rgba(255, 255, 255, 0.15);
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.3);
  animation: bubbleRise linear infinite;
  pointer-events: none;
}

@keyframes bubbleRise {
  0% {
    transform: translateY(0) scale(0.8);
    opacity: 0.3;
  }
  50% {
    opacity: 0.6;
  }
  100% {
    transform: translateY(-110vh) scale(1.1);
    opacity: 0;
  }
}

效果预览与调试建议

将以上HTML、CSS和JavaScript代码整合到一个文件中,用浏览器打开即可看到一条金黄色的小鱼在深蓝色水族箱中跟随鼠标游动。鼠标移动越快,鱼鳍摆动越急促,尾巴摇摆越频繁,整体游动姿态十分自然。

调试时需要注意以下几点:

  • 确保CSS变量在D3更新前已正确定义初始值,避免鱼出现位置异常。
  • 跟随系数followFactor建议在0.05到0.15之间调整,数值越大鱼跟随越紧,但会显得生硬。
  • 鱼鳍和尾巴的动画时间不宜过短或过长,0.4~0.8秒是一个合理的范围。

结语

通过CSS与D3的配合,我们实现了从视觉呈现到交互逻辑的完整闭环。CSS负责精致的外观与基础动效,D3则承担数据处理与事件驱动的任务,两者相辅相成。这套模式可以扩展至更多生物模拟、游戏角色控制等场景,只需替换对应的样式与运动算法即可。

CSS动画D3_js交互鼠标跟随动画网页动效前端开发

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。