preface

The last article introduced the use of path and a brief introduction to common PATH animations. In this article, we’ll look at container elements in SVG and some of the special container features that can be implemented: composite reuse, graphic markup, element textures, element masks, perforation effects, and element fill animations, as illustrated by sample code and instructions.

The articles

Set foot on SVG | construct comprehensive functions and characteristics of SVG based article (a) –

Set foot on SVG | construct comprehensive functions and characteristics of SVG – base (2) of article

Set foot on SVG | construct comprehensive functions and characteristics of SVG – base (3) of article

Container element

The container elements that might be used in daily development are as follows:

  • <a>
  • <defs>
  • <g>
  • <symbol>
  • <marker>
  • <mask>
  • <pattern>

A hyperlink

SVG version hyperlink, used basically the same as Html A tag. Most browsers automatically distinguish between a tags in SVG

Outside chain web page and this page anchor jump

Case 1:

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <! -- Jump to web page -->
    <a class="border" href="https://developer.mozilla.org/en-US/docs/SVG" target="_blank">
      <rect x="10" y="10" width="120" height="80" fill="green" />
    </a>
    <! -- Same as a tag can set the anchor point to jump to the page -->
    <a class="border" xlink:href="#test">
      <text x="20" y="140"
        font-family="Verdana"
        font-size="32">Let me jump</text>
    </a>
  </svg>
  <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
  <div id="test">Hello.</div>
  <br><br><br><br><br><br><br><br><br><br>
Copy the code

Composite reuse of graphic elements

A matchstick figure is composed of head (circle), body (line), hands (line) and feet (line). So if we need to draw more than one matchstick man, in order to avoid drawing the same parts repeatedly, we can use the G or symbol tag to reuse these parts as a whole.

The use of g

The basic usage of g and the priority of attribute stacking

Example 2:

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <! Some attributes set on g elements can be inherited by children of g elements.
    <g id="test1" fill="green" stroke="orange">
      <circle cx="0" cy="0" r="10" fill="transparent"/>
      <! -- -- -- > body
      <path d="M 0 10 l 0 30"></path>,<! -- -- -- > hands
      <path d="M 0 15 l -10 20"></path>
      <path d="M 0 15 l 10 20"></path>
      <! - feet - >
      <path d="M 0 40 l -10 20"></path>
      <path d="M 0 40 l 10 20"></path>
    </g>

    <g id="test2" fill="transparent">
      <circle cx="0" cy="0" r="10" />
      <path d="M 0 10 l 0 30"></path>,<path d="M 0 15 l -10 20"></path>
      <path d="M 0 15 l 10 20"></path>
      <path d="M 0 40 l -10 20"></path>
      <path d="M 0 40 l 10 20"></path>
    </g>

    <! SVG attributes have their own scope, and will use the value closest to them first.
    <! -- use1 circle fill uses circle fill and whole line color uses stroke of g -->
    <use id="use1" x="20" y="120" fill="red" stroke="blue" xlink:href="#test1"></use>
    <! -- use2 circles are filled with g fill and the color of the whole line is the stroke of the use -->
    <use id="use2" x="120" y="120"  fill="red" stroke="blue" xlink:href="#test2"></use>
  </svg>
Copy the code

From this example we can see the following characteristics

  1. begThe graphic elements wrapped by the element are displayed directly
  2. begElements wrapped in graphics can be treated as a wholeuseTo use the
  3. ganduseYou can set graphic properties that will be inherited from the wrapped element
  4. useA node must be given when reusing a graph
  5. Attributes also have their own scope, and in the case of multiple attributes stacked, the closest one will be selected first

It is important to note here that the display properties of SVG can be used in CSS. What would happen if the class set the same property?

Class and set priority in SVG attributes

Example 3:

Several possible scenarios and outcomes are listed below

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <! The same element that sets fill in the attribute also sets fill in the class. The class of the same element has a higher priority -->
    <rect x="0" y="0" width="30" height="30" fill="green" class="fill-red"/>
    <! The child element inherits the fill defined in the parent attribute and sets the fill in the child element class. The child element class has a higher priority -->
    <g fill="green">
      <rect x="0" y="40" width="30" height="30" class="fill-red"/>
    </g>
    <! The child element inherits the fill defined in the parent class and sets the fill in the child element's attribute. Child element attributes have higher precedence -->
    <g class="fill-red">
      <rect x="0" y="80" width="30" height="30" fill="green"/>
    </g>
    <! The child element inherits attributes defined by the parent element class.
    <g fill="green" class="fill-red">
      <rect x="0" y="120" width="30" height="30" />
    </g>
  </svg>
Copy the code

