Search code examples
htmlcsssvgsvg-animate

make svg lines draw in when their container ul is visible


I've created a 'site map' inspired menu which uses svgs to connect each of the items in the menu. At the moment the svg's are static. However I believe it's possible to make these draw in?

I have the added complication that I only want the lines to draw in when their container ul is visible.

These are currently visible when the parent li is hovered over...

   #submenu-1 li:hover>ul {
      visibility: visible;
      opacity: 1;
      max-height: 500px;
      transition: opacity 0.5s ease-in;
    }

Here's a link to the fiddle https://jsfiddle.net/spittman/sn3xg5Lb/113/show

Any ideas?

Thanks Sam


Solution

  • Where were you stuck? There are plenty of questions and answers on stack overflow about how to animate line drawing in SVG.

    In your case, I recommend that you redraw each of your lines so that they all start at the top and end at their leaf points. At the moment they seem to be split into parts and go in random directions. Some are start to end, and others end to start).

    For example:

    <svg viewBox="0 0 900 50">
      <polyline points="450,0, 450,25, 112.5,25, 112.5,50" class="st0"/>
      <polyline points="450,0, 450,25, 337.5,25, 337.5,50" class="st0"/>
      <polyline points="450,0, 450,25, 562.5,25, 562.5,50" class="st0"/>
      <polyline points="450,0, 450,25, 787.5,25, 787.5,50" class="st0"/>
    </svg>
    

    The line drawing animation is done by setting a stroke-dasharray equal to the length of the line. Then you animate the stroke-dashoffset from that length down to 0. There are many tutorials on the web that explain how that works. I won't repeat the details here.

    #submenu-1 li ul svg polyline.st0 {
      stroke-dasharray: 388px;
      stroke-dashoffset: 388px;
    }
    

    Then on hover we transition the stroke-dashoffset from 388 to 0.

    #submenu-1 li:hover>ul svg polyline.st0 {
      stroke-dashoffset: 0;
      transition: stroke-dashoffset 1s ease-in;
    }
    

    You'll need to repeat the above steps for each of the tree SVGs. For the smaller tree graphs the 388px value will need to be reduced.

    Complete example:

    $('#menu').mouseover(function () {
          $('#page-title').hide();      
    });
    $('#menu').mouseout(function () {
          $('#page-title').show();      
    });
    @import url("https://use.typekit.net/tud5kgo.css");
    
    body {
      margin: 0;
      padding: 0;
      border: 0;
      background-color: black;
    }
    
    /* Main Menu*/
    
    #submenu-1 {
      list-style: none;
      margin: 0;
      padding: 0px 0 0 0;
    }
    
    /* Level 1 – List item  */
    
    #submenu-1 li {
      width: 900px;
      float: left;
      text-align: center;
      padding-top: 10px;
    }
    
    #submenu-1 li:hover>ul {
      visibility: visible;
      opacity: 1;
      max-height: 500px;
      transition: opacity 0.5s ease-in;
    }
    
    #submenu-1 li ul svg polyline.st0 {
      stroke-dasharray: 388px;
      stroke-dashoffset: 388px;
    }
    
    #submenu-1 li:hover>ul svg polyline.st0 {
      stroke-dashoffset: 0;
      transition: stroke-dashoffset 1s ease-in;
    }
    
    #submenu-1 ul {
      list-style: none;
      left: 0;
      margin: 0;
      padding: 0;
      position: relative;
      width: 900px;
      float: left;
      visibility: hidden;
      opacity: 0;
      transition: visibility 0s, opacity 0.5s linear;
      max-height: 0;
      transition: max-height 0.5s ease-out;
      z-index: 600;
      padding: 10px 0px 0px 0px;
    }
    
    
    a:link,
    a:visited,
    a:active {
      color: white;
      text-align: center;
      text-transform: uppercase;
      text-decoration: none;
      font-family: "montserrat";
      font-weight: 800;
      font-size: 25px;
      letter-spacing: 2px;
      line-height: 1;
    }
    
    a:hover {
      color: grey;
    }
    
    .st0{fill:none;stroke:#FFFFFF;stroke-width:6;stroke-miterlimit:10;}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div id="container">
      <div id="menu">
    
        <ul id="submenu-1">
          <li id="m"><a href="#">what brings<br>you here?</a>
    
            <ul>
              <svg viewBox="0 0 900 50">
                <polyline points="450,0, 450,25, 112.5,25, 112.5,50" class="st0"/>
                <polyline points="450,0, 450,25, 337.5,25, 337.5,50" class="st0"/>
                <polyline points="450,0, 450,25, 562.5,25, 562.5,50" class="st0"/>
                <polyline points="450,0, 450,25, 787.5,25, 787.5,50" class="st0"/>
              </svg>
        
            </ul>
            
          </li>
        </ul>
      </div>
    </div>