Search code examples
javascriptcsssvgcss-animationssnap.svg

How to achieve overflow hidden with svg animation?


I am trying to animate a path within an svg. The path is of a squiggly line to look like a wave. What I am trying to do is have this path translate horizontally on a infinite loop to make it look as though the water is moving.

You can see a similar effect achieved by the outline, only going vertically and this is not within an SVG: https://theoutline.com/

Here is the JsFiddle I have so far with an svg wave/squiggle.

<g class="wave-container">
  <path class="wave" d="M1,1c1.6,0,1.6,1.6,3.3,1.6S5.9,1,7.6,1c1.6,0,1.6,1.6,3.3,1.6S12.5,1,14.2,1s1.6,1.6,3.3,1.6
                c1.6,0,1.6-1.6,3.3-1.6"/>
</g>

https://jsfiddle.net/bje5rxzs/

I am trying to be able to animate this wave horizontally within it's group/container. I know SVG does not support overflow:hidden; within, so how would this be achieved? Would a mask work? I am open to using a snap.svg if required. I will have other elements within this svg moving, so the squiggle needs to be within the same svg.

Any help much appreciated! Thank you :)


Solution

  • Updated

    Like any animation where you are changing the position of something you can use transforms.

    The key here is making the squiggly path wider than the svg viewbox, and setting overflow:hidden on svg (which is supported).

    Since your illustration is tiny I had to make the svg viewbox tiny as well, only 15px wide, so that the path could overlap the svg container.

    <svg version="1.1" x="0px" y="0px" width="15px" height="3.6px" viewBox="0 0 15 3.6">
       <path class="white-path animate" d="M1,1c1.6,0,1.6,1.6,3.3,1.6S5.9,1,7.6,1c1.6,0,1.6,1.6,3.3,1.6S12.5,1,14.2,1s1.6,1.6,3.3,1.6 c1.6,0,1.6-1.6,3.3-1.6"/>
    </svg>
    

    css:

    svg {
      overflow:hidden;
    }
    .white-path {
      fill:none;
      stroke:#FFFFFF;
      stroke-width:2;
      stroke-linecap:round;
      stroke-linejoin:round;
      stroke-miterlimit:10;
     }
     @keyframes squiggle {
       from {
         transform: translateX(-7px)
       }
       to {
         transform: translateX(0px)
       }
     }
     .animate {
       animation: squiggle 1s linear infinite;
     }
    

    I used a negative x translation, and through trial and error picked the right distance so the looping was seamless.

    Demo: https://jsfiddle.net/bje5rxzs/6/