In a word, attributes defined in class are preferred for the same element, and those defined on itself are not. If not, it inherits from the parent element, which also follows the class attribute preference principle.

The use of the symbol

The symbol tag and G can be combined to reuse elements. Unlike G, elements wrapped in symbol are not displayed, and only images within the viewable area are displayed

In example 1gSwitch tosymbol

Example 4:

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <symbol id="test1" fill="green" stroke="orange" viewBox="0 0 200 200">
      <circle cx="0" cy="0" r="10" fill="transparent"/>
      <! -- -- -- > body
      <path d="M 0 10 l 0 30"></path>,<! -- -- -- > hands
      <path d="M 0 15 l -10 20"></path>
      <path d="M 0 15 l 10 20"></path>
      <! - feet - >
      <path d="M 0 40 l -10 20"></path>
      <path d="M 0 40 l 10 20"></path>
    </symbol>
    <use id="use1" x="20" y="120" fill="red" stroke="blue" xlink:href="#test1"></use>
  </svg>
Copy the code

Google, Edge, and Firefox all do this, showing only parts of the viewBox of SVG elements

Defs definition reference

SVG allows us to define graphic elements that need to be reused later. It is recommended that all reference elements that need to be used again be defined within the DEFS element. Doing so increases the legibility and accessibility of SVG content. Graphic elements defined in defS elements are not rendered directly. You can render these elements anywhere in your viewport using the

element.

The main purpose of DEFS is to declare variables and ease reuse. There is no limit to the order or number of elements wrapped within defS

The elements that defS can wrap are: animation elements, descriptive elements, shape elements, structured elements, and gradient elements

After the defS declaration, the id index is available globally, and ids with the same name are not overridden (ids are unique, and the former is preferred). The id is the same as that of a common label.

defsElements defined within are not displayed

Example 5:

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <g id="test1" fill="green" stroke="orange" viewBox="0 0 200 200">
        <circle cx="0" cy="0" r="10" fill="transparent"/>
        <! -- -- -- > body
        <path d="M 0 10 l 0 30"></path>,<! -- -- -- > hands
        <path d="M 0 15 l -10 20"></path>
        <path d="M 0 15 l 10 20"></path>
        <! - feet - >
        <path d="M 0 40 l -10 20"></path>
        <path d="M 0 40 l 10 20"></path>
      </g>
    </defs>
    <use id="use1" x="20" y="120" fill="red" stroke="blue" xlink:href="#test1"></use>
  </svg>
Copy the code

Marker Marker graph of the end bit of a path

A marker element defines an arrow or multilateral marker graph to draw on a particular <path> element, <line> element, <polyline> element, or <polygon> element.

Special attributes:

  • RefX: offset in the x direction
  • RefY: offset in the y direction
  • MarkerWidth: The width of the marker container to control the size of the marker
  • MarkerHeight: The height of the marker container. The size of the marker can be controlled
  • Orient: The rotation Angle of a marker

Marker containers can define viewBox properties. As with SVG elements, a separate coordinate system is generated. MarkerWidth and markerHeight set the width and height of the container. Same as width and height in SVG. Except that markerWidth and markerHeight do not have specific units. The specific length and width are related to the unit length of the SVG coordinate system. Classic nesting dolls.

What needs to be noted here is that the initial direction of marker coordinate system is related to the derivative direction of the line. The X-axis direction of the marker coordinate system, the derivative direction of the same line (tangent direction in the case of a curve). The y axis is rotated 90° counterclockwise by the x axis.

See the following figure for details

Simple marker

Example 6:

Marker can be applied at the beginning, connection and end of the line respectively

Stroke-width increases the size of the marker, which is also within the regular range of the stroke

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <marker id="Triangle" viewBox="0 0 10 10." " refX="1" refY="5"
          markerWidth="4" markerHeight="4" orient="auto">
        <path d="M 0 0 L 10 5 L 0 10 z" fill="orange"/>
      </marker>
      <marker id="rect" viewBox="0 0 10 10." " refX="1" refY="5"
          markerWidth="4" markerHeight="4" orient="auto">
        <rect x="0" y="0" width="10" height="10" fill="blue"></rect>
      </marker>
      <marker id="circle" viewBox="0 0 10 10." " refX="1" refY="5"
          markerWidth="4" markerHeight="4" orient="auto">
        <circle cx="5" cy="5" r="5" fill="red"></circle>
      </marker>
    </defs>
    <! Marker at the end -->
    <line x1="10" y1="20" x2="150" y2="20" stroke="orange"  marker-end="url(#Triangle)"/>
    <! -- Apply marker at the beginning and stroke-width will increase the size of marker -->
    <line x1="10" y1="40" x2="150" y2="40" stroke="red" stroke-width="3"  marker-start="url(#circle)"/>
    <! -- Apply marker at connection -->
    <polyline fill="none" stroke="blue" points="10 '60 s, 150, 60, 150100, 180100" marker-mid="url(#rect)"/>
    <! -- Three different markers are used -->
    <polyline fill="none" transform="translate(0,60)" stroke="blue" points="10 '60 s, 150, 60, 150100, 180100" marker-start="url(#circle)" marker-mid="url(#rect)" marker-end="url(#Triangle)"  />
  </svg>
