This is the second in a series of articles titled “Implementing Common Front-end Features with Native JS” that cover some of the basics of SVG and how to implement a writing animation in SVG.

SVG is an XML-based markup language that is often used to elegantly and succinctly render graphics that automatically change in response, and to work seamlessly with CSS, DOM, JavaScript and other web standards. So at work, using it skillfully can make the development process much more handy.

Today’s example is writing animation with JavaScript + SVG.

Implementation effect

The final result:

Draw the SVG graphics

How do you achieve this? First, you need to prepare a picture:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280 40." ">
  <g fill="none" stroke="# 000">
    <path
      d="M20.15 22.62 c - 3.74-3.67-7.94-9.77-5-15 2.5 3.16 5.88 1.35 4.2. 5.23 2, 11.08, 66-6-2.95-2.62-14.8 8.04.02 4-7-1.15-1.88 3.52. 9 5 0"
    />
    <path
      d=2.87-2.37 6.7 0 9 3.02.14 4.57-2.8 6-5"
    />
    <path
      d=2.87-3.6 6.56-1 9 4.88.6 7.7-4.72 7-9m0 0c-.08 3.47 "m0m0 0c-.08 2.87-3.6 6.56-1 9 4.88.6 7.7-4.72 7-9m0 0c-.08 2.6 6.87 5.95 4.02 l. 05 -. 02"
    />
    <path
      d="M77.15 c2.8-25.62. 5.64 4.77 3-7-5. 67-52. 5-5.4 4.48 2.84 5.9 5 9.6.1 9 2.97.08"
    />
    <path
      d="M86.15 c2.77 22.62-4.7-7-9.27-7-15-2. 77-2.68-2.88-4.8-5.18-4.56, 4.62-1.9-9.75-74. 82 14.2 2.64 2.2 5.43 2.47 6.62 4.38"
    />
    <path
      d="M94.15 c2.77 22.62-4.7-7-9.27-7-15-2. 77-2.68-2.88-4.8-5.18-4.56, 4.62-1.9-9.75-74. 82 14.2 2.64 2.2 5.43 2.47 6.62 4.38"
    />
    <path
      d="M121.15 13.62c-.43 2.95 2.74 -.600 zm-3 9c2.5-5.4 1.76-3.03.27 1.18-1.95 3.2.96 4.9 4.73 1.82l2-3"
    />
    <path
      d=M125.15 22.6c.55-2.93 6.15-5.93 4.73-.94-.45 2.02-1.04 4-1.73 5.94m1-3c1.27-2.85 3.74-7.46 7.38-5.6 2.44 2.3-2.94 7.36 1.16 8.6 2.77-.3 4.06-2.92 5.45-5"
    />
    <path
      d="M159.15 22.6c2.02-2.78 3.9-7.3 2.07-1.3-1.98 6.12-4.05 12.2-6.07 18.3m6-18c.83-4.6 8.62-3.63 8 1.1.06 2.33-1.9 4.4-4 4.9 m - 4-1 c4. 33 10.2-2.78. 4 to 13-4"
    />
    <path
      d="M180.15 18.62 c - 4.63-1.2-8.56 6.1 4.02 8.5 4.4 2.74 9.78 4.58 5.53-7.74-3.54-2.53-4.84-3.16. 05 4.97 2.22.82 5.06.2 6.55-1.73"
    />
    <path
      d="M188.15 22.6c2.35-2.74 2.73-7.08 3.9-1.64 1.38 2 4.07 5.8.1 6.64m-4-1c3.62 2.38 8.93.9 10.5-3.27l.32-.45.18-.28"
    />
    <path
      d="M199.15 22.6c2.35-2.74 2.73-7.08 3.9-1.64 1.38 2 4.07 5.8.1 6.64m-4-1c3.62 2.38 8.93.9 10.5-3.27l.32-.45.18-.28"
    />
    <path
      d="M213.15 13.62c-.43 2.95 2.74-.60zm-3 9c2-5-5.4 1.76-3.03.27 1.18-1.95 3.9 2.96 4.9 4.73 1.82l2-3"
    />
    <path
      d="M217.15 22.6c2.77-4.7 7-9.27 7-15-2.77-2.68-4.56 2.88-4.8 5.18-.74 4.62-1.9 9.75-1.82 14.2 2.47 1.77 5.9-1.88 "M217.15 22.6c2.77-4.7 7-9.27 7-15-2.77-2.68-4.56 2.88-4.8 5.18- 6.3-4.45.7-6-1-1.8 2.32 1.07 2.74. 1.5.23 22 4-1"
    />
    <path
      d="M234.15 13.62c-.43 2.95 2.74 -.600 zm-3 9c2-5 "1.76-3.03.27 1.18-1.95 2.96 4.73 1.82l2-3"
    />
    <path
      d="M238.15 22.6c2.77-4.7 7-9.27 7-15-2.77-2.68-4.56 2.88-4.8 5.18-.74 4.62-1.9 9.75-2.82 14.2 2.64 2.2 5.43-2.47 "M238.15 22.6c2.77-4.7 7-9.27 7-15-2.77 2.68-4.56 2.88-4.8 5.18- 6.62-4.38"
    />
    <path
      d="M249.15 13.613c-.43 2.95 2.74-.60zm-3 9c2-5-5.4 1.76-3.03.27 1.18-1.95 3.9 2.96 4.9 4.73 1.82l2-3"
    />
    <path
      d="M253.15 22.62-2.18 2.84-4.55 4.7m3-9c-1.9 6.38-4.7 12.62-6 19.1.3 3.68 5.68 1.46 6.6-1l1. 4-2.6m-8-8h7"
    />
    <path
      d="M262.15 22.6c2.6-3.76-3.03.27 1.18-1.98 3.77 3.02 5.1 2.44 1.56-1.28 2.53-2.97 3.63-4.62m1-3c-2.4 6.64-4.1 13.56-7 20-3.85-3.06-3.5-3.64-1.62-5.38-3.73-4.66-10-5.83-13.62-10.62"
    />
  </g>
