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
-
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
-
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.
-
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
-
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
-
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
-
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
-
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…
- Update the arc, where
angle
Is 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
arcTween
Methods are defined as follows. It returns ad
Tween 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.
- The principle of updating the pointer at the end of the arc is the same as above, wherein
oldAngle
Is 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/…