You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中SVG clip-path缩放匹配问题:水罐动画波形裁剪异常

解决React中水罐SVG clip-path裁剪波形错位/消失问题

问题核心

使用SVG定义的水罐路径作为clip-path裁剪动画波形时,裁剪区域与SVG图标尺寸不匹配导致错位;添加clipPathUnits="objectBoundingBox"后裁剪直接消失,调整viewBox等属性无效。

解决方案

1. 统一坐标空间与定位

保留默认的userSpaceOnUse坐标系统(与SVG viewBox坐标一致),将SVG和波形容器设置为相同尺寸并重叠定位,确保裁剪路径与容器完全对应。

2. 修改后的React组件代码

import styles from "./WaterTankSmall.module.css";

const waterLevel = 50;

const WaterTankSmall = () => {
  return (
    <div className={styles.container}>
      {/* SVG */}
      <svg
        className={styles.svgIcon}
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 66 82.5"
        preserveAspectRatio="xMidYMid meet"
      >
        <defs>
          <clipPath id="waterTankClip">
            <path d="M52.6 47V25H13.4v22.4h39.2V47zM13.5 23h39c-.6-5.5-4.8-9.9-10.1-10.9V3h1.9c.6 0 1-.4 1-1s-.4-1-1-1H21.7c-.6 0-1 .4-1 1s.4 1 1 1h1.7v9.2c-5.2 1.1-9.3 5.4-9.9 10.8zM25.4 3h14.9v9h-6.4V8.3h2.2c.6 0 1-.4 1-1s-.4-1-1-1h-6.5c-.6 0-1 .4-1 1s.4 1 1 1H32V12h-6.6V3zM52.4 49.4H13.6c1 5.1 5.2 9.1 10.4 9.9l-2.5 4.1c-.2.3-.2.7 0 1 .2.3.5.5.9.5h21.2c.4 0 .7-.2.9-.5.2-.3.2-.7 0-1l-2.5-4c5.2-.8 9.3-4.8 10.4-10z" />
          </clipPath>
        </defs>

        <path
          d="M52.6 47V25H13.4v22.4h39.2V47zM13.5 23h39c-.6-5.5-4.8-9.9-10.1-10.9V3h1.9c.6 0 1-.4 1-1s-.4-1-1-1H21.7c-.6 0-1 .4-1 1s.4 1 1 1h1.7v9.2c-5.2 1.1-9.3 5.4-9.9 10.8zM25.4 3h14.9v9h-6.4V8.3h2.2c.6 0 1-.4 1-1s-.4-1-1-1h-6.5c-.6 0-1 .4-1 1s.4 1 1 1H32V12h-6.6V3zM52.4 49.4H13.6c1 5.1 5.2 9.1 10.4 9.9l-2.5 4.1c-.2.3-.2.7 0 1 .2.3.5.5.9.5h21.2c.4 0 .7-.2.9-.5.2-.3.2-.7 0-1l-2.5-4c5.2-.8 9.3-4.8 10.4-10z"
          className={styles.tankOutline}
        />
      </svg>

      {/* wave container*/}
      <div
        className={styles.waveContainer}
        style={{
          clipPath: "url(#waterTankClip)",
          WebkitClipPath: "url(#waterTankClip)",
        }}
      >
        {[...Array(4)].map((_, i) => (
          <div
            key={i}
            className={`${styles.wave} ${styles[`wave${i + 1}`]}`}
            style={{
              height: `${waterLevel * 2}%`,
            }}
          ></div>
        ))}
        <div className={styles.waterLevelText}>{`${waterLevel}%`}</div>
      </div>
    </div>
  );
};

export default WaterTankSmall;

3. 更新后的样式文件

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #f0f8ff; 
}

.svgIcon {
  width: 500px;
  height: 500px;
  fill: none;
  stroke-width: 1;
  stroke: #1e90ff;
  position: absolute;
  pointer-events: none;
}

.waveContainer {
  position: absolute;
  width: 500px;
  height: 500px;
  bottom: 0;
}

.wave {
  position: absolute;
  bottom: 0;
  left: -100%;
  width: 5000px; 
  height: 2500px; 
  background: linear-gradient(to bottom, #87ceeb, #1e90ff);
  clip-path: polygon(
    0% 50%,
    10% 45%,
    20% 50%,
    30% 55%,
    40% 50%,
    50% 45%,
    60% 50%,
    70% 55%,
    80% 50%,
    90% 45%,
    100% 50%,
    100% 100%,
    0% 100%
  );
  z-index: 0;
}

.wave1 {
  background: linear-gradient(to bottom, #87ceeb, #1e90ff);
  opacity: 0.7;
  animation: wave1-animation 6s infinite ease-in-out;
}

.wave2 {
  background: linear-gradient(
    to bottom,
    rgba(135, 206, 235, 0.5),
    rgba(30, 144, 255, 0.5)
  );
  opacity: 0.5;
  animation: wave2-animation 8s infinite ease-in-out;
}

.wave3 {
  background: linear-gradient(
    to bottom,
    rgba(135, 206, 235, 0.4),
    rgba(30, 144, 255, 0.4)
  );
  opacity: 0.3;
  animation: wave3-animation 10s infinite ease-in-out;
}

.wave4 {
  background: linear-gradient(
    to bottom,
    rgba(135, 206, 235, 0.6),
    rgba(30, 144, 255, 0.6)
  );
  opacity: 0.4;
  animation: wave4-animation 12s infinite ease-in-out;
}

/* Wave animation*/
@keyframes wave1-animation {
  0% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(-30%);
  }
  100% {
    transform: translateX(0);
  }
}

@keyframes wave2-animation {
  0% {
    transform: translateX(-25%);
  }
  50% {
    transform: translateX(25%);
  }
  100% {
    transform: translateX(-25%);
  }
}

@keyframes wave3-animation {
  0% {
    transform: translateX(-15%);
  }
  50% {
    transform: translateX(15%);
  }
  100% {
    transform: translateX(-15%);
  }
}

@keyframes wave4-animation {
  0% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(-20%);
  }
  100% {
    transform: translateX(0);
  }
}

关键修改说明

  • 移除无效的#waterTankClip CSS样式(SVG内部元素无法通过CSS设置宽高)
  • 将SVG与波形容器设为绝对定位,尺寸统一为500x500px,确保裁剪区域完全对齐
  • 给SVG添加pointer-events: none,避免遮挡波形交互
  • 恢复wave元素的clip-path定义(原代码中被注释)
  • 移除无效的maskContentUnits属性

内容的提问来源于stack exchange,提问作者hyunji an

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:04:55