【问题标题】:Animate SVG on hover - Make a smile from donts on hover悬停时动画 SVG - 悬停时不做微笑
【发布时间】:2021-02-24 09:55:39
【问题描述】:

我有一个 SVG 文件,其中点在直线上。我想要实现的是当用户将鼠标悬停在 svg 文件上时,点会变成像附加图像一样的微笑。

过渡需要平滑。

这里最好的方法是什么?我可以只使用 css 还是应该使用 js?

谢谢

【问题讨论】:

    标签: javascript css svg svg-animate


    【解决方案1】:

    使用SMIL animation,无需任何脚本即可实现。它将三次贝塞尔路径从直线变为弯曲并返回。动画由位于线条顶部的透明矩形上的mouseover 和mouseout 事件触发。

    这条线本身使用了两个小技巧的组合:您可以将pathLength 设置为属性,以便stroke-dasharray 然后根据它计算破折号长度。对于stroke-dasharray: 0 1 与stroke-linecap 的组合,长度为零的破折号显示为点,笔划宽度为它们的直径。只需使用 pathLength 和 stroke-width 的值来更改点的距离及其大小。

    #line {
      fill: none;
      stroke: black;
      stroke-width: 4;
      stroke-dasharray: 0 1;
      stroke-linecap: round;
    }
    #overlay {
      opacity: 0;
    }
    <svg viewBox="0 0 100 100" width="150">
      <path id="line" d="M 10 50 C 35 50 65 50 90 50" pathLength="15">
        <animate attributeName="d" begin="overlay.mouseover" dur="0.3s"
                 fill="freeze" restart="whenNotActive"
                 from="M 10 50 C 35 50 70 50 90 50"
                 to="M 15 30 C 20 70 80 70 85 30"/>
        <animate attributeName="d" begin="overlay.mouseout" dur="0.3s"
                 fill="freeze" restart="whenNotActive"
                 from="M 15 30 C 20 70 80 70 85 30"
                 to="M 10 50 C 35 50 65 50 90 50"/>
      </path>
      <rect id="overlay" width="100%" height="100%" />
    </svg>

    【讨论】:

    • 这正是我想要的。谢谢。
    【解决方案2】:

    在下一个示例中,我将计算路径上点的位置,每个点的位置是使用 getTotalLength 计算的路径总长度的十分之一。对于每个圆圈,我正在设置初始 cx 的值(在这种情况下,由于初始 cy==0 我没有设置它。

    我还在每个圆圈内添加 2 个 &lt;animate&gt; 元素,这些元素会将 cx 和 cy 动画化到路边路径上的下一个位置。

    动画将在点击时开始。

    const SVG_NS = "http://www.w3.org/2000/svg";//svg namespace
    const dur = .5;// the animation duration
    let circles = Array.from(document.querySelectorAll("circle"))
    
    let la = a.getTotalLength();
    let lb = b.getTotalLength();
    let start = {x:-100,y:0}
    
    circles.forEach((c,i) =>{
      let da = i*la/10;
      let db = i*lb/10;
      let pa = a.getPointAtLength(da); 
      let pb = b.getPointAtLength(db); 
      c.setAttribute("cx",pa.x);
      
      let a1 = document.createElementNS(SVG_NS,"animate");
      a1.setAttribute("attributeName","cx");
      a1.setAttribute("from",pa.x);
      a1.setAttribute("to",pb.x);
      a1.setAttribute("dur",dur);
      a1.setAttribute("begin","svg.click");  
      c.appendChild(a1);
      
      
      let a2 = document.createElementNS(SVG_NS,"animate");
      a2.setAttribute("attributeName","cy");
      a2.setAttribute("from",pa.y);
      a2.setAttribute("to",pb.y);
      a2.setAttribute("dur",dur);
      a2.setAttribute("begin","svg.click");  
      c.appendChild(a2);
    })
    
    svg.addEventListener("click",()=>{
      circles.forEach((c,i) =>{
      let db = i*lb/10
      let pb = b.getPointAtLength(db);  
      c.setAttribute("cx",pb.x)
      c.setAttribute("cy",pb.y)
    })
    })
    svg{border:solid}
    path{fill:none; stroke:black;}
    <svg id="svg" viewBox="-150 -50 300 150" width="300">
      <path id="a" d="M-100,0 A15000,15000 0 0 0 100,0"/>
      <path id="b" d="M-100,0 A150,150 0 0 0 100,0"/>
      
      <circle r="5" />
      <circle r="5" />
      <circle r="5" />
      <circle r="5" />
      <circle r="5" />
      <circle r="5" />
      <circle r="5" />
      <circle r="5" />
      <circle r="5" />
      <circle r="5" />
      <circle r="5" />
    </svg>

    在示例中,用于计算圆位置的路径被描边。您可以从 CSS 中删除笔触。

    【讨论】:

      猜你喜欢
      • 2021-06-08
      • 1970-01-01
      • 1970-01-01
      • 2014-09-28
      • 1970-01-01
      • 2017-06-10
      • 1970-01-01
      • 2012-02-09
      • 2015-01-12
      相关资源
      最近更新 更多