var graphs = {}; (function(d3) { graphs.BubblesGraph = function(config) { var width = config.width; var height = config.height; var centerX = width / 2; var centerY = height / 2; var radius = config.radius || 50; var colors = d3.scale.category20().range(); var force = d3.layout.force() .charge(-500) .gravity(0) .size([width, height]); function attachGraphTo(selector) { var svg = d3.select(selector) .append('svg') .attr('width', width) .attr('height', height); d3.json(config.dataUrl, function(error, nodes) { if (error) { android.showToast('failure to load graph'); throw error; } var nodeCount = nodes.length; var maxValue = d3.max(nodes, function(d, i) { return d.max; }); var valueScale = d3.scale.ordinal() .domain(d3.range(maxValue + 1)) .rangePoints([radius * 0.3, radius * 0.8]); var gauge = d3.gauge() .textSuffix(config.textSuffix) .textColor(darkColor) .circleFillGap(0.05) .circleThickness(function(d, i) { return isCenterBubble(d) ? 0.2 : 0.1; }) .circleColor(darkColor) .waveAnimateTime(1000) .waveRiseTime(function(d, i) { return 3000 * valuePercentage(d); }) .waveColor(lightColor) .waveTextColor(darkColor) .x(function(d, i) { return d.x; }) .y(function(d, i) { return d.y; }) .value(0) .valueMaximum(function(d) { return d.max; }) .radius(function(d, i) { d.radius = isCenterBubble(d) ? radius : valueScale(d.max, i); return d.radius; }); var links = []; nodes.push({ name:"total", max: d3.sum(nodes, function(d, i) { return d.max; }), value: d3.sum(nodes, function(d, i) { return d.value; }), center: true, fixed: true, x: centerX, y: centerY }); nodes.forEach(function (d, i) { var link = { source: i, target: nodeCount, value: 1 }; links.push(link); }); force.nodes(nodes) .links(links) .linkDistance(width / 5) .start(); var link = svg.selectAll('.link') .data(links) .enter().append('line') .attr('class', 'link') .style('stroke-width', 5) .style('stroke', darkColor); var node = svg.selectAll('.gauge') .data(nodes) .enter().append('g') .attr('class', 'gauge') .call(force.drag) .call(gauge); node.append('title').text(function(d) { return d.name; }); force.on('tick', function() { link.attr('x1', function(d) { return d.target.x; }) .attr('y1', function(d) { return d.target.y; }) .attr('x2', function(d) { return d.source.x; }) .attr('y2', function(d) { return d.source.y; }); node.attr('transform', function(d, i) { return 'translate(' + (d.x - d.radius) + ',' + (d.y - d.radius) + ')'; }) }); force.on('end', function() { gauge.value(function(d) { return d.value; }); node.call(gauge); }); }); } function darkColor(d, i) { return isCenterBubble(d) ? colors[14] : colors[i * 2]; } function lightColor(d, i) { return isCenterBubble(d) ? colors[15] : colors[i * 2 + 1]; } function isCenterBubble(d, i) { if (config.isCenterBubble) { return config.isCenterBubble(d, i); } return d.center; } function valuePercentage(d, i) { return Math.min(d.value / d.max, 1); } return { attachTo: attachGraphTo } }; })(d3);