Dynamic renderings (lag at the beginning of animation, wait…) :

If you look closely at the dynamic renderings above, you can see:

  • When a value changes to a new value, it is a gradual process;
  • There is a vertical line at the end of the arc, as a pointer to the dashboard, when the dashboard value changes, there is an elastic animation effect.

At first, I used Echarts to implement the dashboard, but it didn’t meet the above two requirements. So it was changed to d3.js. D3.js is perfect for customizing charts to meet our needs in detail.

Initialize the dashboard

  1. Start by defining an SVG element:

    <svg id="myGauge" width="80" height="108" ></svg>
    Copy the code

    Then, declare some variables for initialization:

    var width=80, 
        height=108.// The height and width of SVG can also be obtained from the width and height attributes of SVG
        innerRadius = 22,
        outerRadius = 30.// Inner and outer radius of the arc
        arcMin = -Math.PI*2/3,
        arcMax = Math.PI*2/3.// Start and end angles of the arc
    Copy the code
  2. Create an Arc method and set all the properties except endAngle. When creating an arc, pass an object containing the endAngle attribute to this method to calculate the SVG path for a given Angle.

    var arc = d3.arc()
        .innerRadius(22)
        .outerRadius(30)
        .startAngle(arcMin)
    Copy the code

    How to set the arc Angle? If you map a circle to a clock, 12 o ‘clock is 0, 3 o ‘clock clockwise is math.pi /2, and 6 o ‘clock counterclockwise is -math.pi. So the arc shape from -math. PI*2/3 to Math.PI*2/3 is shown in the renderings above. Refer to arc.startAngle in the API documentation for more information.

  3. Get the SVG elements and convert the origin to the center of the canvas so that we do not need to specify their positions separately when we create arcs later

    var svg = d3.select("#myGauge")
    var g = svg.append("g").attr("transform"."translate(" + width / 2 + "," + height / 2 + ")");
    Copy the code
  4. Add text (title, value, unit) to dashboard

    // Add the dashboard title
    g.append("text").attr("class"."gauge-title")
        .style("alignment-baseline"."central") // Align relative to the parent element
        .style("text-anchor"."middle") // Text anchor point, centered
        .attr("y".- 45)   // The distance to the center
        .text("CPU Usage");
    // Add the value displayed on the dashboard, declare a variable because it will be updated later
    var valueLabel = g.append("text").attr("class"."gauge-value")
        .style("alignment-baseline"."central") // Align relative to the parent element
        .style("text-anchor"."middle") // Text anchor point, centered
        .attr("y".25)    // The distance to the center
        .text(12.65); 
    // Add a unit of value to the dashboard display
    g.append("text").attr("class"."gauge-unity")
        .style("alignment-baseline"."central") // Align relative to the parent element
        .style("text-anchor"."middle") // Text anchor point, centered
        .attr("y".40)    // The distance to the center
        .text("%");
    Copy the code

    An important advantage of D3 SVG diagrams over Echarts Canvas is the ability to style SVG using CSS. For example, the dashboard title here looks like this:

    .gauge-title{
        font-size: 10px;
        fill: #A1A6AD;
    }
    Copy the code
  5. Add background arc

    // Add background arc
    var background = g.append("path")
        .datum({endAngle:arcMax})  // Pass the endAngle argument to the arc method
        .style("fill"."# 444851")
        .attr("d", arc);
    Copy the code
  6. Add an arc for percentages, where percentage is the percentage to be represented, the decimal from 0 to 1.

    // Calculate the end Angle of the arc
    var currentAngle = percentage*(arcMax-arcMin) + arcMin
    // Add another layer of arc to indicate the percentage
    var foreground = g.append("path")
        .datum({endAngle:currentAngle})
        .style("fill"."# 444851")
        .attr("d", arc);
    Copy the code
  7. Add a pointer marker to the end of the arc

    var tick = g.append("line")
        .attr('class'.'gauge-tick')
        .attr("x1".0)
        .attr("y1", -innerRadius)
        .attr("x2".0)
        .attr("y2", -(innerRadius + 12))  // Define the line position, default is in the center of the arc, 12 is the length of the pointer
        .style("stroke"."#A1A6AD")
        .attr('transform'.'rotate('+ angleToDegree(currentAngle) +') ')
    Copy the code

    The rotate parameter is a degree. Math.PI corresponds to 180, so you need to define an angleToDegree method to convert currentAngle.

So now you have an SVG dashboard, but it’s still. How do you update this dashboard?

Update dashboard

Need to update: arc representing the new percentage; The value below the arc. Changing the value below the arc is simple:

valueLabel.text(newValue)
Copy the code

Updating the arc is a bit more troublesome. The specific idea is to modify the endAngle of the arc and the transform value of the pointer at the end of the arc. In the implementation process, need to use the API:

  • selection.transition:Github.com/d3/d3-trans…
  • transition.attrTween:Github.com/d3/d3-trans…
  • d3.interpolate:Github.com/d3/d3-inter…
  1. Update the arc, whereangleIs the end Angle of the new arc.
    // Update the arc and set the gradient effect
    foreground.transition()
        .duration(750)
        .ease(d3.easeElastic)   // Set the bouncing effect
        .attrTween("d", arcTween(angle)); 
    Copy the code

    arcTweenMethods are defined as follows. It returns adTween animation of the propertymethodsTo make an arc gradient from the current Angle to a new Angle.

    arcTween(newAngle) {
        let self=this
        return function(d) {
            var interpolate = d3.interpolate(d.endAngle, newAngle); // Find an interpolation between the two values
            return function(t) {
                d.endAngle = interpolate(t);    // Calculate interpolation based on transition time t and assign it to endAngle
                return arc(d); // Returns the new "d" attribute value
            };  
        };
    }
    Copy the code

    A more detailed explanation of this method is availableArc TweenComments in.

  2. The principle of updating the pointer at the end of the arc is the same as above, whereinoldAngleIs the end Angle of the old arc.
    // Update the pointer marker at the end of the arc and set the gradient effect
    tick.transition()
        .duration(750)
        .ease(d3.easeElastic)   // Set the bouncing effect
        .attrTween('transform'.function(){ // Set the gradient of the "transform" property as arcTween method above
            var i = d3.interpolate(angleToDegree(oldAngle), angleToDegree(newAngle));    / / get the interpolation
            return function(t) {
                return 'rotate('+ i(t) +') '
            };
        })
    Copy the code

At this point, we have successfully created a dynamically refreshed, brief and beautiful SVG dashboard.

The end of the

Every time I use D3.js, I can’t help but feel how powerful and interesting it is. It’s like a treasure chest that allows us to maximize our needs.

Reference reading:

  • The Arc Tween: bl.ocks.org/mbostock/51…
  • D3 API documentation: github.com/d3/d3/blob/…