Write in front:

  1. This article is a simple personal learning summary and class notes arrangement. Most of the knowledge points come from the online live courses of “Kaikaiba” and official materials.
  2. As it is still in the front-end learning and entry stage, it is inevitable that there will be deviations in the mastery and understanding of knowledge. Therefore, this article is only a personal record, and please do not use it as a basis for information.

To do a good job, he must sharpen his tools. Before we look at D3’s core manipulation of SVG, we first need to know what SVG is and the basic usage of SVG drawing.

SVG Scalable Vector Graphics is a graphics format for describing two-dimensional vector graphics based on extensible Markup Language (EXTENSIBLE Markup Language). SVG, developed by the W3C, is an open standard.

Draw graphics in SVG

SVG root view

The SVG root view can be thought of as a canvas, and all the drawing is done in SVG. Some parameters need to be configured when SVG is initialized:

  • version: SVG version
  • xmlns: namespace
  • widthheight: SVG canvas for a meal
  • viewBox: View box, always fully displayed on the canvas, where the graphics are proportionally displayed based on the width and height of the view box
<svg version="1.2" 
     xmlns="http://www.w3.org/2000/svg"
     width="400"
     height="400"
     viewBox="0 0 400 400"
     ></svg>
Copy the code

Once the SVG and container are declared, we can draw inside the SVG tag. The common graphics are as follows:

  • rectangular
  • circular
  • Path ==> universal drawing mode
    • A straight line
    • The circular arc
    • Quadratic Bessel curve
    • Continuation of quadratic Bessel curves
    • Cubic Bezier curves

Let’s look at how to draw the above shapes one by one.

rectangular

<! - the rect rectangular rectangular width on the upper left corner point position x | y | height size -- -- >
<rect x="100" y="100" width="400" height="400" fill="#00acec" />
Copy the code

circular

<! Cx | - circle round cy center position radius r - >
<circle cx="300" cy="300" r="100" fill="#00acec" />
Copy the code

Path-line

There are several common attributes for paths (that is, lines) that control the style of paths:

  • fillUsed to control the fill color inside the path (closed curve only works)
  • stroksUsed to control the color of the path line
  • stroke-widthUsed to control the width of the line
  • stroke-dasharrayUsed to control the continuity of lines, often used to draw dashed lines
<! - the path of the path d shape, capital letters for the absolute level, lowercase letters for the relative point starting point: M | M the next point: L | L - >

<path
  d=" M 300 300 L 500 300 "
  fill="none"
  stroke="# 000"
  stroke-width="10"
  stroke-dasharray="30 10"
/>
Copy the code

Path-arc

<! - arc A | A, Such as 300, 300, A 150 M 200 0 0 0 500 x 300 rx ry radius - axis - rotation axis x [0360] large - the arc - whether flag show maximum arc 0 | 1 sweep - where flag arc side 0 | 1 x y end points -- -- >
<path
  d=" M 300 300 A 150 200 20 1 0 500 300 "
  fill="none"
  stroke="# 000"
  stroke-width="5"
/>
Copy the code

Path-quadratic Bezier curves

<! - Q | Q quadratic bezier curve, such as M 200 100 300 400 200 100 100 400 Q are cpx1 cpy1 control points, used to control the degree of curvature of curve 300 of 400 x y are end points -- -- >

<path
  d=" M 100 400 Q 200 100 300 400 "
  fill="none"
  stroke="# 000"
  stroke-width="10"
/>
Copy the code

Continuation of quadratic Bessel curves

The us through Q | Q generates a quadratic bezier curve, if we want then, you need to pass T | T declare next curve of all control points.

<! - the continuation of quadratic bezier T | T, such as T 500 400 x y end point x y end point... -->

<path
  d=" M 100 400 Q 200 100 300 400 T 500 400 700 400 900 400 "
  fill="none"
  stroke="# 000"
  stroke-width="10"
/>
Copy the code

Cubic Bezier curves

Bessel curve and three times the conic except statement parameters into C | C, the only difference is that the control points from one into two

