cloudvisio
Version:
Visual Representation of cloud data
125 lines (100 loc) • 3.9 kB
JavaScript
// dependencies
var d3 = require('d3'),
arc = d3.svg.arc();
var pie = function( self ) {
this.self = self;
// setup options
self.set( this.defaults );
// set axis
self._axisSchema( this.schema );
};
pie.prototype = {
layout: "pie",
schema: {
label: "string",
value: "number"
},
defaults: {
r : 1500, // radius, height/2
ir : 0,
textOffset: 500
},
constructor: pie,
render: function( append ){
var width = 4000, // internal (non-customizable) width
height = 3000, // internal (non-customizable) height
self = this.self,
data = this.data();
// Insert an svg:svg element (with margin) for each row in our dataset. A
// child svg:g element translates the origin to the pie center.
var svg = d3.select( self.el + " "+ self.options.container)
.data( data ) //associate our data with the document
.append("svg:g")
.attr("transform", "translate(" + width/2 + "," + height/2 + ")");
// add pie group
var pie = d3.layout.pie() //this will create arc data for us given a list of values
.value(function(d) { return d.value; }) // Binding each value to the pie
.sort( function(d) { return null; } );
// Select all <g> elements with class slice (there aren't any yet)
var arcs = svg.selectAll("g.slice")
// Associate the generated pie data (an array of arcs, each having startAngle,
// endAngle and value properties)
.data(pie)
// This will create <g> elements for every "extra" data element that should be associated
// with a selection. The result is creating a <g> for every object in the data array
.enter()
// Create a group to hold each slice (we will have a <path> and a <text>
// element associated with each slice)
.append("svg:g")
.attr("class", "slice"); //allow us to style things in the slices (like text)
// The data for each svg:svg element is a row of numbers (an array). We pass
// that to d3.layout.pie to compute the angles for each arc. These start and end
// angles are passed to d3.svg.arc to draw arcs! Note that the arc radius is
// specified on the arc, not the layout.
var slices = arcs.append("svg:path")
.attr("alt", function(d) { return d.data.label; })
.attr("d", arc
.innerRadius( self.options.ir )
.outerRadius( self.options.r )
)
.style("fill", function(d, i) { return self.color( i ); });
// animate slices
slices.transition()
.ease("cubic")
.duration(2000)
.attrTween("d", this.tweenPie);
var label = arcs.append("svg:text")
.style("font-size", function(d) { return Math.max( 1, (d.data.value/100) ) * 15; }) //add a label to each slice
.attr("fill", "white")
.attr("transform", function(d, i) { //set the label's origin to the center of the arc
//we have to make sure to set these before calling arc.centroid
d.innerRadius = self.options.r/2;
d.outerRadius = self.options.r;
return "translate(" + arc.centroid(d) + ")"; //this gives us a pair of coordinates like [50, 50]
})
.attr("text-anchor", "middle") //center the text on it's origin
.text(function(d, i) { return d.data.label; }) //get the label from our original data array
.style("opacity", 0)
.transition().ease("cubic").duration(2000).style("opacity", 1);
//.transition().ease("cubic").duration(2000).attrTween("opacity", d3.interpolateNumber(0, 100) );
},
data: function (){
var self = this.self,
data = [];
var label = self._axis.label,
value = self._axis.value;
data = self.models.map(function( data, i ){
return { label: data[label], value: data[value] };
});
return [data];
},
// helpers
tweenPie: function(b) {
b.innerRadius = 0;
var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
return function(t) {
return arc(i(t));
};
}
};
module.exports = pie;