From: opi Date: Tue, 10 Mar 2015 23:45:02 +0000 (+0100) Subject: Refactor Pie charts. X-Git-Url: https://nos-oignons.net/gitweb/graphnion.git/commitdiff_plain/63c3875c3bc5cf22e59d18561e11c325247d9835 Refactor Pie charts. --- diff --git a/graphnion.js b/graphnion.js new file mode 100644 index 0000000..b4ac1a6 --- /dev/null +++ b/graphnion.js @@ -0,0 +1,161 @@ +(function(window){ + 'use strict'; + + /*global define, module, exports, require */ + var Graphnion = {}; + + Graphnion.pie = function (selector, options) { + return new GraphnionPie(selector, options); + }; + + + /** + * Pie graphs + */ + + function GraphnionPie(selector, options) { + + // Default settings + var defaults = { + type: 'consensus', + size : 150, + colors : { + relays : "#111", + others : "#666" + } + } + // main element + this.selector = selector; + + // option cache + this.options = {}; + options = options || {}; + + this.options.type = options.type || defaults.type; + this.options.size = options.size || defaults.size; + this.options.colors = options.colors || defaults.colors; + this.options.onionoo = options.onionoo; + + + // initialize some attributes + this.init(); + this.callOnionoo(); + } + + Graphnion.version = "0.1"; + + GraphnionPie.prototype = { + constructor: GraphnionPie, + + init : function() { + var self = this; + + this.radius = this.options.size / 2, + this.labelRadius = this.radius - (this.options.size / 10) + this.formatPercent = d3.format(".2%"); + this.arc = d3.svg.arc() + .outerRadius(this.radius - (this.options.size / 10)) + .innerRadius(this.radius - (this.options.size / 4)); + + this.pie = d3.layout.pie() + .sort(null) + .value(function(d) { return d.frac; }); + + switch (this.options.type) { + case 'consensus': + this.field = "consensus_weight_fraction"; + break; + case 'guard': + this.field = "guard_probability"; + break; + case 'middle': + this.field = "middle_probability"; + break; + case 'exit': + this.field= "exit_probability"; + break; + } + }, + + draw : function(frac) { + var self = this; + + var data = [ + { + frac: frac, + color: this.options.colors.relays + }, + { + frac: (1 - frac), + color: this.options.colors.others + } + ]; + + var svg = d3.select(this.selector).append("svg") + .style("margin", "auto") + .attr("width", this.options.size) + .attr("height", this.options.size) + .append("g") + .attr("transform", "translate(" + this.options.size / 2 + "," + this.options.size / 2 + ")"); + + + var text = svg.append("text") + .attr("text-anchor", "middle") + .attr("dy", ".35em") + .text(this.formatPercent(frac)); + + var g = svg.selectAll(".arc") + .data(this.pie(data)) + .enter() + .append("g") + .attr("class", "arc"); + + g.append("path") + .attr("d", this.arc) + .style("fill", function(d) { return d.data.color; }); + + }, + + callOnionoo : function() { + var self = this; + + // Create Onionoo url + var url = "https://onionoo.torproject.org/details?type=relay&fields=fingerprint,nickname," + this.field; + if (typeof this.options.onionoo.contact !== 'undefined') { + url += "&contact=" + this.options.onionoo.contact; + } + else if (typeof this.options.onionoo.family !== 'undefined') { + url += "&family=" + this.options.onionoo.family; + } + + // Load data, and draw graph + d3.json(url, function(error, data) { + if (error) return console.warn(error); + + var frac = self.computeData(data); + self.draw(frac); + }); + }, + + computeData : function(rawData) { + var self = this; + + var frac = 0; + rawData['relays'].forEach(function(d) { + frac += d[self.field]; + }); + return frac; + } + + } + + + if (typeof define === 'function' && define.amd) { + define("Graphnion", ["d3"], Graphnion); + } else if ('undefined' !== typeof exports && 'undefined' !== typeof module) { + module.exports = Graphnion; + } else { + window.Graphnion = Graphnion; + } + +})(window); \ No newline at end of file