Skip to content

Instantly share code, notes, and snippets.

@larskotthoff
Last active August 29, 2015 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save larskotthoff/8689540 to your computer and use it in GitHub Desktop.
Save larskotthoff/8689540 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<style>
.container {
width: 100%;
height: 500px;
}
</style>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="progress.js"></script>
</head>
<body>
<div class="container">
<svg id="cp_svg">
</svg>
</div>
<script>
function getRandomRange(min, max) {
return Math.random() * (max - min) + min;
}
var graph = ht.cp;
graph.init("#cp_svg", 800, 500);
graph.labels[0].startValue=0;
graph.labels[0].endValue=300;
graph.setProgress(280);
graph.graph();
setInterval(function(){
graph.setProgress(getRandomRange(200,250));
graph.graph();
},2000);
</script>
</body>
</html>
var ht = ht || {};
ht.cp = (function () {
var svg;
var cp ={};
cp.svgId = '';
cp.dotLabelSettings = new Array();
cp.textLabelSettings = new Array();
cp.arcSettings = [
{
"totalArcAngle":300,
"startAngle":-150,
"endAngle":-150,
//"progressValue":200,
"radius":150,
"thickness":40,
}
];
//settings for labels
cp.labels = [
{
"pointThickness": 3,
"distance": 60,
"textDistance": 30,
"strokeColor": "#888",
"strokeWidth": 0.5,
"textColor": "#777",
"pointColor": "#888",
"textSize": 4,
//"interval":100,
//"precision":2,
"num": 10,
"startValue": 0,
"endValue": 300
}
];
cp.graphTitle = {
"text":"Power",
"size":20,
"color":"#bbb"
}
//styling circular graph elements
cp.graphStyles = {
"progressColor":'#3791ed',
"transitionTiming":1500,
"innerCircle":{
"radius":null,
"lineWidth":0,
"strokeColor":"rgba(200,200,200,0.9)",
"fillColor":"#2e2e2e",
"text":"270",
"textSize":7,
"textColor":"#096ed4"
}
};
cp.init = function (svgId, width, height) {
this.svgId = svgId;
this.setCenter(width,height);
svg = d3.select(svgId)
.attr("height", height)
.attr("width", width)
//.attr("viewBox","0 0 500 500")
//.attr("preserveAspectRatio", "xMidYMid meet")
.append("g")
.attr("transform", "translate("+width/2+","+height/2+")");
//initailize graph styles
this.initGraphStyles();
svg.append("text")
.attr("x",0)
.attr("y",10)
.attr("text-anchor","middle")
.attr("fill",this.graphTitle.color)
.attr("font-size",12)
.attr("id", "progressValue");
};
cp.getSvg = function(){
return d3.select(this.svgId);
}
cp.setCenter = function(width,height){
this.svgCenter = {
cx:0,
cy: 0
}
}
cp.getCenter = function(){
return this.svgCenter;
}
cp.getOneUnit = function(){
return (this.arcSettings[0].totalArcAngle) / (this.labels[0].endValue - this.labels[0].startValue);
}
cp.currentProgress = cp.arcSettings[0].endAngle;
cp.getCurrentProgress = function(){
return this.currentProgress;
}
cp.setProgress = function(val){
var oneUnit = this.getOneUnit();
this.currentProgress = this.arcSettings[0].startAngle + (val * oneUnit);
this.displayValue(val);
}
cp.degreeToRadian = function(deg){
return deg * Math.PI / 180.0;
}
var arc = d3.svg.arc()
.startAngle(function (d) {
return cp.degreeToRadian(d.startAngle);
})
.endAngle(function (d) {
return cp.degreeToRadian(d.endAngle);
})
.innerRadius(function (d) {
return d.radius
})
.outerRadius(function (d) {
return d.thickness + d.radius;
});
cp.bind = function(){
var g;
g = svg.selectAll("g")
.data(this.arcSettings)
.enter().append("g")
.attr("class", "arc");
g.append("path")
.style("fill", this.graphStyles.progressColor)
.attr("d", arc);
}
cp.graph = function(){
this.bind();
selectArcs();
}
cp.initGraphStyles = function(){
//circle that passes through dot labels
svg.append("circle")
.attr("class","dotLabelsCircle")
.attr("cx",0)
.attr("cy",0)
.attr("r",this.arcSettings[0].radius + this.labels[0].distance)
.style("fill","none")
.style("stroke",this.labels[0].strokeColor);
//inncer circle
svg.append("circle")
.attr("class","innerCircle")
.attr("cx",0)
.attr("cy",0)
.attr("r",this.arcSettings[0].radius + this.arcSettings[0].thickness-0.6)
.style("fill",this.graphStyles.innerCircle.fillColor)
.style("stroke","none");
svg.append("text")
.attr("x",0)
.attr("y",-this.arcSettings[0].radius/2)
.attr("text-anchor","middle")
.attr("fill",this.graphTitle.color)
.attr("font-size",this.graphTitle.size)
.text(this.graphTitle.text);
this.drawLabel();
}
function selectArcs() {
d3.selectAll("g.arc > path")
.each(arcTween);
}
function arcTween() {
d3.select(this)
.transition().duration(cp.graphStyles.transitionTiming)
.attrTween("d", tweenArc({ endAngle: cp.getCurrentProgress() }));
}
function tweenArc(b) {
return function (a) {
var i = d3.interpolate(a, b);
for (var key in b) a[key] = b[key]; // update data
return function (t) {
return arc(i(t));
};
};
}
cp.polarToCartesian = function(centerX, centerY, radius, angleInDegrees) {
var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
cp.displayValue = function(val){
svg.select("#progressValue")
.text(val);
}
// i am planning to use this function for drawing the labels
cp.drawLabel = function() {
var textLabelRadius = this.arcSettings[0].radius + this.labels[0].distance + this.labels[0].textDistance;
//invisible circle for label text
// this.drawCircle(this.circularProgressSettings.x, this.circularProgressSettings.y, textLabelRadius, 1, "rgba(0,0,0,1)","none");
label = this.labels[0];
if (label.num) {
interval = (label.endValue - label.startValue) / label.num;
} else {
interval = label.interval;
}
numOfLabels = (label.endValue - label.startValue) / interval;
angleInterval = (this.arcSettings[0].totalArcAngle) / numOfLabels;
labels = new Array();
angle = (-this.arcSettings[0].totalArcAngle/2);
for (var value = label.startValue; value <= label.endValue; value += interval) {
labels.push({
angle: angle,
value: value
});
angle += angleInterval;
}
//console.log(labels);
//loop for label and text
for (i = 0; i < labels.length; i++) {
angle = labels[i].angle;
value = labels[i].value;
if(label.precision == null){
if( value % 1 !== 0) {
value = value.toFixed(2);
}
} else {
value = value.toFixed(label.precision);
}
pointRadius = this.arcSettings[0].radius + label.distance;
DotPoints = this.polarToCartesian(this.getCenter().cx, this.getCenter().cy, pointRadius, angle);
TextPoints = this.polarToCartesian(this.getCenter().cx, this.getCenter().cy, textLabelRadius, angle);
this.dotLabelSettings.push(
{
dotX:DotPoints.x,
dotY:DotPoints.y,
}
);
this.textLabelSettings.push(
{
value:value,
textX:TextPoints.x,
textY:TextPoints.y
}
)
//draw dots here using d3 and the data i that i will be probably binding is this.labelSettings
/**this.drawCircle(DotPoints.x, DotPoints.y,this.circularProgressSettings.label.pointThickness, '', '', this.circularProgressSettings.label.pointColor);
this.set("id",this.getSvgId()+"_label_dot_"+i);
//draw text labels using d3
this.drawText(value, TextPoints.x, TextPoints.y+2, this.circularProgressSettings.label.textSize, 'none', this.circularProgressSettings.label.textColor);
this.set("id",this.getSvgId()+"_label_text_"+i);
*/
}
this.drawDots();
this.drawTextLabels();
}
cp.drawDots = function(){
svg.selectAll("circle.dots")
.style("fill",this.labels[0].pointColor)
.style("stroke","none")
.data(this.dotLabelSettings)
.enter()
.append("circle")
.attr("class","dots")
.attr("r", this.labels[0].pointThickness)
.attr("cx", function(d){
return d.dotX;
})
.attr("cy", function(d){
return d.dotY;
});
}
cp.drawTextLabels = function() {
svg.selectAll("text.dots")
.data(this.textLabelSettings)
.enter()
.append("text")
.attr("class","dots")
.attr("x", function(d) { return d.textX; })
.attr("y", function(d) { return d.textY+5; })
.attr("text-anchor","middle")
.text(function(d) { return d.value; });
}
return cp;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment