Search code examples
htmlcsssvgcss-animationssvg-animationelements

SVG Rectangle stroke animation-play-state wont change from Javascript


I have been trying to get this code to run for a hover animation for an SVG button, but the browser won't consider my script, although it would consider if the Animation state is mentioned in the CSS.

I am trying to look for any mistakes as to why this would happen, but can't figure one out.

Here is the entire code snippet

body {
  /*display:contents;*/
  height: 100vh;
  background-color: rgb(23, 20, 31);
}

.header {
  background-color: rgb(30, 25, 43);
  height: 10vh;
}

.container {
  width: fit-content;
  margin-top: 2vh;
  padding: 10px;
  background-color: rgb(30, 25, 43);
  /*has transparency*/
}

.button {
  display: inline-block;
  width: 220px;
  height: 280px;
  margin: 10px;
  background-color: rgb(40, 33, 58);
  border-radius: 16px;
  box-shadow: 5px 10px 16px -2px rgba(0, 0, 0, 0.247);
}


/*BUTTON 01*/

button.button_01tag {
  margin: 80px 36px 130px 36px;
  width: 144px;
  height: 64px;
  position: absolute;
  background-color: transparent;
  border: transparent;
  position: absolute;
  padding: 0px;
}

svg.button_01svg {
  width: 140px;
  height: 60px;
}

rect.button_01svgrect {
  z-index: 2;
  fill: rgb(89, 0, 255);
  width: 120px;
  height: 40px;
}

rect.button_01svgrect_stroke {
  fill: transparent;
  width: 120px;
  height: 40px;
  stroke-width: 1;
  stroke: rgba(213, 198, 255, 0);
  stroke-dasharray: 10 132 20 132;
  stroke-linecap: round;
  stroke-dashoffset: 0;
  animation-name: hoverbutton01 1s;
  -webkit-animation: hoverbutton01 1s;
  -moz-animation: hoverbutton01 1s;
  -ms-animation: hoverbutton01 1s;
  animation-timing-function: linear;
  /*animation-play-state:paused;*/
}

@keyframes hoverbutton01 {
  10% {
    stroke: rgb(213, 198, 255);
    stroke-dasharray: 10 132 20 132;
    stroke-dashoffset: 0;
  }
  60% {
    stroke: rgb(213, 198, 255);
    stroke-dasharray: 80 80 80 80;
    stroke-dashoffset: -40;
  }
  70% {
    stroke: rgb(213, 198, 255);
    stroke-dasharray: 80 80 80 80;
    stroke-dashoffset: -60;
  }
  to {
    stroke: rgba(76, 255, 231, 0);
    stroke-dasharray: 80 80 80 80;
    stroke-dashoffset: -140;
  }
}

div.button_01info {
  width: 180px;
  height: 100px;
  padding-left: 20px;
  padding-right: 20px;
  padding-top: 2px;
  margin: 180px 0px 0px 0px;
  position: absolute;
  border-radius: 0px 0px 16px 16px;
  color: rgb(107, 107, 255);
  font-family: 'Poppins';
  font-size: 14px;
  font-weight: 300;
  line-height: 100%;
  background-color: rgb(50, 41, 71);
}
<!DOCTYPE html>
<html>

<head>
  <title>Ui Library</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!--bootstrap.css provides/changes default values for all HTML attributes, like margin, padding fonts etc.-->
  <link href="./node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet">
  <link href="./style.css" rel="stylesheet">
</head>

<body>

  <div class="header"></div>
  <div class="container">

    <div class="button">
      <button type="button" class="button_01tag" onmouseover="buttonhover()" onmouseleave="buttonnohover()">
                <svg  class="button_01svg" viewBox="-10 -10 140 60">
                    
                    <defs>
                        <filter id="glow">
                            <fegaussianblur class="blur" result="coloredBlur" stddeviation="2"></fegaussianblur>
                            <femerge>
                                <femergenode in="coloredBlur"></femergenode>
                                <femergenode in="coloredBlur"></femergenode>
                                <femergenode in="coloredBlur"></femergenode>
                                <femergenode in="coloredBlur"></femergenode>
                                <femergenode in="SourceGraphic"></femergenode>
                            </femerge>
                        </filter>
                    </defs>
                    <rect class="button_01svgrect" rx="08" ry="08"/>
                    <rect class="button_01svgrect_stroke" rx="08" ry="08" filter="url(#glow)" />
                </svg>
            </button>

      <div class="button_01info">
        <h4>Outlined animation</h4>
        Hover on this button to see the effect.
      </div>

    </div>

  </div>

  <script>
    function buttonhover() {
      document.getElementsByClassName("button_01svgrect_stroke").style.animationPlayState = "running";
    }

    function buttonnohover() {
      document.getElementsByClassName("button_01svgrect_stroke").style.animationPlayState = "paused";
    }
  </script>

</body>

</html>


