maison.m
maison.m

Reputation: 863

SVG stroke-dashoffset not working

I've been having some issue getting the path of my SVG to animate using stroke-dasharray in conjunction with stroke-dashoffset. The path length was calculated with Js. Below I have included a JsFiddle showing exactly what I am trying to accomplish.

I have searched and searched, and a lot of the examples I came across did not work for me. At this point I am concluding that I am missing something, but I am at my wits end trying to figure out what that is.

<div>
  <svg x="0px" y="0px" width="312px" height="312px" viewBox="0 0 512 512">
    <g>
      <path class="pathOne" d="M320,128c52.562,0,95.375,42.438,96,94.813c-0.25,1.938-0.438,3.875-0.5,5.875l-0.812,23.5l22.25,7.75   C462.688,268.906,480,293.062,480,320c0,35.312-28.688,64-64,64H96c-35.281,0-64-28.688-64-64c0-34.938,28.188-63.438,63-64   c1.5,0.219,3.063,0.406,4.625,0.5l24.313,1.594l8-22.969C140.938,209.313,165.063,192,192,192c3.125,0,6.563,0.375,11.188,1.188   l22.406,4.031l11.156-19.844C253.875,146.938,285.75,128,320,128 M320,96c-47.938,0-89.219,26.688-111.156,65.688   C203.375,160.719,197.781,160,192,160c-41.938,0-77.219,27.063-90.281,64.563C99.813,224.438,97.969,224,96,224c-53,0-96,43-96,96   s43,96,96,96h320c53,0,96-43,96-96c0-41.938-27.062-77.25-64.562-90.313C447.5,227.75,448,225.938,448,224   C448,153.313,390.688,96,320,96L320,96z" fill="#333333"/>
    </g>
  </svg>
</div>

svg {
 position: fixed;
 top: 50%;
 left: 50%;
 transform: translate(-50%, -50%);
}
path.pathOne {
  stroke-dasharray: 2566;
  stroke-dataoffset: 2566;
  animation: cloud 5s linear alternate infinite;
}
@keyframes cloud {
  from {
    stroke-dashoffset: 2566;
  }
  to {
    stroke-dashoffset: 0;
  }
}

https://jsfiddle.net/maisonm/9c3baxh5/

Upvotes: 2

Views: 10734

Answers (2)

Alexandr_TT
Alexandr_TT

Reputation: 14545

Handwriting solution

When an SVG shape has a double path with different distances between the paths and the shape at the points of change of direction, then it is better to use the technique - Handwriting to animate drawing the paths.
Its essence is to animate the middle line, which is wide enough to cover the widest parts of the original shape.

This middle line must be drawn in a vector editor and saved as path

enter image description here

Next, animate this path by drawing a line from maximum to zero . Add this element to the mask and apply a mask to the original shape of the cloud outline.

<animate attributeName="stroke-dasharray"
  begin="svg1.click" dur="4s" values="1281,0;0,1281" fill="freeze" />

where 1281 maximum centerline length

The length of the animated mask changes to reveal the original outline of the cloud. At the same time, creating the illusion of drawing lines with different widths and shapes.

