【问题标题】:How to animate svg icon on hover and while it appears in the view port?如何在悬停时为 svg 图标设置动画,同时它出现在视口中?
【发布时间】:2021-05-26 07:35:42
【问题描述】:

当鼠标悬停在 SVG 图标上或出现在视口中时,我正在尝试为 SVG 图标设置动画。

但图标出现动画后,鼠标悬停时不动画。

有没有简单的解决办法?

下面是代码sn-p。在 javascript 中,我使用 window.addEventListener 来检查按钮是否可见。当它可见时,会在 div 中添加一个触发动画的类。

在 CSS 中,有一个类 .animateButton 可以为 SVG 图标的各个组件设置动画。我正在使用路径来选择这些组件。

:hover 用于触发相同的动画,但它当前不起作用。

window.addEventListener('scroll', () => {
  
    var buttonTop = button.getBoundingClientRect().top;
    var buttonIsVisible = (buttonTop - window.innerHeight+25) < 0 && buttonTop > 0;
    //console.log(buttonIsVisible);
    if (buttonIsVisible) {
        if (!button.classList.contains("animateButton")) {
        //console.log(button.className);
            button.classList.add("animateButton");
        }
    } else {
        button.className = "";
    }
})
#button{
width:150px;
background-color:green;
color:white;
padding:.5rem;
text-align: center;
margin-top:500px;
margin-bottom:500px;
}

#button:hover path:nth-child(1){
    stroke-dasharray: 25px;
    stroke-dashoffset: 25px;
    animation: animate-icon .8s ease forwards;
}
#button:hover path:nth-child(2){
    stroke-dasharray: 25px;
    stroke-dashoffset: 25px;
    animation: animate-icon  .8s ease forwards .3s;
}
#button:hover path:nth-child(3), #button:hover path:nth-child(4){
    stroke-dasharray: 7px;
    stroke-dashoffset: 7px;
    animation: animate-icon .5s ease forwards .5s;
}

.animateButton path:nth-child(1){
    stroke-dasharray: 25px;
    stroke-dashoffset: 25px;
    animation: animate-icon .8s ease forwards;
}
.animateButton path:nth-child(2){
    stroke-dasharray: 25px;
    stroke-dashoffset: 25px;
    animation: animate-icon  .8s ease forwards .3s;
}
.animateButton path:nth-child(3), .animateButton path:nth-child(4){
    stroke-dasharray: 7px;
    stroke-dashoffset: 7px;
    animation: animate-icon .5s ease forwards .5s;
}

@keyframes animate-icon{
    to{
        stroke-dashoffset: 0px;
    }
}
<div>
Scroll down to see animation!!
</div>

<div id="button">
 <svg id="circle" width="25" height="25" viewBox="0 0 25 25" fill="none"
                                xmlns="http://www.w3.org/2000/svg">
                                <path
                                    d="M16.6666 21.875V19.7917C16.6666 18.6866 16.2276 17.6268 15.4462 16.8454C14.6648 16.064 13.605 15.625 12.5 15.625H5.20829C4.10322 15.625 3.04342 16.064 2.26201 16.8454C1.48061 17.6268 1.04163 18.6866 1.04163 19.7917V21.875"
                                    stroke="url(#paint0_linear)" stroke-width="2" stroke-linecap="round"
                                    stroke-linejoin="round" />
                                <path
                                    d="M8.85417 11.4583C11.1554 11.4583 13.0208 9.59285 13.0208 7.29167C13.0208 4.99048 11.1554 3.125 8.85417 3.125C6.55298 3.125 4.6875 4.99048 4.6875 7.29167C4.6875 9.59285 6.55298 11.4583 8.85417 11.4583Z"
                                    stroke="url(#paint1_linear)" stroke-width="2" stroke-linecap="round"
                                    stroke-linejoin="round" />
                                <path d="M20.8334 8.33337V14.5834" stroke="url(#paint2_linear)" stroke-width="2"
                                    stroke-linecap="round" stroke-linejoin="round" />
                                <path d="M23.9584 11.4584H17.7084" stroke="url(#paint3_linear)" stroke-width="2"
                                    stroke-linecap="round" stroke-linejoin="round" />
                                <defs>
                                    <linearGradient id="paint0_linear" x1="2.18637" y1="15.625" x2="8.84787"
                                        y2="24.9627" gradientUnits="userSpaceOnUse">
                                        <stop stop-color="#242E31" />
                                        <stop offset="1" stop-color="#0C1314" />
                                    </linearGradient>
                                    <linearGradient id="paint1_linear" x1="5.29803" y1="3.125" x2="13.3121" y2="7.61847"
                                        gradientUnits="userSpaceOnUse">
                                        <stop stop-color="#242E31" />
                                        <stop offset="1" stop-color="#0C1314" />
                                    </linearGradient>
                                    <linearGradient id="paint2_linear" x1="20.9066" y1="8.33337" x2="22.1606"
                                        y2="8.44587" gradientUnits="userSpaceOnUse">
                                        <stop stop-color="#242E31" />
                                        <stop offset="1" stop-color="#0C1314" />
                                    </linearGradient>
                                    <linearGradient id="paint3_linear" x1="18.1663" y1="11.4584" x2="18.7611"
                                        y2="13.543" gradientUnits="userSpaceOnUse">
                                        <stop stop-color="#242E31" />
                                        <stop offset="1" stop-color="#0C1314" />
                                    </linearGradient>
                                </defs>
                            </svg>