<! - three times bezier curve C | C, For example, M 100 400 C 200 400 200 200 300 200 the above C 200 400 is CPx1 CPy1 control point 1 followed by THE 200 after C 200 400 200 is cpX2 CPy2 control point 2 and the last 300 200 is the end point of x y -->
<path
  d=" M 100 400 C 200 400 200 200 300 200 "
  fill="none"
  stroke="# 000"
  stroke-width="10"
/>
Copy the code

Continuation of the cubic Bezier curve

Same as above, only need to continue through the S | S declare all control points, then through S | S statement of the control points you just need to declare control point 2:

<! - three times the continuation of Bessel curve S | S, such as S 400 400 500 400 400 400 S is cpx2 cpy2 control point is 2 500 400 x y end point -- -- >
<path
  d=" M 100 400 C 200 400 200 200 300 200 S 400 400 500 400 600 200 700 200 "
  fill="none"
  stroke="# 000"
  stroke-width="10"
/>
Copy the code

Graphics containers

The path attributes above all use some of the same attributes, such as fill stroke, etc. It is not elegant to write these repeated attributes in each path tag. Also, if the project is large and there are so many similar path tags, we don’t know which path tag corresponds to which function, it’s not easy for us to manage.

Therefore, D3 provides a graphics container G for unified management of graphics that deal with the same object or task and manage common attributes.

<g fill="none" stroke="# 000">
  <path
    d=" M 100 400 L 200 400 200 200 300 200 400 400 500 400 "
    stroke-width="2"
    stroke-dasharray="3"
  />
  <path
    d=" M 100 400 C 200 400 200 200 300 200 S 400 400 500 400 600 200 700 200 "
    stroke-width="10"
  />
</g>
Copy the code

Set the SVG style

The SVG style is already controlled by properties such as Fill Stroke while drawing the graphics above. Now let’s take an example of controlling the color of SVG graphics to see how to set the SVG style in detail.

Color according to the color area can be divided into “fill area” and “stroke area”

  • fillProperty to control the color of the fill area. The default is black, which is responsible for filling the color inside the graph
  • strokeProperty to control the stroke area, default to None, responsible for stroke and filling the color of the shape outline
<circle cx="300" cy="300" r="200" fill="rgba(255,100,0,0.5)"/>
<circle cx="300"
        cy="300"
        r="200"
        fill="none"
        stroke="#00acec"/>
Copy the code

All of the above are filled with only solid colors. In fact, there are many different colors that can be used:

  • Pure color
  • gradient
    • Linear gradient
    • Radial gradient
  • texture

Gradient – Linear gradient

Declare linearGradient parameters using the linearGradient tag. See MDN for the related API.

Declare the parameters of the gradientTransform inside the tag via the gradientTransform attribute:

  1. rotate(a)Controls the Angle of linear rotation
  2. translate(x,y)Control movement in x and y directions
  3. scale(sx,sy)Controls scaling in x and y directions

Declare the filled node color within the linearGradient with the Stop child tag.

  1. offsetThe offset [0, 1]
  2. stop-colorcolor

