看到按钮的一个有趣的效果

Saw an interesting effect for the button

我想在将鼠标悬停在 svg 对象上时创建与此站点上完全相同的效果 http://animejs.com/

为此,我打开了 inkscape 并绘制了一条路径并保存了悬停前后的两个状态。

第一个状态:

<svg viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">

 <path d="m11 103c64-2.5 123-1.5 178 0v42c-61 3.5-120 0.43-178 0z"
 style="fill:none; stroke:#ff17ff;"/>
</svg>

第二状态

<svg viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">

 <path d="m11 103c62-7.8 121-6.3 178 0v42c-61 9.7-120 6.3-178 0z" 
       style="fill:none;stroke:#ff17ff"/>
</svg>

很可能需要在 js/jquery 中完成,请告诉我如何实现这种效果?如何以如此灵活的方式更改路径?

要为按钮的轮廓设置动画,您需要为参数设置动画 d 补丁

<animate attributeName="d" values="path1;path2" dur="2s" begin="btn.mouseover" /> 

.container {
width:25%;
height:25%;
}
<div class="container">
<svg   viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">

 <path id="btn"  d="m11 103c64-2.5 123-1.5 178 0v42c-61 3.5-120 0.43-178 0z"
 style="fill:none; stroke:#ff17ff;">
 <animate attributeName="d" values="m11 103c64-2.5 123-1.5 178 0v42c-61 3.5-120 0.43-178 0z;m11 103c62-7.8 121-6.3 178 0v42c-61 9.7-120 6.3-178 0z" dur="1s" begin="btn.mouseover" />
 </path>
 <text x="23" y="136" font-size="36" >mouseover</txt>
</svg>
</div>

我看到已经有答案了,但由于我已经准备好了,所以我将其发布。我正在使用 Javascript 而不是 SMIL 动画。

路径我已经准备好了。如果你看一下,我已经将每个命令都转换为 C

let rid = null;
let ry = [];
let speed = 1 / 10;

class pathsPair {
  constructor(thePath, yes, no) {
    this.path = thePath;
    this.yes = yes;
    this.no = no;
    this.vals = this.getArgsRy(yes);
    this.target = this.getArgsRy(no);
    this.targetAlp = 0;
    this.alp = 1;
    this.light = 70;
  }

  getArgsRy(path) {
    let d = path.getAttribute("d").replace(/\r?\n|\r/g, ""); //remove breaklines
    if (d.charAt(0) == "m") {
      d = "M" + d.slice(1);
    }
    let argsRX = /(?=[a-zA-Z])/;
    let args = d.split(argsRX);

    let ArgsRy = [];

    args.map(arg => {
      let argRy = arg
        .slice(1)
        .replace(/\-/g, " -")
        .split(/[ ,]+/);
      argRy.map((p, i) => {
        if (p == "") {
          argRy.splice(i, 1);
        }
      });

      for (let i = 0; i < argRy.length; i++) {
        argRy[i] = parseFloat(argRy[i]);
      }

      argRy.unshift(arg[0]);
      ArgsRy.push(argRy);
    });

    return ArgsRy;
  }

  morph() {
    let newD = "";

    this.vals.map((v, vi) => {
      let newStr = v[0];
      for (let i = 1; i < v.length; i++) {
        this.updateProp(vi, i);

        newStr += v[i].toFixed(3) + " ";
      }
      newD += newStr + " ";
    }); //
    this.path.setAttributeNS(null, "d", newD);
  }

  updateProp(vi, i) {
    let dist = this.target[vi][i] - this.vals[vi][i];
    let vel = dist / 10;
    this.vals[vi][i] += vel;
  }

  sayNO() {
    this.target = this.getArgsRy(this.no);
    this.targetAlp = 0;
  }

  sayYES() {
    this.target = this.getArgsRy(this.yes);
    this.targetAlp = 1;
  }
}

let the_pair = new pathsPair(morphingPath, _2, _1);
console.log(the_pair);
svg.addEventListener("mouseover", function() {
  console.log(rid);
  if (rid) {
    window.cancelAnimationFrame(rid);
    rid = null;
  }
  the_pair.sayYES();
  Frame();
});
svg.addEventListener("mouseleave", function() {
  
  if (rid) {
    window.cancelAnimationFrame(rid);
    rid = null;
  }
  the_pair.sayNO();
  Frame();
});

function Frame() {
  rid = window.requestAnimationFrame(Frame);
  the_pair.morph();
}

window.addEventListener("load", function() {
  Frame();
});
svg{border:1px solid}
#morphingPath{fill:transparent; stroke:black;}
<svg id="svg" viewBox="0 90 210 70" xmlns="http://www.w3.org/2000/svg">
<defs>
 <path id="_1" d="M11.000, 103.000 C75.000, 100.500 134.000, 101.500 189.000, 103.000 C189.000, 117.000 189.000, 131.000 189.000, 145.000 C128.000, 148.500 69.000, 145.430 11.000, 145.000 z"
/>
  
   <path id="_2" d="M11.000, 103.000 C73.000, 95.200 132.000, 96.700 189.000, 103.000 C189.000, 117.000 189.000, 131.000 189.000, 145.000 C128.000, 154.700 69.000, 151.300 11.000, 145.000 z" 
       />
  </defs>
  
  <path id="morphingPath" d=""
 style="fill:none; stroke:#ff17ff;" />
</svg>