这是我的问题:我有一个包含以下列的CSV文件
我想制作一个动态泡泡D3.js图表。每个气泡应代表一个项目,我希望用户可以按类型,所有者或状态对它们进行排序。我found一个运行良好的脚本,除了它从CSV中的每一行创建一个气泡。我正试图找到一种方法来“复制”气泡,当数字< 1但直到现在我还没找到...
你有什么建议?我应该使用D3.js吗? jQuery的?其他
以下是代码:
d3.csv('data/test.csv', function (error, data) { var width = 600, height = 600; var fill = d3.scale.ordinal().range(['#827d92','#827354','#523536','#72856a','#2a3285']) var svg = d3.select("#chart").append("svg") .attr("width", width) .attr("height", height); _.each(data, function (elem) { elem.radius = 5; elem.x = _.random(0, width); elem.y = _.random(0, height); }); var padding = 2; var maxRadius = d3.max(_.pluck(data, 'radius')); function getCenters(vname, w, h) { var nodes = [], c =[], result = {}; var v = _.uniq(_.pluck(data, vname)); var l = d3.layout.treemap().size([w, h]).ratio(1/1); _.each(v, function (k, i) { c.push({name: k, value: 1}); }); nodes = l.nodes({children: c})[0].children; for (var i = 0; i < nodes.length; i++) { result[nodes[i].name] = nodes[i]; } return result; } var nodes = svg.selectAll("circle") .data(data); nodes.enter().append("circle") .attr("class", "node") .attr("cx", function (d) { return d.x; }) .attr("cy", function (d) { return d.y; }) .attr("r", 2) .style("fill", function (d) { return fill(d.cat_int); }) .on("mouseover", function (d) { showPopover.call(this, d); }) .on("mouseout", function (d) { removePopovers(); }) nodes.transition().duration(1000) .attr("r", function (d) { return d.radius; }) var force = d3.layout.force() .charge(0) .gravity(0) .size([width, height]) draw('cat_int'); $( ".btn" ).click(function() { draw(this.id); }); function draw (varname) { var foci = getCenters(varname, 600, 600); force.on("tick", tick(foci, varname, .45)); labels(foci) force.start(); } function tick (foci, varname, k) { return function (e) { data.forEach(function(o, i) { var f = foci[o[varname]]; o.y += ((f.y + (f.dy / 2)) - o.y) * k * e.alpha; o.x += ((f.x + (f.dx / 2)) - o.x) * k * e.alpha; }); nodes .each(collide(.1)) .attr("cx", function (d) { return d.x; }) .attr("cy", function (d) { return d.y; }); } } function labels (foci) { svg.selectAll(".label").remove(); svg.selectAll(".label") .data(_.toArray(foci)).enter().append("text") .attr("class", "label") .text(function (d) { return d.name }) .attr("transform", function (d) { return "translate(" + (d.x + (d.dx / 2)) + ", " + (d.y + 20) + ")"; }); } function removePopovers () { $('.popover').each(function() { $(this).remove(); }); } function showPopover (d) { $(this).popover({ placement: 'auto top', container: 'body', trigger: 'manual', html : true, content: function() { return "Category: " + d.cat_int + "<br/> Owner: " + d.owner + "<br/>Sate: " + d.state; } }); $(this).popover('show') } function collide(alpha) { var quadtree = d3.geom.quadtree(data); return function(d) { var r = d.radius + maxRadius + padding, nx1 = d.x - r, nx2 = d.x + r, ny1 = d.y - r, ny2 = d.y + r; quadtree.visit(function(quad, x1, y1, x2, y2) { if (quad.point && (quad.point !== d)) { var x = d.x - quad.point.x, y = d.y - quad.point.y, l = Math.sqrt(x * x + y * y), r = d.radius + quad.point.radius + padding; if (l < r) { l = (l - r) / l * alpha; d.x -= x *= l; d.y -= y *= l; quad.point.x += x; quad.point.y += y; } } return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; }); }; } });