在我的React项目中,我有一个包含水平线(路径)的SVG,当我在每个路径上悬停鼠标时,我想要启动波浪动画,该动画从悬停的点开始,连续结束,直到路径线的末端.

默认情况下,我使用振动css动画.我想用波动代替振动

我对此一无所知.我不喜欢SVG.

我想要这样的GIF.

enter image description here

我的Reaction组件

"use client";
import { useCallback } from "react";
import "./styles.css";
const SongPlayer = () => {
  const soundFontUrl = "/sounds/guitar/";
  const playNote = useCallback((note: string) => {
    const audio = new Audio(soundFontUrl + note.trim() + ".mp3");
    audio.play();
  }, []);

  const handleMouseOver = (note: string, id: string) => {
    playNote(note);
    const el = document.getElementById(id);
    el?.classList.add("vibrating");

    setTimeout(() => {
      el?.classList.remove("vibrating");
    }, 1000);
  };

  return (
    <div className="w-full mt-[44px]">
      <div className="w-full flex justify-center items-center">
        <svg
          id="guitar"
          className="guitar"
          width="1700"
          height="324"
          viewBox="0 0 1441 324"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        >
    
          <path
            id="g-one"
            onMouseOver={() => handleMouseOver("D3", "g-one")}
            d="M1075.88 242.167C1059.69 248.627 1044.41 255.881 1021.79 251.862C1020.83 251.69 1019.91 251.509 1019.03 251.319M1019.03 251.319C987.538 244.521 1010.27 226.472 1021.79 232.056C1028.69 235.4 1025.2 244.393 1019.03 251.319ZM1019.03 251.319C1014.6 256.283 1008.47 258.373 993.68 258.373C954.721 258.373 905.598 232.907 799 235.49L0 235.49"
            stroke="#A39D92"
            strokeWidth="1.5"
          />
          <path
            id="g-two"
            onMouseOver={() => handleMouseOver("D5", "g-two")}
            d="M0 275H1089.5"
            stroke="#A39D92"
            strokeWidth="1.5"
          />
          <path
            id="g-three"
            onMouseOver={() => handleMouseOver("C4", "g-three")}
            d="M0 164.5H1026"
            stroke="#A39D92"
            strokeWidth="1.5"
          />
          <path
            id="g-four"
            onMouseOver={() => handleMouseOver("C2", "g-four")}
            d="M0 125H1057.5"
            stroke="#A39D92"
            strokeWidth="1.5"
          />
          <path
            id="g-five"
            onMouseOver={() => handleMouseOver("F4", "g-five")}
            d="M0 54H1151"
            stroke="#A39D92"
            strokeWidth="1.5"
          />
          <path
            id="g-six"
            onMouseOver={() => handleMouseOver("F2", "g-six")}
            d="M0 14.5H1164.5"
            stroke="#A39D92"
            strokeWidth="1.5"
          />
        </svg>
      </div>
    </div>
  );
};

export default SongPlayer;

推荐答案

下面是一个try (使用D3库):

const svg = d3.select('svg');

const totalWidth = 300;
const waveLength = 30;
const maxMagnitude = 40;
const delta = 5;
const maxIndex = 22;

const line = d3.line().curve(d3.curveMonotoneX);

const nextStep = (handle, points, y, index) => {
  const pArray = points.map(p => [p.x, p.y]);
    
  points.forEach(p => {
        if (p.m > 0) {
        p.m -= 2;
        if (p.y > y) 
            p.y = y - p.m;
        else
            p.y = y + p.m;
      }
  });
  if (index < maxIndex) {
    const path = line(pArray);
    d3.select(handle)
      .transition()
      .duration(250)
      .attr('d', path);
    setTimeout(() => nextStep(handle, points, y, index + 1), 250);
  }
  else {
    d3.select(handle).attr('d', `M 0,${y} H 300`);
  }
 }


const onHover = (handle, e, lineIndex) => {
  let x = e.offsetX;
  let y = lineIndex * 30;
  let m = maxMagnitude;
  const start = - Math.ceil(x / waveLength);
  const end = Math.ceil((totalWidth - x) / waveLength);
  
  const points = [];
  
  for (let i = 0; i >= start; i--) {
    points.unshift({x, y, m: 0});
    x -= waveLength / 4;
    points.unshift({x, y: y - m, m});
    m = Math.max(0, m - delta);
    x -= waveLength / 4;
    points.unshift({x, y: y, m: 0});
    x -= waveLength / 4;
    points.unshift({x, y: y + m, m});
    m = Math.max(0, m - delta);
    x -= waveLength / 4;
  }

  m = maxMagnitude;
  x = e.offsetX;
  for (let i = 0; i <= end; i++) {
    if (i !== 0)
        points.push({x, y, m: 0});
    x += waveLength / 4;
    points.push({x, y: y + m, m});
    m = Math.max(0, m - delta);
    x += waveLength / 4;
    points.push({x, y: y, m: 0});
    x += waveLength / 4;
    points.push({x, y: y - m, m});
    m = Math.max(0, m - delta);
    x += waveLength / 4;
  }
  
  nextStep(handle, points, y, 0);
}

for (let i = 0; i <= 10; i++) {
    svg.append('path')
    .attr('d', `M 0,${i * 30} H 300`)
    .attr('fill', 'none')
    .attr('stroke', 'blue')
    .on('mouseover', function(e) {
        onHover(this, e, i);
    });
}
svg {
  border: 1px solid blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
<svg width='300' height='300'>
</svg>

Reactjs相关问答推荐

如何通过TEK查询将对象传递到Express后台

通过单击具有此值的按钮将值添加到数组对象键

当我try 部署我的Reaction应用程序时,为什么在此PrevState语句中收到语法错误?

关于forwardRef,我可以';我不理解第二个用例

如何在React组件中自动更新图表数据?

在reactjs中刷新页面时丢失状态值

我如何使用 React toastify (Promise) toast 和邮箱 js

验证 Yup 中的对象项

Chakra UI:如何在选中状态下设置复选框 colored颜色

如何在 ChartJS 中创建此图表?在 NEXTjs 和 TSX 中

try 从 React JS 构建此教程游戏但无法继续前进

useEffect 渲染没有依赖数组的组件

如何使用样式化函数为 TextField 的输入组件设置样式

页面不显示

React CSSTransition 两次创建新页面并在这两个相同的页面上运行转换

在 Formik 表单中访问子组件的值

React Router v6 - 访问嵌套路由和处理手写 url 的正确方法

哪个是创建 React 应用程序的更好方法?

useEffect 仅在跟随链接后有效,不适用于直接链接

material uireact ,如何从表格中删除阴影?试图找到 api 但找不到正确的属性