How to get handwriting animation with irregular SVG Strokes using JS and CSS?

Viewed 119

I have followed this tutorial to get to where I am. So far, I have the animation working for the mask layer. The only issue is that I cannot change the .mask stroke color to #fff like the tutorial. Once I do that, the mask layer seems to disappear and nothing is animated.

Can someone help me understand why I can't make the lines in the "M" look like they are being drawn by the animation?

const masks = ["M"];

masks.forEach((mask, index, el) => {
  const id = `#Mask-${mask}`;
  let path = document.querySelector(id);
  const length = path.getTotalLength();
  path.style.strokeDasharray = length;
  path.style.strokeDashoffset = length;
});
.Character {
  cursor: pointer;
  position: absolute;
  fill: #000000;
  left: 0;
  top: 0;
}
#Char-M {
  mask: url(#Mask-M);
}

.mask {
        fill: none;
        stroke: #333;
        stroke-miterlimit: 10;
        stroke-width: 171px;
        stroke-linecap: round;
        stroke-linejoin: bevel;
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
      }

@keyframes strokeOffset {
  to {
    stroke-dashoffset: 0;
  }
}

#Mask-M {
  animation: strokeOffset 3s linear infinite;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 559.4 535.94">
>
  <g id="Mask-Layer">
    <g id="Mask">
      <path id="Mask-M" class="mask" d="M90.89,534.25l-4-412c-.54-16.52-4.5-27.17,4-13l165.23,232.5A28.56,28.56,0,0,0,303,341.3L455.79,95.19c9.49-15.28,18.5-11.92,18.1,6.06l-6,433.5"/>
    </g>
  </g>
  <g id="Character-Layer">
    <g id="Character">
      <path id="Char-M" data-name="M" d="M241.39,405.9H216L35.81,102.69V526.41H13.18V64.48H38.64Zm-183-236.54L81,207.58V526.41H58.45ZM292.59,405.9H266.87L64.39,64.48H90.17ZM103.72,245.75l22.67,38V526.41H103.72Zm420-143.1L343.58,405.9H317.8L115.66,64.48h25.47L331,384.75,520.56,64.53h25.83V526.41H523.76ZM149,322.22l22.63,37.94V526.41H149Zm151.52-17.57-13.2-21.2,130.77-219h25.78Zm26.09,43.79-12.89-20.92,155.93-263H495.1Zm61.3,9.48L410.54,320V526.41H387.9Zm45.27-77L455.81,243V526.41H433.17ZM478.44,205l22.63-38.21V526.41H478.44Z"/>
    </g>
  </g>
</svg>

1 Answers

Well, you don't necessarily need a mask, you can just progressively uncover the underlying character by moving the stroke-dasharray of a duplicate over-drawing. Here's a simplified version of yours showing how this would work.

There are some nasty drawing artifacts (in Chrome at least) - because very large strokes often have bad rendering artifacts when you combine them with stroke dash arrays and miters/end-caps. But it does work.

.mask {
        stroke: #fff;
        fill: none;
        stroke-width: 171px;
        stroke-dasharray: 1600 1600;
        stroke-dashoffset: 3200;
      }

@keyframes strokeOffset {
  to {
    stroke-dashoffset: 1600;
  }
}

#Mask-M {
  animation: strokeOffset 3s linear infinite;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 559.4 535.94">

  <g id="Character-Layer">
    <g id="Character">
      <path id="Char-M" data-name="M" d="M241.39,405.9H216L35.81,102.69V526.41H13.18V64.48H38.64Zm-183-236.54L81,207.58V526.41H58.45ZM292.59,405.9H266.87L64.39,64.48H90.17ZM103.72,245.75l22.67,38V526.41H103.72Zm420-143.1L343.58,405.9H317.8L115.66,64.48h25.47L331,384.75,520.56,64.53h25.83V526.41H523.76ZM149,322.22l22.63,37.94V526.41H149Zm151.52-17.57-13.2-21.2,130.77-219h25.78Zm26.09,43.79-12.89-20.92,155.93-263H495.1Zm61.3,9.48L410.54,320V526.41H387.9Zm45.27-77L455.81,243V526.41H433.17ZM478.44,205l22.63-38.21V526.41H478.44Z"/>
    </g>
  </g>
  
  <g id="Mask-Layer">
    <g id="Mask">
      <path id="Mask-M" class="mask" d="M90.89,534.25l-4-412c-.54-16.52-4.5-27.17,4-13l165.23,232.5A28.56,28.56,0,0,0,303,341.3L455.79,95.19c9.49-15.28,18.5-11.92,18.1,6.06l-6,433.5"/>
    </g>
  </g>
  
</svg>

Related