<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="312" height="312" viewBox="0 0 512 512" >
<defs>
 <mask id="msk"> 
     <rect width="100%" height="100%" fill="white" />
       <!-- middle line -->
    <path stroke="#111" stroke-dashoffset="700" stroke-width="45" fill="none" d="m262.3 400c56 0.2 111.3 0 168 0 14.8 0 28.2-10.8 39.1-20.7 9-8.2 15.8-19.2 19.9-30.7 5.2-14.5 9.1-31 5.4-46-4.8-19.1-18.9-35.5-33.7-48.3-7.8-6.7-24.3-4.1-27.6-13.8-5.7-16.5-1.3-35.8-7.7-52.2-7.1-18.4-17.9-36.4-33-49.1-18.4-15.4-42-27.5-66-29.1-24.1-1.7-49.5 6.8-69.8 19.9-16.9 10.9-21.1 35.5-39.1 46-12.4 6.2-27.9-0.8-41.4 2.3-13 3-26.9 6.5-36.8 15.3-13.2 11.7-14.3 25-26.1 46-3.1 5.6-12.9 0.2-19.2 1.5-15.4 3.2-31.9 5.9-44.5 15.3-15.3 11.5-27.7 28.5-33 46.8-4 14-4.3 30.7 2.3 43.7 12.1 24 35.3 50.8 62.1 51.4 65.1 1.5 120.7 1.3 181 1.5z">
      <!-- A mask animation with a wide line that reveals the outlines of the cloud -->
      <animate id="an" attributeName="stroke-dasharray" begin="svg1.click" dur="8s" values="1281,0;0,1281" fill="freeze" repeatCount="1" /> 
   
    </path>
 </mask>
</defs>
                <!-- Cloud contours -->
 <path mask="url(#msk)" fill="dodgerblue" class="pathOne" d="m320 128c52.6 0 95.4 42.4 96 94.8-0.2 1.9-0.4 3.9-0.5 5.9l-0.8 23.5 22.3 7.8C462.7 268.9 480 293.1 480 320c0 35.3-28.7 64-64 64H96c-35.3 0-64-28.7-64-64 0-34.9 28.2-63.4 63-64 1.5 0.2 3.1 0.4 4.6 0.5l24.3 1.6 8-23C140.9 209.3 165.1 192 192 192c3.1 0 6.6 0.4 11.2 1.2l22.4 4 11.2-19.8C253.9 146.9 285.8 128 320 128m0-32C272.1 96 230.8 122.7 208.8 161.7 203.4 160.7 197.8 160 192 160 150.1 160 114.8 187.1 101.7 224.6 99.8 224.4 98 224 96 224 43 224 0 267 0 320c0 53 43 96 96 96h320c53 0 96-43 96-96 0-41.9-27.1-77.2-64.6-90.3C447.5 227.8 448 225.9 448 224 448 153.3 390.7 96 320 96Z"/>
 
 <text x="200" y="300" font-size="36px" fill="dodgerblue" > Click me
   <animate id="op" attributeName="opacity" begin="an.end" dur="1s" values="1;0" fill="freeze" repeatCount="1" />
 </text>
</svg>

Option with repeated animation after a 2s pause

To do this, add a restart condition after a pause of 2s: begin="svg1.click;an.end+2s"

<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="312" height="312" viewBox="0 0 512 512" >
<defs>
 <mask id="msk"> 
     <rect width="100%" height="100%" fill="white" />
       <!-- middle line -->
    <path stroke="#111" stroke-dashoffset="700" stroke-width="45" fill="none" d="m262.3 400c56 0.2 111.3 0 168 0 14.8 0 28.2-10.8 39.1-20.7 9-8.2 15.8-19.2 19.9-30.7 5.2-14.5 9.1-31 5.4-46-4.8-19.1-18.9-35.5-33.7-48.3-7.8-6.7-24.3-4.1-27.6-13.8-5.7-16.5-1.3-35.8-7.7-52.2-7.1-18.4-17.9-36.4-33-49.1-18.4-15.4-42-27.5-66-29.1-24.1-1.7-49.5 6.8-69.8 19.9-16.9 10.9-21.1 35.5-39.1 46-12.4 6.2-27.9-0.8-41.4 2.3-13 3-26.9 6.5-36.8 15.3-13.2 11.7-14.3 25-26.1 46-3.1 5.6-12.9 0.2-19.2 1.5-15.4 3.2-31.9 5.9-44.5 15.3-15.3 11.5-27.7 28.5-33 46.8-4 14-4.3 30.7 2.3 43.7 12.1 24 35.3 50.8 62.1 51.4 65.1 1.5 120.7 1.3 181 1.5z">
      <!-- A mask animation with a wide line that reveals the outlines of the cloud -->
      <animate id="an" attributeName="stroke-dasharray" begin="svg1.click;an.end+2s" dur="6s" values="1281,0;0,1281" fill="freeze" />
    </path>
 </mask>