Solution

  • Problem

    These two lines in the functions buttonhover & buttonnohover

    function buttonhover() {
      document.getElementsByClassName("button_01svgrect_stroke").style.animationPlayState = "running" //here;
    }
    
    function buttonnohover() {
      document.getElementsByClassName("button_01svgrect_stroke").style.animationPlayState = "paused" //here also;
    }
    

    The function document.getElementsByClassName returns an HTMLCollection object, it is just like an list..

    Solution

    Replace this

    <rect class="button_01svgrect" rx="08" ry="08"/>
    <rect class="button_01svgrect_stroke" rx="08" ry="08" filter="url(#glow)" />
    

    with this

    <rect id="button_01svgrect" rx="08" ry="08"/>
    <rect id="button_01svgrect_stroke" rx="08" ry="08" filter="url(#glow)" />
    

    and update your script tag as

    function buttonhover() {
      document.getElementById("button_01svgrect_stroke").style.animationPlayState = "running" //here;
    }
    
    function buttonnohover() {
      document.getElementById("button_01svgrect_stroke").style.animationPlayState = "paused" //here also;
    }
    

    One more problem is your script tag is inside your body tag. Edit that also.

    Try this snippet:

    <!DOCTYPE html>
    <html>
    
    <head>
      <title>Ui Library</title>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <style type="text/css">
       
    body {
      /*display:contents;*/
      height: 100vh;
      background-color: rgb(23, 20, 31);
    }
    
    .header {
      background-color: rgb(30, 25, 43);
      height: 10vh;
    }
    
    .container {
      width: fit-content;
      margin-top: 2vh;
      padding: 10px;
      background-color: rgb(30, 25, 43);
      /*has transparency*/
    }
    
    .button {
      display: inline-block;
      width: 220px;
      height: 280px;
      margin: 10px;
      background-color: rgb(40, 33, 58);
      border-radius: 16px;
      box-shadow: 5px 10px 16px -2px rgba(0, 0, 0, 0.247);
    }
    
    
    /*BUTTON 01*/
    
    button.button_01tag {
      margin: 80px 36px 130px 36px;
      width: 144px;
      height: 64px;
      position: absolute;
      background-color: transparent;
      border: transparent;
      position: absolute;
      padding: 0px;
    }
    
    svg.button_01svg {
      width: 140px;
      height: 60px;
    }
    
    #button_01svgrect {
      z-index: 2;
      fill: rgb(89, 0, 255);
      width: 120px;
      height: 40px;
    }
    
    #button_01svgrect_stroke {
      fill: transparent;
      width: 120px;
      height: 40px;
      stroke-width: 1;
      stroke: rgba(213, 198, 255, 0);
      stroke-dasharray: 10 132 20 132;
      stroke-linecap: round;
      stroke-dashoffset: 0;
      animation-name: hoverbutton01 1s linear infinite;
      -webkit-animation: hoverbutton01 1s linear infinite;
      -moz-animation: hoverbutton01 1s linear infinite;
      -ms-animation: hoverbutton01 1s linear infinite;
      animation-play-state: paused;
    }
    
    @keyframes hoverbutton01 {
      10% {
        stroke: rgb(213, 198, 255);
        stroke-dasharray: 10 132 20 132;
        stroke-dashoffset: 0;
      }
      60% {
        stroke: rgb(213, 198, 255);
        stroke-dasharray: 80 80 80 80;
        stroke-dashoffset: -40;
      }
      70% {
        stroke: rgb(213, 198, 255);
        stroke-dasharray: 80 80 80 80;
        stroke-dashoffset: -60;
      }
      to {
        stroke: rgba(76, 255, 231, 0);
        stroke-dasharray: 80 80 80 80;
        stroke-dashoffset: -140;
      }
    }
    
    div.button_01info {
      width: 180px;
      height: 100px;
      padding-left: 20px;
      padding-right: 20px;
      padding-top: 2px;
      margin: 180px 0px 0px 0px;
      position: absolute;
      border-radius: 0px 0px 16px 16px;
      color: rgb(107, 107, 255);
      font-family: 'Poppins';
      font-size: 14px;
      font-weight: 300;
      line-height: 100%;
      background-color: rgb(50, 41, 71);
    }
     </style>
    </head>
    
    <body>
    
      <div class="header"></div>
      <div class="container">
    
        <div class="button">
          <button type="button" class="button_01tag" onmouseover="buttonhover()" onmouseleave="buttonnohover()">
                    <svg  class="button_01svg" viewBox="-10 -10 140 60">
                        
                        <defs>
                            <filter id="glow">
                                <fegaussianblur class="blur" result="coloredBlur" stddeviation="2"></fegaussianblur>
                                <femerge>
                                    <femergenode in="coloredBlur"></femergenode>
                                    <femergenode in="coloredBlur"></femergenode>
                                    <femergenode in="coloredBlur"></femergenode>
                                    <femergenode in="coloredBlur"></femergenode>
                                    <femergenode in="SourceGraphic"></femergenode>
                                </femerge>
                            </filter>
                        </defs>
                        <rect id="button_01svgrect" rx="08" ry="08"/>
                        <rect id="button_01svgrect_stroke" rx="08" ry="08" filter="url(#glow)" />
                    </svg>
                </button>
    
          <div class="button_01info">
            <h4>Outlined animation</h4>
            Hover on this button to see the effect.
          </div>
    
        </div>
    
      </div>
    
    </body>
    
    <script>
      const button_01svgrect_stroke = document.getElementById("button_01svgrect_stroke");
        
        function buttonhover()
        {
          // resets the animation property
          button_01svgrect_stroke.style.animation = "";
          button_01svgrect_stroke.style.animationPlayState = "running";
        }
    
        function buttonnohover()
        {
          // deletes the animation
          button_01svgrect_stroke.style.animation = "none";
          button_01svgrect_stroke.style.animationPlayState = "paused";
        }
    </script>
    
    </html>