|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<head> |
|
<title>D3 Async Arc Progress Gauge / Meter</title> |
|
<style> |
|
|
|
.progress-meter .background { |
|
fill: #ddd; |
|
} |
|
|
|
.progress-meter .foreground { |
|
fill: rgb(192, 192, 192); |
|
} |
|
|
|
.progress-meter text { |
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; |
|
font-size: 24px; |
|
font-weight: bold; |
|
} |
|
|
|
</style> |
|
</head> |
|
<body> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> |
|
<script> |
|
|
|
// be sure to check out the console logs to see the async events! |
|
|
|
var width = 960, |
|
height = 500, |
|
twoPi = 2 * Math.PI, |
|
progress = 0, |
|
total = 0, |
|
formatPercent = d3.format(".0%"); |
|
|
|
var arc = d3.svg.arc() |
|
.startAngle(0) |
|
.innerRadius(180) |
|
.outerRadius(240); |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height) |
|
.append("g") |
|
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); |
|
|
|
var meter = svg.append("g") |
|
.attr("class", "progress-meter"); |
|
|
|
meter.append("path") |
|
.attr("class", "background") |
|
.attr("d", arc.endAngle(twoPi)); |
|
|
|
// if you're going off Bostock's original ArcTween example |
|
// (http://bl.ocks.org/mbostock/5100636), you would bind the arc angle |
|
// to the SVG as a data attribute like this: |
|
// |
|
// meter.append("path") |
|
// .datum({endAngle: twoPi}) |
|
// .attr("class", "background") |
|
// .attr("d", arc); |
|
|
|
var foreground = meter.append("path") |
|
.attr("class", "foreground"); |
|
|
|
var text = meter.append("text") |
|
.attr("text-anchor", "middle") |
|
.attr("dy", ".35em"); |
|
|
|
// = = = = = Breaking off from Bostock's example = = = = = |
|
|
|
// used to to create dummy data |
|
var generateDurations = function(numberOfFiles) { |
|
var i = 0, durations = []; |
|
|
|
for(i=0; i<numberOfFiles; i++) { |
|
durations.push(Math.floor(Math.random() * 3000)); |
|
} |
|
return durations; |
|
} |
|
|
|
var count = 0; |
|
var update = function(fileNumber) { |
|
console.log("File "+ (fileNumber+1) + " downloaded."); |
|
count++; |
|
|
|
var interp = d3.interpolate(progress, count / total); |
|
d3.transition().duration(400).tween("progressName", function() { |
|
return function(t) { |
|
progress = interp(t); |
|
foreground.attr("d", arc.endAngle(twoPi * progress)) |
|
.style("fill", function() { |
|
// not necessary -- just makes the arc darker as it progresses |
|
var gray = Math.floor(12 - (12*progress)) * 16; |
|
return "rgb("+ gray +","+ gray +","+ gray +")"; |
|
}); |
|
text.text(formatPercent(progress)); |
|
}; |
|
}); |
|
|
|
if(count >= total) { |
|
meter.transition().delay(250).attr("transform", "scale(0)"); |
|
} |
|
}; |
|
|
|
var initialize = function() { |
|
var numberOfFiles = 20; |
|
var fileDurations = generateDurations(numberOfFiles); |
|
|
|
total = numberOfFiles; |
|
|
|
var i = 0; |
|
for(i=0; i<fileDurations.length; i++) { |
|
console.log("Setting a "+ fileDurations[i] + "ms timeout for File "+ (i+1)) |
|
|
|
setTimeout(function(that) { |
|
// using a closure to capture the value of i at this moment in the loop |
|
return function() { |
|
update(that); |
|
}; |
|
}(i), fileDurations[i]); |
|
} |
|
}(); |
|
|
|
</script> |