<span class="buttonText"> Hover Me! </span>
</div>

【问题讨论】:

    标签: javascript html css


    【解决方案1】:

    您可以使用Intersection Observer

    const intersectRatio = .2;
    var options = {
      root: null,
      rootMargin: '0px',
      threshold: intersectRatio
    }
    
    var handleIntersect = function(entries, observer) {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          console.log("visble")
          entry.target.classList.add('animateButton');
          observer.unobserve(entry.target)
        } else
          console.log("invisble")
      });
      console.log("Handle");
    }
    
    var observer = new IntersectionObserver(handleIntersect, options);
    document.querySelectorAll('#button').forEach(function(r) {
      observer.observe(r);
    })
    #button {
      width: 150px;
      background-color: green;
      color: white;
      padding: .5rem;
      text-align: center;
      margin-top: 500px;
      margin-bottom: 500px;
    }
    
    #button:hover path:nth-child(1) {
      stroke-dasharray: 25px;
      stroke-dashoffset: 25px;
      animation: animate-icon .8s ease forwards;
    }
    
    #button:hover path:nth-child(2) {
      stroke-dasharray: 25px;
      stroke-dashoffset: 25px;
      animation: animate-icon .8s ease forwards .3s;
    }
    
    #button:hover path:nth-child(3),
    #button:hover path:nth-child(4) {
      stroke-dasharray: 7px;
      stroke-dashoffset: 7px;
      animation: animate-icon .5s ease forwards .5s;
    }
    
    .animateButton path:nth-child(1) {
      stroke-dasharray: 25px;
      stroke-dashoffset: 25px;
      animation: animate-icon .8s ease forwards;
    }
    
    .animateButton path:nth-child(2) {
      stroke-dasharray: 25px;
      stroke-dashoffset: 25px;
      animation: animate-icon .8s ease forwards .3s;
    }
    
    .animateButton path:nth-child(3),
    .animateButton path:nth-child(4) {
      stroke-dasharray: 7px;
      stroke-dashoffset: 7px;
      animation: animate-icon .5s ease forwards .5s;
    }
    
    @keyframes animate-icon {
      to {
        stroke-dashoffset: 0px;
      }
    }
    <div>
      Scroll down to see animation!!
    </div>
    
    <div id="button">
      <svg id="circle" width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path
                                        d="M16.6666 21.875V19.7917C16.6666 18.6866 16.2276 17.6268 15.4462 16.8454C14.6648 16.064 13.605 15.625 12.5 15.625H5.20829C4.10322 15.625 3.04342 16.064 2.26201 16.8454C1.48061 17.6268 1.04163 18.6866 1.04163 19.7917V21.875"
                                        stroke="url(#paint0_linear)" stroke-width="2" stroke-linecap="round"
                                        stroke-linejoin="round" />
                                    <path
                                        d="M8.85417 11.4583C11.1554 11.4583 13.0208 9.59285 13.0208 7.29167C13.0208 4.99048 11.1554 3.125 8.85417 3.125C6.55298 3.125 4.6875 4.99048 4.6875 7.29167C4.6875 9.59285 6.55298 11.4583 8.85417 11.4583Z"
                                        stroke="url(#paint1_linear)" stroke-width="2" stroke-linecap="round"
                                        stroke-linejoin="round" />
                                    <path d="M20.8334 8.33337V14.5834" stroke="url(#paint2_linear)" stroke-width="2"
                                        stroke-linecap="round" stroke-linejoin="round" />
                                    <path d="M23.9584 11.4584H17.7084" stroke="url(#paint3_linear)" stroke-width="2"
                                        stroke-linecap="round" stroke-linejoin="round" />
                                    <defs>
                                        <linearGradient id="paint0_linear" x1="2.18637" y1="15.625" x2="8.84787"
                                            y2="24.9627" gradientUnits="userSpaceOnUse">
                                            <stop stop-color="#242E31" />
                                            <stop offset="1" stop-color="#0C1314" />
                                        </linearGradient>
                                        <linearGradient id="paint1_linear" x1="5.29803" y1="3.125" x2="13.3121" y2="7.61847"
                                            gradientUnits="userSpaceOnUse">
                                            <stop stop-color="#242E31" />
                                            <stop offset="1" stop-color="#0C1314" />
                                        </linearGradient>
                                        <linearGradient id="paint2_linear" x1="20.9066" y1="8.33337" x2="22.1606"
                                            y2="8.44587" gradientUnits="userSpaceOnUse">
                                            <stop stop-color="#242E31" />
                                            <stop offset="1" stop-color="#0C1314" />
                                        </linearGradient>
                                        <linearGradient id="paint3_linear" x1="18.1663" y1="11.4584" x2="18.7611"
                                            y2="13.543" gradientUnits="userSpaceOnUse">
                                            <stop stop-color="#242E31" />
                                            <stop offset="1" stop-color="#0C1314" />
                                        </linearGradient>
                                    </defs>
                                </svg>
      <span class="buttonText"> Hover Me! </span>
    </div>

    【讨论】:

      【解决方案2】:

      问题是css动画不是那么容易重启的。 css-tricks 有一篇关于此的文章:https://css-tricks.com/restart-css-animation/。我使用的技巧是将元素重新插入到页面中。您也可以尝试使用void element.offsetWidth; 解决方案。

      以下是应用的文章中提到的重新插入解决方案。我必须嵌套 2 个事件,因为在克隆元素时 mouseenter 事件会在 mousemove 时自动重新触发。

      let btn = document.getElementById('button');
      
      window.addEventListener('scroll', () => {
        
          var buttonTop = btn.getBoundingClientRect().top;
          var buttonIsVisible = (buttonTop - window.innerHeight+25) < 0 && buttonTop > 0;
          //console.log(buttonIsVisible);
          if (buttonIsVisible) {
              if (!btn.classList.contains("animateButton")) {
              //console.log(btn.className);
                  btn.classList.add("animateButton");
              }
          } else {
              btn.className = "";
          }
      })
      
      let animateIt = () => {
          let newone = btn.cloneNode(true);
          btn.parentNode.replaceChild(newone, btn);
          btn = document.getElementById('button');
      
          // apply the event when leaving
          // the newly inserted element
          // to prevent constant animation retriggering
          btn.addEventListener('mouseout', () =>
              btn.addEventListener('mouseenter', animateIt)
          );
      };
      
      btn.addEventListener('mouseenter', animateIt);
      #button {
      width:150px;
      background-color:green;
      color:white;
      padding:.5rem;
      text-align: center;
      margin-top:500px;
      margin-bottom:500px;
      }
      
      #button:hover path:nth-child(1){
          stroke-dasharray: 25px;
          stroke-dashoffset: 25px;
          animation: animate-icon .8s ease forwards;
      }
      #button:hover path:nth-child(2){
          stroke-dasharray: 25px;
          stroke-dashoffset: 25px;
          animation: animate-icon  .8s ease forwards .3s;
      }
      #button:hover path:nth-child(3), #button:hover path:nth-child(4){
          stroke-dasharray: 7px;
          stroke-dashoffset: 7px;
          animation: animate-icon .5s ease forwards .5s;
      }
      
      .animateButton path:nth-child(1){
          stroke-dasharray: 25px;
          stroke-dashoffset: 25px;
          animation: animate-icon .8s ease forwards;
      }
      .animateButton path:nth-child(2){
          stroke-dasharray: 25px;
          stroke-dashoffset: 25px;
          animation: animate-icon  .8s ease forwards .3s;
      }
      .animateButton path:nth-child(3), .animateButton path:nth-child(4){
          stroke-dasharray: 7px;
          stroke-dashoffset: 7px;
          animation: animate-icon .5s ease forwards .5s;
      }
      
      @keyframes animate-icon{
          to{
              stroke-dashoffset: 0px;
          }
      }
      <div>
      Scroll down to see animation!!
      </div>
      
      <div id="button">
       <svg id="circle" width="25" height="25" viewBox="0 0 25 25" fill="none"
                                      xmlns="http://www.w3.org/2000/svg">
                                      <path
                                          d="M16.6666 21.875V19.7917C16.6666 18.6866 16.2276 17.6268 15.4462 16.8454C14.6648 16.064 13.605 15.625 12.5 15.625H5.20829C4.10322 15.625 3.04342 16.064 2.26201 16.8454C1.48061 17.6268 1.04163 18.6866 1.04163 19.7917V21.875"
                                          stroke="url(#paint0_linear)" stroke-width="2" stroke-linecap="round"
                                          stroke-linejoin="round" />
                                      <path
                                          d="M8.85417 11.4583C11.1554 11.4583 13.0208 9.59285 13.0208 7.29167C13.0208 4.99048 11.1554 3.125 8.85417 3.125C6.55298 3.125 4.6875 4.99048 4.6875 7.29167C4.6875 9.59285 6.55298 11.4583 8.85417 11.4583Z"
                                          stroke="url(#paint1_linear)" stroke-width="2" stroke-linecap="round"
                                          stroke-linejoin="round" />
                                      <path d="M20.8334 8.33337V14.5834" stroke="url(#paint2_linear)" stroke-width="2"
                                          stroke-linecap="round" stroke-linejoin="round" />
                                      <path d="M23.9584 11.4584H17.7084" stroke="url(#paint3_linear)" stroke-width="2"
                                          stroke-linecap="round" stroke-linejoin="round" />
                                      <defs>
                                          <linearGradient id="paint0_linear" x1="2.18637" y1="15.625" x2="8.84787"
                                              y2="24.9627" gradientUnits="userSpaceOnUse">
                                              <stop stop-color="#242E31" />
                                              <stop offset="1" stop-color="#0C1314" />
                                          </linearGradient>
                                          <linearGradient id="paint1_linear" x1="5.29803" y1="3.125" x2="13.3121" y2="7.61847"
                                              gradientUnits="userSpaceOnUse">
                                              <stop stop-color="#242E31" />
                                              <stop offset="1" stop-color="#0C1314" />
                                          </linearGradient>
                                          <linearGradient id="paint2_linear" x1="20.9066" y1="8.33337" x2="22.1606"
                                              y2="8.44587" gradientUnits="userSpaceOnUse">
                                              <stop stop-color="#242E31" />
                                              <stop offset="1" stop-color="#0C1314" />
                                          </linearGradient>
                                          <linearGradient id="paint3_linear" x1="18.1663" y1="11.4584" x2="18.7611"
                                              y2="13.543" gradientUnits="userSpaceOnUse">
                                              <stop stop-color="#242E31" />
                                              <stop offset="1" stop-color="#0C1314" />
                                          </linearGradient>
                                      </defs>
                                  </svg>
      <span class="buttonText"> Hover Me! </span>
      </div>

      【讨论】:

        猜你喜欢
        • 2020-07-12
        • 2016-05-09
        • 1970-01-01
        • 2021-08-22
        • 2022-01-10
        • 1970-01-01
        • 2012-04-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多