|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
body { font: 12px Arial;} |
|
|
|
path { |
|
stroke-width: 2; |
|
fill: none; |
|
} |
|
|
|
.axis path, |
|
.axis line { |
|
fill: none; |
|
stroke: grey; |
|
stroke-width: 1; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
a {text-decoration:none ; color:#77f} |
|
a:hover {text-decoration:underline} |
|
#retrieval-time { font-size: 0.7em; color:#333 } |
|
|
|
</style> |
|
<body> |
|
<h2 align="center"><a target="_blank" href="http://twister.net.co">Twister</a> daily traffic</h2> |
|
<h4 align="center"> |
|
source: <a target="_blank" href="https://twisterio.com/statistics">TwisterIO</a> |
|
<span id="retrieval-time"></span> |
|
</h4> |
|
<a href="https://gist.github.com/thedod/12c2e8a92d521144e146"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/a6677b08c955af8400f44c6298f40e7d19cc5b2d/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677261795f3664366436642e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png"></a> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
|
|
<script> |
|
// code from https://stackoverflow.com/questions/20017699/ |
|
var w = window, |
|
d = document, |
|
e = d.documentElement, |
|
g = d.getElementsByTagName('body')[0], |
|
graph_width = (w.innerWidth || e.clientWidth || g.clientWidth)-23, |
|
graph_height = (w.innerHeight || e.clientHeight|| g.clientHeight)-115; |
|
margin = {top: 30, right: 80, bottom: 30, left: 80}, |
|
width = graph_width - margin.left - margin.right, |
|
height = graph_height - margin.top - margin.bottom; |
|
|
|
var parseDate = d3.time.format("%Y-%m-%d").parse; |
|
|
|
var x = d3.time.scale().range([0, width]); |
|
var yright = d3.scale.linear().range([height, 0]); |
|
var yleft = d3.scale.linear().range([height, 0]); |
|
|
|
var xAxis = d3.svg.axis().scale(x) |
|
.orient("bottom").ticks(4).tickFormat(d3.time.format('%m/%d')); |
|
|
|
var yAxisLeft = d3.svg.axis().scale(yleft) |
|
.orient("left").ticks(16); |
|
|
|
var yAxisRight = d3.svg.axis().scale(yright) |
|
.orient("right").ticks(16); |
|
|
|
var valueline = d3.svg.line() |
|
.x(function(d) { return x(d.date); }) |
|
.y(function(d) { return yright(d.posts_per_user); }); |
|
|
|
var valueline2 = d3.svg.line() |
|
.x(function(d) { return x(d.date); }) |
|
.y(function(d) { return yleft(d.num_user); }); |
|
|
|
var svg = d3.select("body") |
|
.append("svg") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + margin.bottom) |
|
.append("g") |
|
.attr("transform", |
|
"translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
// Get the data |
|
|
|
d3.json("https://twisterio.com/statistics?needjson=true", function(error, json) { |
|
d3.select('#retrieval-time').text(d3.time.format.utc('%Y-%m-%d, %H:%M UTC')(new Date())); |
|
var data = json.data; |
|
data.forEach(function(d) { |
|
d.date = parseDate(d.date); |
|
d.num_post = +d.num_post; |
|
d.num_user = +d.num_user; |
|
d.posts_per_user = d.num_user&&d.num_post/d.num_user||0; |
|
}); |
|
|
|
// Scale the range of the data |
|
x.domain(d3.extent(data, function(d) { return d.date; })); |
|
yright.domain([0, d3.max(data, function(d) { |
|
return Math.max(d.posts_per_user); })]); |
|
yleft.domain([0, d3.max(data, function(d) { |
|
return Math.max(d.num_user); })]); |
|
|
|
svg.append("path") // Add the valueline path. |
|
.style("stroke", "steelblue") |
|
.attr("d", valueline(data)); |
|
|
|
svg.append("path") // Add the valueline2 path. |
|
.style("stroke", "red") |
|
.attr("d", valueline2(data)); |
|
|
|
svg.selectAll(".tooltip") |
|
.data(data) |
|
.enter().append("a") |
|
.attr("class", "tooltip") |
|
.attr("href","#") |
|
.attr("title", function(d) { |
|
return d3.time.format.utc('%Y-%m-%d')(d.date) + ":\n" + |
|
+ d.num_post + " twists\nby " + |
|
+ d.num_user + " users\n(" + |
|
+ d.posts_per_user.toFixed(2) +" twists/user)" |
|
}).append("circle") |
|
.attr("r", 3) |
|
.style("fill","steelblue") |
|
.attr("cx", function(d) { return x(d.date); }) |
|
.attr("cy", function(d) { return yright(d.posts_per_user); }); |
|
// add the 2nd cirlce as a child to reuse the tooltip (cheap. Eh?) |
|
svg.selectAll(".tooltip").append("circle") |
|
.attr("r", 3) |
|
.style("fill","red") |
|
.attr("cx", function(d) { return x(d.date); }) |
|
.attr("cy", function(d) { return yleft(d.num_user); }); |
|
|
|
svg.append("g") // Add the X Axis |
|
.attr("class", "x axis") |
|
.attr("transform", "translate(0," + height + ")") |
|
.call(xAxis); |
|
|
|
svg.append("g") |
|
.attr("class", "y axis") |
|
.style("fill", "red") |
|
.call(yAxisLeft) |
|
.append("text") |
|
.attr("transform", "rotate(-90)") |
|
.attr("y", "-6em") |
|
.attr("dy", ".71em") |
|
.style("text-anchor", "end") |
|
.text("Active users"); |
|
|
|
|
|
svg.append("g") |
|
.attr("class", "y axis") |
|
.attr("transform", "translate(" + width + " ,0)") |
|
.style("fill", "steelblue") |
|
.call(yAxisRight) |
|
.append("text") |
|
.attr("transform", "rotate(-90)") |
|
.attr("y", "4em") |
|
.attr("dy", ".71em") |
|
.style("text-anchor", "end") |
|
.text("Twists/user"); |
|
|
|
}); |
|
|
|
</script> |
|
</body> |