</defs>
                <!-- Cloud contours -->
 <path mask="url(#msk)" fill="dodgerblue" class="pathOne" d="m320 128c52.6 0 95.4 42.4 96 94.8-0.2 1.9-0.4 3.9-0.5 5.9l-0.8 23.5 22.3 7.8C462.7 268.9 480 293.1 480 320c0 35.3-28.7 64-64 64H96c-35.3 0-64-28.7-64-64 0-34.9 28.2-63.4 63-64 1.5 0.2 3.1 0.4 4.6 0.5l24.3 1.6 8-23C140.9 209.3 165.1 192 192 192c3.1 0 6.6 0.4 11.2 1.2l22.4 4 11.2-19.8C253.9 146.9 285.8 128 320 128m0-32C272.1 96 230.8 122.7 208.8 161.7 203.4 160.7 197.8 160 192 160 150.1 160 114.8 187.1 101.7 224.6 99.8 224.4 98 224 96 224 43 224 0 267 0 320c0 53 43 96 96 96h320c53 0 96-43 96-96 0-41.9-27.1-77.2-64.6-90.3C447.5 227.8 448 225.9 448 224 448 153.3 390.7 96 320 96Z"/>
 
 <text x="200" y="300" font-size="36px" fill="dodgerblue" > Click me 
    <animate id="op" attributeName="opacity" begin="6s" dur="1s" values="1;0" fill="freeze" />
 </text>
 
</svg>

Upvotes: 2

ccprog
ccprog

Reputation: 21811

Your grafic does not show the stroke of a path, but a filled path without a stroke. Here is a illustration of your path data as you could see them in the svg editor Inkscape: cloud path

That is the path you could animate. Was that what you wanted? In that case, define a stroke and remove the fill:

path.pathOne {
  fill: none;
  stroke: black;
  stroke-width: 3;
  stroke-dasharray: 2566;
  stroke-dataoffset: 2566;
  animation: cloud 5s linear alternate infinite;
}
@keyframes cloud {
  from {
    stroke-dashoffset: 2566;
  }
  to {
    stroke-dashoffset: 0;
  }
}
  <svg x="0px" y="0px" width="250px" height="250px" viewBox="0 0 512 512">
<g>
  <path class="pathOne" d="M320,128c52.562,0,95.375,42.438,96,94.813c-0.25,1.938-0.438,3.875-0.5,5.875l-0.812,23.5l22.25,7.75   C462.688,268.906,480,293.062,480,320c0,35.312-28.688,64-64,64H96c-35.281,0-64-28.688-64-64c0-34.938,28.188-63.438,63-64   c1.5,0.219,3.063,0.406,4.625,0.5l24.313,1.594l8-22.969C140.938,209.313,165.063,192,192,192c3.125,0,6.563,0.375,11.188,1.188   l22.406,4.031l11.156-19.844C253.875,146.938,285.75,128,320,128 M320,96c-47.938,0-89.219,26.688-111.156,65.688   C203.375,160.719,197.781,160,192,160c-41.938,0-77.219,27.063-90.281,64.563C99.813,224.438,97.969,224,96,224c-53,0-96,43-96,96   s43,96,96,96h320c53,0,96-43,96-96c0-41.938-27.062-77.25-64.562-90.313C447.5,227.75,448,225.938,448,224   C448,153.313,390.688,96,320,96L320,96z" fill="#333333"/>
</g>
  </svg>

Note that both subpaths are dashed on their own, resulting in the impression that there are two animations. But that is not what is happening, it's simply that the dash and the offset are applied to each subpath separately.

Since the path length is computed for the total of both subpaths, you see a time lag before the animation repeats.

But maybe what you were aiming for was this?

Upvotes: 3

Related Questions