Finally, inside the graphics TAB, call the gradient fill color with fill=” URL (# ID)”

<defs>
  <linearGradient
    id="gr"
    gradientTransform="rotate(30)"
  >
    <stop offset="0" stop-color="#fff" />
    <stop offset="0.5" stop-color="#00acec" />
    <stop offset="1" stop-color="#fff" />
  </linearGradient>
</defs>

<circle cx="300" cy="300" r="200" fill="url(#gr)"/>
Copy the code

Gradient – Radial fill

Radial fill is declared via the radialGradient tag, and the rest is exactly the same.

<defs>
  <linearGradient
    id="gr"
    gradientTransform="rotate(30)"
  >
    <stop offset="0" stop-color="#fff" />
    <stop offset="0.5" stop-color="#00acec" />
    <stop offset="1" stop-color="#fff" />
  </linearGradient>
</defs>
<circle cx="300" cy="300" r="200" fill="url(#gr)" />
Copy the code

Texture shading

The interior of the graphics can be textured by drawing SVG graphics or inserting images.

  • Pattern texture shading

    • id
    • ViewBox view box
    • Width Height Specifies the size of the texture element. 100% is recommended
  • Polygon polygon

    • Points: 0,0, 20,50,100 50,80 100,100 80, 100 80,50 100,0 50,20
  • Insert image

    • Href image address
    • X | y position
    • High widht | height width
<polygon points="0,0, 20,50,100 50,80 100,100 80, 100 80,50 100,0 50,20" />
<defs>
  <pattern width="30%" height="30%" viewBox="0 0 100 100" id="pt">
    <! <polygon points="0,0, 20,50,100 50,80 100,100 80, 100 80,50 100,0 50,20"/>
    <image href="./images/rose.jpg" width="100" height="100" />
  </pattern>
</defs>
<circle cx="300" cy="300" r="200" fill="url(#pt)" />
Copy the code

Drawing with D3

Now that you have a basic understanding of how SVG draws graphics and how to set styles, let’s use D3 to manipulate DOM elements and SVG to draw a graphic.

Step1 obtain the main container through the D3 select method.

const main=d3.select('#main')
Copy the code

Step2 Establish SVG and container in main container, and set its related attributes

const svg=main.append('svg')
        .attr('version'.1.2)
        .attr('xmlns'.'http://www.w3.org/2000/svg')
        .attr('width'.'100%')
        .attr('height'.'100%')
        .attr('viewBox'.'- 400-400 800 800)
Copy the code

Step3 create SVG graphics in the SVG container and set related attributes

svg.append('rect')
	.attr('x', -200)
	.attr('y', -100)
	.attr('width'.400)
	.attr('height'.200)
	.attr('fill'.'red')
Copy the code

We can then add various graphics to the SVG container in the same way, but we will find that this way to write a lot of appen methods, a lot of attR methods, is not elegant. Looking back, the overall call logic is the same whether you create an SVG container in main or add graphics to an SVG container. So we can encapsulate this sequence of call logic into a method.

Step4 encapsulates the Render method, which takes a real DOM node as an argument and returns a real handler. This return function takes the element node and node attribute item to be generated as arguments and returns the actual element node.

function Render(dom) { // The actual DOM node is passed in as an argument and returns a handler directly
   return function(shape,option){ // The DOM node you want to generate and the node configuration are passed in as parameters
       const obj=dom.append(shape)
       for(let [key,val] of Object.entries(option)){ 
         	// Iterate over the configured item and assign it to the DOM node object
           obj.attr(key,val)
       }
       return obj 
   }
}
Copy the code

Thus, we can add DOM nodes directly and elegantly using the Render method:

/* Get the main container */
const main = d3.select("#main");
function Render(dom) {
  return function (shape, option) {
    const obj = dom.append(shape);
    for (let [key, val] of Object.entries(option)) {
      obj.attr(key, val);
    }
    return obj;
  };
}

const svg = Render(main)("svg", {
  version: 1.2.xmlns: "http://www.w3.org/2000/svg".width: "100%".height: "100%".viewBox: "- 400-400, 800, 800"});// Get the method to create the DOM node
const draw = Render(svg);
/* Draw a graph... * /
draw("rect", {
  x: -200.y: 0.width: 400.height: 200.fill: "red"}); draw("rect", {
  x: -200.y: 0.width: 400.height: 200.fill: "none".stroke: "# 000"."stroke-width": 40}); draw("rect", {
  x: -200.y: 50.width: 400.height: 60.fill: "antiquewhite"}); draw("path", {
  d: ` M -100 150 L 100 150 `.fill: "none".stroke: "# 000"."stroke-width": 40}); draw("circle", {
  cx: -100.cy: 80.r: 20.fill: "red"}); draw("path", {
  d: ` M 80 90 A 20 20 0 0 1 120 90 `.fill: "red"}); draw("path", {
  d: ` M -200 -200 C -100 -200 -100 0 0 0 S 100 -200 200 -200 `.fill: "none".stroke: "# 000"."stroke-width": 40});Copy the code

The above is an example of SVG drawing using D3 manipulation of the DOM.