Copy the code

The pattern texture

Content drawn within the pattern content can be filled as a texture for fill or stroke. It is called a texture because the filled parts are tiled until they fill the entire content.

Properties:

  • X: the x coordinate
  • Y: the y coordinate
  • Width: width of the pattern container
  • Height: Height of the pattern container
  • PatternUnits: The coordinate system used by the Pattern container
  • PatternContentUnits: The coordinate system in which the Pattern container draws the content
  • PatternTransform: Transforms pattern, using the same pattern as transform
  • Xlink :href: references external textures
  • PreserveAspectRatio: Display mode. You can set whether to zoom in or zoom out the display area

Simply use Pattern. Fill versus stroke

Example 7:

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <pattern id="Pattern0" x="0" y="0" width="1" height="1">
        <rect x="0" y="0" width="80" height="80" fill="skyblue" stroke="red"/>
        <circle cx="40" cy="40" r="30" fill="green" stroke="yellow">
      </pattern>
    </defs>
    <! -- Rectangle fill texture -->
    <rect fill="url(#Pattern0)" x="0" y="0" width="100" height="100" stroke="red"/>
    <! -- Circle fill texture -->
    <circle cx="100" cy="140" r="50" fill="url(#Pattern0)" stroke="red"/>
    <! -- Non-closed patterns cannot use pattern for stroke -->
    <line x1="80" y1="40" x2="180" y2="40" stroke="url(#Pattern0)" stroke-width="20"></line>
  </svg>

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <! -- Rectangle Stroke fill texture -->
    <rect fill="red" x="60" y="25" width="80" height="80" stroke="url(#Pattern0)" stroke-width="40"/>
    <! -- Closed path fill texture -->
    <path d="M 10 160 l 100 0 l 0 40 Z" stroke="url(#Pattern0)" stroke-width="40"></path>>
  </svg>
Copy the code

We can see that tiling effect does not appear in Figure 1, because the pattern drawn in the Pattern container does not occupy the entire pattern container, and tiling is carried out according to the contents of the pattern container.

In the example, the size of the Pattern container is equal to the size of the applied shapes (rectangles and circles), so the parts of the Pattern container that are not drawn are left blank

Coordinate system of pattern container

In the example above, the texture looks chaotic, but it has a rule of its own. The relationship between the region of the Pattern container and the painted content will be explained in detail below.

The Pattern container has its own coordinate system with the same rules as SVG. You can control this with two properties: patternUnits and patternContentUnits

patternUnits

PatternUnits are used to set which coordinate system the Pattern container applies to

Values can be used:

  • UserSpaceOnUse: Coordinate system of the graph to be applied with the texture
  • ObjectBoundingBox (default): Use a separate coordinate system. The coordinate system is established with the size of the graph to which the texture is applied as a reference. The range of the viewable area is defined as a percentage, usually 0-1 in this coordinate system. That’s setting a viewBox=”0, 0, 1, 1″.

patternContentUnits

PatternContentUnits are used to set the coordinate system to which the graphic elements defined in the Pattern container apply

Values can be used:

  • UserSpaceOnUse (default): Coordinate system to which the image to be applied with this texture
  • ObjectBoundingBox: Use a separate coordinate system. The coordinate system is established with the size of the graph to which the texture is applied as a reference. The range of the viewable area is defined as a percentage, usually 0-1 in this coordinate system. That’s setting a viewBox=”0, 0, 1, 1″.

These two properties will be better understood through the following examples

Both use objectBoundingBox to implement adaptive tiling

Example 8:

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <! Change texture size with container size -->
      <! The container size is 0.5 times that of the applied shape (n * 0.5).
      <pattern id="Pattern5" x="0" y="0" width="5" height="5" patternContentUnits="objectBoundingBox">
        <! Width: n * 0.02-->
        <rect x="0" y="0" width="0.5" height="0.5" fill="skyblue" stroke="red" stroke-width="0.01"/>
        <! -- cx: n * 0.25cy: n * 0.25r: n * 0.2stroke: n * 0.01-->
        <circle cx="0.25" cy="0.25" r="2" fill="green" stroke="yellow" stroke-width="0.01">
      </pattern>
    </defs>
    <! -- rectangle with width and height of 200, whose reference value is 100 -->
    <rect fill="url(#Pattern5)" stroke="black" x="0" y="0" width="200" height="200"/>
  </svg>
  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <! -- a pattern with width and height of 100 -->
    <rect fill="url(#Pattern5)" stroke="black" x="0" y="0" width="100" height="100"/>
  </svg>
