多个d3.js强制布局实例

时间:2016-05-21 12:47:16

标签: javascript d3.js

我正在使用http://bl.ocks.org/danielatkin/57ea2f55b79ae686dfc7进行一些修改,效果很好。但是我希望在两个具有不同ID的不同HTML元素中有两个相互独立的实例。但实际发生的是一个人的强制布局正在干扰另一个。

我尝试过:

  1. 将整个代码包装在一个函数中,然后调用它两次,仍然在弄乱。
  2. 使用两个不同的名称制作两个不同的函数,然后调用它们中的每一个,但它也会弄乱布局。
  3. 这些是更新代码的函数:

    function draw (varname) {
          var centers = getCenters(varname, [width, height]);
          force.on("tick", tick(centers, varname));
          labels(centers)
          force.start();
        }
    
    function tick (centers, varname) {
          var foci = {};
          for (var i = 0; i < centers.length; i++) {
            foci[centers[i].name] = centers[i];
          }
          return function (e) {
            for (var i = 0; i < data.length; i++) {
              var o = data[i];
              var f = foci[o[varname]];
              o.y += ((f.y + (f.dy / 2)) - o.y) * e.alpha;
              o.x += ((f.x + (f.dx / 2)) - o.x) * e.alpha;
            }
    
            nodes.each(collide(.2))
              .attr("transform", function(d){ //<-- use transform it's not a g
                return "translate(" + d.x + "," + d.y + ")";
              });
          }
        }
    
    
    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;
                });
              };
    

    也许某些变量或某些元素要么是全局的,要么互相干扰,但我无法弄清楚。需要一些帮助..

    在此处粘贴完整代码:

    开始(&#39;有源&#39);

    function start(type) {
          var data = response.content_affinity.categories;
          for(var i=0; i<data.length; i++)
          {
            data[i]["sentiment"] = data[i].positive_sentiment>55?"Positive":"Negative";
            data[i]["source"] = "twitter";
            data[i]["retweet_count"] = data[i]["share"];
          }
    
          var data2 = response.content_affinity.categories;
          for(var i=0; i<data.length; i++)
          {
            data2[i]["sentiment"] = data2[i].positive_sentiment>55?"Positive":"Negative";
            data2[i]["source"] = "twitter";
            data2[i]["retweet_count"] = data2[i]["share"];
          }
    
          dataAPI = data;
    
          var d3Instances = 0;
          create(data, {id:"#bubble_content_cate_ga"}, d3Instances);
    
          d3Instances++;
          create(data2.slice(0,4), {id:"#bubble_content_cate_ga_2"}, d3Instances);
    
    }
    
    
    function create(data_, obj, d3i) {
    
        var data = data_.concat();
    
        $(obj.id).empty();
    
        var group = size = color = '';
        group = "";
        color = 'sentiment';
        size = "retweet_count";
    
        var colorTheme = {positive:"#6BBA9B", negative:"#6BBA9B", neutral:"#C93946", "default":"#ECF0F1"}
    
    
        var dataAPI, colors;
    
    
        colors = {
    
          sentiment: {
              Positive: "#6BBA9B",
              Neutral: "#ffffff",
              Negative: "#C93946"
            },
            "default": colorTheme["default"] 
        };
        var radius = 75;
        var width = $(obj.id).width();
        var height = $(obj.id).height();
        var fill = d3.scale.ordinal().range(['#FF00CC','#FF00CC','#00FF00','#00FF00','#FFFF00','#FF0000','#FF0000','#FF0000','#FF0000','#7F0000']);
        var svg = d3.select(obj.id).append("svg")
            .attr("width", width)
            .attr("height", height);
            /*var _html = '<div class="row"><div class="col-lg-12 text-center heading-widget">Widget Title</div></div>'
                    +'<div class="row"><div class="col-lg-12 text-center"><button class="groupItems btn button-widget-bubblegraph">Classify</button></div></div>'
            $().prepend(_html);*/
        data = getDataMapping(data, size);
        console.log(data);
        var padding = 5;
        var maxRadius = d3.max(_.pluck(data, 'radius'));
    
        var maximums = {
              retweet_count: d3.max(_.pluck(data, 'retweet_count')),
          volume: d3.max(_.pluck(data, 'volume')),
          lasPrice: d3.max(_.pluck(data, 'lastPrice')),
          standardDeviation: d3.max(_.pluck(data, 'standardDeviation'))
        };
    
        var getCenters = function (vname, size) {
            var centers, map;
            centers = _.uniq(_.pluck(data, vname)).map(function (d) {
              return {name: d, value: 1};
            });
    
            map = d3.layout.treemap().size(size).ratio(1/1);
            map.nodes({children: centers});
    
            return centers;
        };
    
    
    
        var defs = svg.append("defs");
    
        var filter = defs.append("filter").attr("id", "drop-shadow").attr("height", "130%");
        filter.append("feGaussianBlur").attr("in", "SourceAlpha").attr("stdDeviation", 5).attr("result", "blur");
        filter.append("feOffset").attr("in", "blur").attr("dx", 5).attr("dy", 5).attr("result", "offsetBlur"); 
        var feMerge = filter.append("feMerge"); 
        feMerge.append("feMergeNode").attr("in", "offsetBlur") ;
        feMerge.append("feMergeNode").attr("in", "SourceGraphic");
    
    
    
    
            var nodes = svg.selectAll("g")
                .data(data);
    
            var g = nodes.enter().append("g")
              .attr("class", "bubbleParentg_"+d3i)
              .on("mouseover", function(d) {
                showPopover.call(this, d);
              })
              .on("click", function(d) {
                doTheFiltering.call(this, d);
              })
              .on("mouseout", function(d) {
                removePopovers();
              });
    
            g.append("circle")
              .attr("class", function (d, i) { return " circle_"+d.sentiment+" circle_"+i})
    
              .attr("r", function (d) { return d.radius; })
              .style('fill', function(d) {
               return colors["sentiment"][d["sentiment"]];
               })
              .style("filter", "url(#drop-shadow)");
    
    
              g.append("text")
                .attr("dy",".35em")
                .attr("dx",function(d){
                    return "-"+(d.radius-d.radius/5)+"px";
                })
                .attr("fill", "white")
                .text(function(d){
                    return d.category.formatEntity();
                })
                .style("font-size", function(d) { 
                    console.log(this.getComputedTextLength());
                    return Math.min(2 * d.radius, (2 * d.radius - 8) / this.getComputedTextLength() * 12) + "px"; 
                });
    
    
    
        function getDataMapping(data, vname) {
          var max = d3.max(_.pluck(data, vname));
    
          for (var j = 0; j < data.length; j++) {
            //data[j].radius = (vname != '') ? radius * (data[j][vname] / max) : 15;
            data[j].radius = (data.length-2*j+20)*2.5;
            data[j].x = data[j].x ? data[j].x : Math.random() * width;
            data[j].y = data[j].y ? data[j].y : Math.random() * height;
            data[j].sentiment = data[j].sentiment;
          }
    
          return data;
        }
    
    
        var force = d3.layout.force();
    
    
        var tick = function(centers, varname) {
          var foci = {};
          for (var i = 0; i < centers.length; i++) {
            foci[centers[i].name] = centers[i];
          }
          return function (e) {
            for (var i = 0; i < data.length; i++) {
              var o = data[i];
              var f = foci[o[varname]];
              o.y += ((f.y + (f.dy / 2)) - o.y) * e.alpha;
              o.x += ((f.x + (f.dx / 2)) - o.x) * e.alpha;
            }
    
            svg.selectAll("g.bubbleParentg_"+d3i).each(collide(.2))
              .attr("transform", function(d){ //<-- use transform it's not a g
                return "translate(" + d.x + "," + d.y + ")";
              });
          }
        }
    
        draw("");
    
        function draw (varname) {
          var centers = getCenters(varname, [width, height]);
    
          console.log(centers);
          force.on("tick", tick(centers, varname));
          //labels(centers)
          force.start();
        }
    
    
    
    
    
    
        function doTheFiltering(d){
            console.log(data);
            console.log(d);
    
            data.forEach(function(el, i){
                if(el.category == d.category){
                    data[i]["filtering"] = "true";
                }
                else{
                    data[i]["filtering"] = "false";
                }
            });
    
            draw("filtering");
            showInnerCat(d.category);
        }
    
        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;
            });
          };
        }
    
    
      }
    
    
    
    
        function returnTweets(dataPiece){
                return   '<span style="font-weight:800; font-size:17px; display:inline-block;" class="color_yellow"> <i class="fa fa-twitter fa-fw" style="color:#cccccc;"></i> '+dataPiece.count+'&nbsp;&nbsp;&nbsp;</span>'
                         +'<span style="font-weight:800; font-size:17px; display:inline-block;"  class="color_red"> <i class="fa fa-smile-o fa-fw" style="color:#cccccc;"></i> '+Math.round(dataPiece.positive_sentiment)+'%</span>';
    
        }
    
    
    
    
        function removePopovers (a, reinit) {
    
              var _curr = a;
              $('.popover').each(function() {
                $(this).remove();
              }); 
    
        }
    
    
        function showPopover (d) {
    
    
              removePopovers(this, false);
              d3.selectAll("circle").classed("selectedCircle", false);  
              $(this).popover({
                placement: 'auto top',
                container: 'body',
                trigger: 'manual',
                position:"fixed",
                html : true,
                content: function() { 
                  return returnTweets(d);
                }
              });
              $(this).popover('show');
              $(".popover").addClass(d.sentiment+"_border");
    
    
    
        }
    

0 个答案:

没有答案