Yet another simple gauge chart using d3 Inspired by Jake Trent's Codepen snippet
To move the pointer needle, type in following code in you javascript console
needle.moveTo(.25)
Yet another simple gauge chart using d3 Inspired by Jake Trent's Codepen snippet
To move the pointer needle, type in following code in you javascript console
needle.moveTo(.25)
var needle; | |
(function(){ | |
var barWidth, chart, chartInset, degToRad, repaintGauge, | |
height, margin, numSections, padRad, percToDeg, percToRad, | |
percent, radius, sectionIndx, svg, totalPercent, width; | |
percent = .65; | |
numSections = 1; | |
sectionPerc = 1 / numSections / 2; | |
padRad = 0.025; | |
chartInset = 10; | |
// Orientation of gauge: | |
totalPercent = .75; | |
el = d3.select('.chart-gauge'); | |
margin = { | |
top: 20, | |
right: 20, | |
bottom: 30, | |
left: 20 | |
}; | |
width = el[0][0].offsetWidth - margin.left - margin.right; | |
height = width; | |
radius = Math.min(width, height) / 2; | |
barWidth = 40 * width / 300; | |
/* | |
Utility methods | |
*/ | |
percToDeg = function(perc) { | |
return perc * 360; | |
}; | |
percToRad = function(perc) { | |
return degToRad(percToDeg(perc)); | |
}; | |
degToRad = function(deg) { | |
return deg * Math.PI / 180; | |
}; | |
// Create SVG element | |
svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom); | |
// Add layer for the panel | |
chart = svg.append('g').attr('transform', "translate(" + ((width + margin.left) / 2) + ", " + ((height + margin.top) / 2) + ")"); | |
chart.append('path').attr('class', "arc chart-filled"); | |
chart.append('path').attr('class', "arc chart-empty"); | |
arc2 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth) | |
arc1 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth) | |
repaintGauge = function (perc) | |
{ | |
var next_start = totalPercent; | |
arcStartRad = percToRad(next_start); | |
arcEndRad = arcStartRad + percToRad(perc / 2); | |
next_start += perc / 2; | |
arc1.startAngle(arcStartRad).endAngle(arcEndRad); | |
arcStartRad = percToRad(next_start); | |
arcEndRad = arcStartRad + percToRad((1 - perc) / 2); | |
arc2.startAngle(arcStartRad + padRad).endAngle(arcEndRad); | |
chart.select(".chart-filled").attr('d', arc1); | |
chart.select(".chart-empty").attr('d', arc2); | |
} | |
var Needle = (function() { | |
/** | |
* Helper function that returns the `d` value | |
* for moving the needle | |
**/ | |
var recalcPointerPos = function(perc) { | |
var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY; | |
thetaRad = percToRad(perc / 2); | |
centerX = 0; | |
centerY = 0; | |
topX = centerX - this.len * Math.cos(thetaRad); | |
topY = centerY - this.len * Math.sin(thetaRad); | |
leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI / 2); | |
leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI / 2); | |
rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI / 2); | |
rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI / 2); | |
return "M " + leftX + " " + leftY + " L " + topX + " " + topY + " L " + rightX + " " + rightY; | |
}; | |
function Needle(el) { | |
this.el = el; | |
this.len = width / 3; | |
this.radius = this.len / 6; | |
} | |
Needle.prototype.render = function() { | |
this.el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius); | |
return this.el.append('path').attr('class', 'needle').attr('d', recalcPointerPos.call(this, 0)); | |
}; | |
Needle.prototype.moveTo = function(perc) { | |
var self, | |
oldValue = this.perc || 0; | |
this.perc = perc; | |
self = this; | |
// Reset pointer position | |
this.el.transition().delay(100).ease('quad').duration(200).select('.needle').tween('reset-progress', function() { | |
return function(percentOfPercent) { | |
var progress = (1 - percentOfPercent) * oldValue; | |
repaintGauge(progress); | |
return d3.select(this).attr('d', recalcPointerPos.call(self, progress)); | |
}; | |
}); | |
this.el.transition().delay(300).ease('bounce').duration(1500).select('.needle').tween('progress', function() { | |
return function(percentOfPercent) { | |
var progress = percentOfPercent * perc; | |
repaintGauge(progress); | |
return d3.select(this).attr('d', recalcPointerPos.call(self, progress)); | |
}; | |
}); | |
}; | |
return Needle; | |
})(); | |
needle = new Needle(chart); | |
needle.render(); | |
needle.moveTo(percent); | |
})(); |
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<style type="text/css"> | |
.chart-gauge | |
{ | |
width: 400px; | |
margin: 100px auto | |
} | |
.chart-filled | |
{ | |
fill: steelblue; | |
} | |
.chart-empty | |
{ | |
fill: #dedede; | |
} | |
.needle, .needle-center | |
{ | |
fill: #464A4F; | |
} | |
svg { | |
font: 10px sans-serif; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="chart-gauge"></div> | |
<script type="text/javascript" src="d3_gauge.js"></script> | |
<script type="text/javascript"> | |
setInterval(function(){ | |
needle.moveTo(Math.random()); | |
}, 5000); | |
</script> | |
</body> | |
</html> |
Hey @ameyms, very cool. Quick question - to start the dial at 50% instead of 0%, what variables / values would need to be changed? I changed recalcPointerPos.call(this, 0)
on line 109 from 0 to 0.5 and that is where it starts briefly, but then it seems it keeps starting back at 0.
Thanks!
Plz can Anyone help me How can I do this same in reactHook.
Can you update this code for d3 version 4 ?
I tried and I am stuck at this error.
Uncaught TypeError: this.setAttribute is not a function at d3.min.js:2 at pt.Jf [as each] (d3.min.js:4) at pt.Qf [as attr] (d3.min.js:4) at script.js:134 at o (d3.min.js:2) at yn (d3.min.js:2) at gn (d3.min.js:2)