Copy the code

Mask the mask

In SVG, you can point to a transparent mask layer composed with the current object to form a background. The transparent mask layer can be any other graphic object or <g> element. The mask element is used to define such a mask element. The attribute mask is used to refer to a mask element.

Proprietary attributes:

  • X: the x coordinate
  • Y: the y coordinate
  • Width Mask Specifies the width of the container. The default value is 120%
  • Height: mask The height of the container. The default value is 120%
  • MaskUnits: Coordinates used by the mask container (same pattern)
  • MaskContentUnits: Coordinates used by the mask content area (same pattern)

The color of the graphic in the mask does not change the color of the applied element. The color inside the mask is more transparent as it is closer to #FFFFFF (the color of the active element is more obvious after the composition), and less transparent as it is closer to #000000 (the color of the active element is lighter and less obvious after the composition). Through this feature can achieve the effect of perforation.

Mask color effect

Example 9:

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <mask id="Mask1">
        <! -- The color of the graph in the mask does not change the color of the element, but only affects the transparency of the mask. The closer it is to white, the more transparent it is.
        <rect x="0" y="0" width="200" height="200" fill="#FF0000" />
        <circle cx="100" cy="100" r="50" fill="#FFFFFF" />
      </mask>
    </defs>
    <rect x="0" y="0" width="200" height="200" fill="green" mask="url(#Mask1)"/>
  </svg>
Copy the code

Perforation is achieved through mask

Example 10:

Make a circle in the center of the red rectangle, through which you can see the blue rectangle behind it

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <mask id="Mask3">
        <! -- Center left blank -->
        <rect width="100%" height="100%" fill="#FFFFFF"/>
        <circle cx="100" cy="100" r="50" fill="# 000000" >
      </mask>
    </defs>
    <! -- Bottom blue rectangle -->
    <rect x="0" y="0" width="200" height="200" fill="blue" />
    <! -- Empty red rectangle in center -->
    <rect x="0" y="0" width="200" height="200" fill="red" mask="url(#Mask3)"/>
  </svg>
Copy the code

Fill animation through mask

Example 11:

Given a mask at a fixed position, the dynamic filling effect can be realized by changing the position relationship between the acting element and the mask

Animations here are made quickly with the help of the Anime library

Love the SVG


      <! DOCTYPEsvg PUBLIC "- / / / / W3C DTD SVG 1.1 / / EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1641870835466" id="like" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2888" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M667.786667 117.333333C832.864 117.333333 938.666667 249.706667 938.666667 427.861333 C0 138.250667-125.098667 290.506667-371.573334 461.589334a96.768 96.768 0 0 1-110.186666 0C210.432 718.368 85.333333 566.112 85.333333 427.861333 85.333333 249.706667 191.136 117.333333 356.213333 117.333333c59.616 0 100.053333 20.832 155.786667 68.096C567.744 138.176 608.170667 117.333333 667.786667 117.333333z" p-id="2889"></path></svg>
Copy the code

The implementation code is as follows:

  <svg class="border" width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <mask id="Mask5">
        <use href=".. /.. /.. /static/like.svg#like" fill="#FFFFFF" ></use>
      </mask>
    </defs>
    <rect id="rect" x="0" y="180" width="200" height="200" fill="#E91E63"  mask="url(#Mask5)" />
    <use href=".. /.. /.. /static/like.svg#like" fill="transparent" stroke="#E91E63" stroke-width="20"></use>
  </svg>
  <div class="input">
    <div>Enter 0-100</div>
    <input type="text" onchange="setLikeValue(event)">
  </div>
Copy the code
    function setLikeValue(e){
      const value = e.target.value;
      const reg = / ^ [0-9] + $/;
      if(! reg.test(value) || +value >100) return
      // The initial y - height
      anime({
        targets: '#rect'.y:180 - (+value/100) * 160
      });
    }
Copy the code

The effect is as follows:

Write in the last

The updates this time were a little slow, which exceeded my expectation. I planned to finish all the updates in February, but I found many problems when I looked back at the notes I had written before, and it took a lot of time to revise the case and sort out the copy.

This month is definitely too late, I will try to finish updating this series as soon as possible, just to review and review, if there is something wrong in the article, you are welcome to correct it, I will revise it in time.

The resources

Source: MDN