nv.models.pie = function() { var margin = {top: 20, right: 20, bottom: 20, left: 20}, width = 500, height = 500, animate = 2000, radius = Math.min(width-(margin.right+margin.left), height-(margin.top+margin.bottom)) / 2, label ='label', field ='y', id = Math.floor(Math.random() * 10000), //Create semi-unique ID in case user doesn't select one color = d3.scale.category20(), showLabels = true, donut = false, title = ''; var lastWidth = 0, lastHeight = 0; var dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'tooltipShow', 'tooltipHide'); function chart(selection) { selection.each(function(data) { var svg = d3.select(this) .on("click", function(d,i) { dispatch.chartClick({ data: d, index: i, pos: d3.event, id: id }); }); var background = svg.selectAll('svg.margin').data([data]); var parent = background.enter(); parent.append("text") .attr("class", "title") .attr("dy", ".91em") .attr("text-anchor", "start") .text(title); parent.append('svg') .attr('class','margin') .attr('x', margin.left) .attr('y', margin.top) .style('overflow','visible'); var wrap = background.selectAll('g.wrap').data([data]); wrap.exit().remove(); var wEnter = wrap.enter(); wEnter .append('g') .attr('class', 'wrap') .attr('id','wrap-'+id) .append('g') .attr('class', 'pie'); wrap .attr('width', width) //-(margin.left+margin.right)) .attr('height', height) //-(margin.top+margin.bottom)) .attr("transform", "translate(" + radius + "," + radius + ")"); var arc = d3.svg.arc() .outerRadius((radius-(radius / 5))); if (donut) arc.innerRadius(radius / 2); // Setup the Pie chart and choose the data element var pie = d3.layout.pie() .value(function (d) { return d[field]; }); var slices = background.select('.pie').selectAll(".slice") .data(pie); slices.exit().remove(); var ae = slices.enter().append("svg:g") .attr("class", "slice") .on('mouseover', function(d,i){ d3.select(this).classed('hover', true); dispatch.tooltipShow({ label: d.data[label], value: d.data[field], data: d.data, index: i, pos: [d3.event.pageX, d3.event.pageY], id: id }); }) .on('mouseout', function(d,i){ d3.select(this).classed('hover', false); dispatch.tooltipHide({ label: d.data[label], value: d.data[field], data: d.data, index: i, id: id }); }) .on('click', function(d,i) { dispatch.elementClick({ label: d.data[label], value: d.data[field], data: d.data, index: i, pos: d3.event, id: id }); d3.event.stopPropagation(); }) .on('dblclick', function(d,i) { dispatch.elementDblClick({ label: d.data[label], value: d.data[field], data: d.data, index: i, pos: d3.event, id: id }); d3.event.stopPropagation(); }); var paths = ae.append("svg:path") .attr('class','path') .attr("fill", function(d, i) { return color(i); }); //.attr('d', arc); slices.select('.path') .attr('d', arc) .transition() .ease("bounce") .duration(animate) .attrTween("d", tweenPie); if (showLabels) { // This does the normal label ae.append("text"); slices.select("text") .transition() .duration(animate) .ease('bounce') .attr("transform", function(d) { d.outerRadius = radius + 10; // Set Outer Coordinate d.innerRadius = radius + 15; // Set Inner Coordinate return "translate(" + arc.centroid(d) + ")"; }) .attr("text-anchor", "middle") //center the text on it's origin .style("font", "bold 12px Arial") .text(function(d, i) { return d.data[label]; }); } // Computes the angle of an arc, converting from radians to degrees. function angle(d) { var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90; return a > 90 ? a - 180 : a; } function tweenPie(b) { b.innerRadius = 0; var i = d3.interpolate({startAngle: 0, endAngle: 0}, b); return function(t) { return arc(i(t)); }; } }); return chart; } chart.margin = function(_) { if (!arguments.length) return margin; margin = _; return chart; }; chart.width = function(_) { if (!arguments.length) return width; if (margin.left + margin.right + 20 > _) { width = margin.left + margin.right + 20; // Min width } else { width = _; } radius = Math.min(width-(margin.left+margin.right), height-(margin.top+margin.bottom)) / 2; return chart; }; chart.height = function(_) { if (!arguments.length) return height; if (margin.top + margin.bottom + 20 > _) { height = margin.top + margin.bottom + 20; // Min height } else { height = _; } radius = Math.min(width-(margin.left+margin.right), height-(margin.top+margin.bottom)) / 2; return chart; }; chart.animate = function(_) { if (!arguments.length) return animate; animate = _; return chart; }; chart.labelField = function(_) { if (!arguments.length) return (label); label = _; return chart; }; chart.dataField = function(_) { if (!arguments.length) return (field); field = _; return chart; }; chart.showLabels = function(_) { if (!arguments.length) return (showLabels); showLabels = _; return chart; }; chart.donut = function(_) { if (!arguments.length) return (donut); donut = _; return chart; }; chart.title = function(_) { if (!arguments.length) return (title); title = _; return chart; }; chart.id = function(_) { if (!arguments.length) return id; id = _; return chart; }; chart.dispatch = dispatch; return chart; }