</svg>
Copy the code

If you haven’t worked with SVG before, you might be wondering why it’s a piece of XML code instead of an image. This is because SVG itself is an XML-based markup language that is displayed as images by browsers that parse the information carried by XML.

For example, if we want to display a 300px long by 300px red filled square in SVG, all we need is the following XML:

<svg
  style="width: 150px; height: 300px"
  version="1.1"
  baseProfile="full"
  xmlns="http://www.w3.org/2000/svg"
>
  <rect width="300" height="300" fill="red" />
</svg>
Copy the code

Operation effect:

The SVG graphics are purposely added 150px width and 300px height for the sake of showing the SVG’s responsive changes later, so they look incomplete.

Try running the above code and you will find that SVG is not a vector, so why can’t the above images be responsive? Just add the viewBox attribute to the XML above.

<svg
  style="width: 150px; height: 300px"
  version="1.1"
  baseProfile="full"
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 400 400"
>
  <rect width="300" height="300" fill="red" />
</svg>
Copy the code

Operation effect:

The values of the viewBox attribute are a blank or comma separated sequence of four parameters, represented from left to right (SVG’s coordinate origin is in the upper left corner) : minimum x-value, minimum y-value, width, and height. The width and height cannot be negative values, and elements can be hidden when the width or height is set to 0.

To think of a viewBox, think of it as a dimension unit rather than a view of any CSS unit (e.g., PX), but just call it a unit for simplicity. For example, if the viewBox is 00 400 400, the minimum X-axis value is 0, the minimum Y-axis value is 0, the width is 400, and the height is 400.

The first two arguments of the viewBox are used to move elements of an SVG graph as a whole. For example, if we define the viewBox property of an SVG graph as 200, 200, 400, 400, we move the element 200 units to the left and up, relative to the view.

Operation effect:

The last two parameters of the viewBox are somewhat abstract to understand, as illustrated by the example above. The viewBox property of the graph above is defined as 0, 0, 400, 400, and the length of the square inside is defined as 300 by 300. In our mind’s eye we imagine a big square of 400 units by 400 units, with a smaller square of 300 units by 300 units in it. Note: SVG has a feature that, by default, resize the viewBox to fit inside SVG. Since the outer SVG is defined as a 150px by 300px rectangle, reducing the actual width of the large square to the SVG width will fit the entire large square in SVG, so the viewBox is now 150px by 150px. One unit of the viewBox = 150px/400 = 0.375px. All the values inside the viewBox *0.375px are the real length. The actual size of that little square is 112.5px by 112.5px.

Make SVG graphics live

To make SVG images move, it is important to understand the concepts of stroke-Dasharray and stroke-dashoffset.

stroke-dasharray

In SVG, you can also specify the stroke-dasharray attribute to make the border become dashed like in CSS border-style: dashed (). The parameter to the stroke-dasharray property is a comma-separated sequence of numbers. Note that the numbers must be separated by commas, although Spaces can be inserted, but the numbers must be separated by commas.

For each set of numbers, the first is used to represent a solid line and the second is used to represent a blank space. If there is only one number 5, a 5px solid line will be drawn, followed by 5px blank, and then another 5px solid line to form a dashed line. For example, if I have a 200px line and I specify the stroke-dasharray value as 200, it means that I draw 200px solid line, followed by 200px blank line, and then another 200px solid line to make a dashed line.

Such as:

<svg
  version="1.1"
  baseProfile="full"
  xmlns="http://www.w3.org/2000/svg"
  width="200"
  height="200"
  viewPort="0 0 200 300"
>
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="5, 5"
    x1="10"
    y1="10"
    x2="190"
    y2="10"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="5, 10"
    x1="10"
    y1="30"
    x2="190"
    y2="30"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="10, 5"
    x1="10"
    y1="50"
    x2="190"
    y2="50"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray=5, "1"
    x1="10"
    y1="70"
    x2="190"
    y2="70"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="1, 5"
    x1="10"
    y1="90"
    x2="190"
    y2="90"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="0.9"
    x1="10"
    y1="110"
    x2="190"
    y2="110"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="15, 10, 5"
    x1="10"
    y1="130"
    x2="190"
    y2="130"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="15, 10, 5, 10"
    x1="10"
    y1="150"
    x2="190"
    y2="150"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="15, 10, 5, 10, 15"
    x1="10"
    y1="170"
    x2="190"
    y2="170"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="5, 5, 1, 5"
    x1="10"
    y1="190"
    x2="190"
    y2="190"
  />
</svg>
Copy the code

Operation effect:

stroke-dashoffset

The stroke-Dashoffset property represents the offset of the path from the starting position. For example, the stroke-dasharray values are defined as 5, 10, 30, with 10 representing 5px dashed line, 10px white space, 30px dashed line, 10px white space, and so on. Then, see what happens by changing its stroke-dashoffset value:

<svg
  version="1.1"
  baseProfile="full"
  xmlns="http://www.w3.org/2000/svg"
  width="200"
  height="200"
  viewPort="0 0 200 300"
>
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="5, 10, 30, 10"
    x1="10"
    y1="10"
    x2="190"
    y2="10"
  />
  <line
    stroke="black"
    stroke-width="2"
    stroke-dasharray="5, 10, 30, 10"
    stroke-dashoffset="15"
    x1="10"
    y1="20"
    x2="190"
    y2="20"
  />
</svg>
Copy the code

Operation effect:

Watching the above code in action, you can reset the start of the path with the stroke-dashoffset property. In the example above, set stroke-dashoffset to 15 and you can see that the path moves 15px to the left.

<svg
  version="1.1"
  baseProfile="full"
  xmlns="http://www.w3.org/2000/svg"
  width="200"
  height="200"
  viewPort="0 0 200 300"
>
  <g fill="none" stroke="# 000">
    <path
      d="M20.15 22.62 c - 3.74-3.67-7.94-9.77-5-15 2.5 3.16 5.88 1.35 4.2. 5.23 2, 11.08, 66-6-2.95-2.62-14.8 8.04.02 4-7-1.15-1.88 3.52. 9 5 0"
    />
  </g>
</svg>
Copy the code

Set both stroke-dasharray and stroke-dashoffset of the path to the same value, and you will see nothing because the dashed line and blank distance of the path are the same.

Use JS to achieve specific functions

To implement the writing animation above, first get the length of path to set stroke-dasharray and stroke-dashoffset values. Then use the animate method in the Web Animations API to set the stroke-Dashoffset value from equal length to 0 to produce a written animation.

Let’s implement the specific functions. Get all paths and use getTotalLength() to get the length of the path, then hide all paths by setting the strokeDashoffset and strokeDasharray values for each path to the same value.

const paths = document.getElementsByTagName('path');
const strokes = [];
let j = 0;

for (let i = 0; i < paths.length; i++) {
  strokes[i] = paths[i].getTotalLength();
  paths[i].style.strokeDasharray = paths[i].getTotalLength();
  paths[i].style.strokeDashoffset = paths[i].getTotalLength();
}
Copy the code

Then use the animate method to dynamically update the strokeDashoffset value for each path.

function strokeLetter(letter, pathLen) {
  letter.animate([{ strokeDashoffset: pathLen }, { strokeDashoffset: 0}, {duration: pathLen * 7.fill: 'forwards',
  }).onfinish = function() {
    j++;
    strokeLetter(paths[j], paths[j].getTotalLength());
  };
}
Copy the code

Web Animations provide animate methods that have similar properties to animation methods in CSS3. Compared with Animations, Web Animations are more flexible and convenient. For example, they provide callback methods.

Finally, call this method so that each path comes out from left to right, and the entire writing animation is complete.

strokeLetter(paths[0], strokes[0]);
Copy the code

Finally, I will share a more interesting example of using SVG for animation: without relying on any library to create their own visual data map, the author of this article used SVG to achieve a real map loading animation, you can go to watch and learn.

Reference article:

  1. SVG documents
  2. viewBox
  3. Web Animations API
  4. The Animate method for Web Animations
  5. SVG animation is used for stroke and text writing
  6. The SVG ViewBox

Finally, the github address for this series of projects is Native Web-Projects. Welcome to Star. My personal website: YTP ‘room, welcome you to visit me when you are free.

This article belongs to personal original, reprint please indicate the source.