【问题标题】:Colored text and line-breaks for D3 node labelsD3 节点标签的彩色文本和换行符
【发布时间】:2018-11-28 16:27:12
【问题描述】:

我正在处理 D3 图表,但无法正确标记节点(我想将“大小”放在第二行,并将所有文本更改为白色。例如,“Toyota”节点会说“Toyota Motor”,并在下面的新行上显示“61.84”)。

这是我的出发点。我尝试使用 CSV 数据添加一个 pre 块,以便它可以在 JSfiddle 上运行,但我卡住了。

我知道我需要更改此代码才能从 pre 块而不是外部 CSV 获取数据:

d3.text("./car_companies.csv", function(error, text) {

之后,我需要添加一个新的“节点追加”,如下所示:

  node.append("revenue")
  .style("text-anchor", "middle")
  .attr("dy", "1.5em")
  .text(function(d) { return d.revenue.substring(0, d.radius / 3); });

http://jsfiddle.net/nick2ny/pqo1x670/4/

感谢您的任何想法。

【问题讨论】:

    标签: d3.js cvs


    【解决方案1】:

    与问题没有直接关系,但要使用<pre> 元素来保存您的数据,您必须使用:

    var text = d3.select("pre").text();
    

    而不是d3.text()

    回到问题:

    要打印这些值,您只需要:

    node.append("text")
        .attr("dy", "1.3em")
        .style("text-anchor", "middle")
        .style("fill", "white")
        .text(function(d) {
            return d.size;
        });
    

    以您想要的方式调整dy。但是,还有一个额外的问题:您没有在数据数组中填充size。因此,在create_nodes 函数中添加:

    size: data[node_counter].size,
    

    以下是这些更改的代码:

    <!DOCTYPE html>
    <meta charset="utf-8">
    <style type="text/css">
      text {
        font: 10px sans-serif;
      }
      
      pre {
        display: none;
      }
      
      circle {
        stroke: #565352;
        stroke-width: 1;
      }
    </style>
    
    <body>
      <pre id="data">
    Toyota Motor,61.84,Asia,239
    Volkswagen,44.54,Europe,124
    Daimler,40.79,Europe,104
    BMW,35.78,Europe,80
    Ford Motor,31.75,America,63
    General Motors,30.98,America,60
    </pre>
    
      <script src="https://d3js.org/d3.v3.min.js"></script>
      <script>
        Array.prototype.contains = function(v) {
          for (var i = 0; i < this.length; i++) {
            if (this[i] === v) return true;
          }
          return false;
        };
    
    
        var width = 500,
          height = 500,
          padding = 1.5, // separation between same-color nodes
          clusterPadding = 6, // separation between different-color nodes
          maxRadius = 12;
    
        var color = d3.scale.ordinal()
          .range(["#0033cc", "#33cc66", "#990033"]);
    
    
    
        var text = d3.select("pre").text();
        var colNames = "text,size,group,revenue\n" + text;
        var data = d3.csv.parse(colNames);
    
        data.forEach(function(d) {
          d.size = +d.size;
        });
    
    
        //unique cluster/group id's
        var cs = [];
        data.forEach(function(d) {
          if (!cs.contains(d.group)) {
            cs.push(d.group);
          }
        });
    
        var n = data.length, // total number of nodes
          m = cs.length; // number of distinct clusters
    
        //create clusters and nodes
        var clusters = new Array(m);
        var nodes = [];
        for (var i = 0; i < n; i++) {
          nodes.push(create_nodes(data, i));
        }
    
        var force = d3.layout.force()
          .nodes(nodes)
          .size([width, height])
          .gravity(.02)
          .charge(0)
          .on("tick", tick)
          .start();
    
        var svg = d3.select("body").append("svg")
          .attr("width", width)
          .attr("height", height);
    
    
        var node = svg.selectAll("circle")
          .data(nodes)
          .enter().append("g").call(force.drag);
    
    
        node.append("circle")
          .style("fill", function(d) {
            return color(d.cluster);
          })
          .attr("r", function(d) {
            return d.radius
          })
    
    
        node.append("text")
          .attr("dy", ".3em")
          .style("text-anchor", "middle")
          .style("fill", "white")
          .text(function(d) {
            return d.text;
          });
    
        node.append("text")
          .attr("dy", "1.3em")
          .style("text-anchor", "middle")
          .style("fill", "white")
          .text(function(d) {
            return d.size;
          });
    
        function create_nodes(data, node_counter) {
          var i = cs.indexOf(data[node_counter].group),
            r = Math.sqrt((i + 1) / m * -Math.log(Math.random())) * maxRadius,
            d = {
              cluster: i,
              radius: data[node_counter].size * 1.5,
              text: data[node_counter].text,
              size: data[node_counter].size,
              revenue: data[node_counter].revenue,
              x: Math.cos(i / m * 2 * Math.PI) * 200 + width / 2 + Math.random(),
              y: Math.sin(i / m * 2 * Math.PI) * 200 + height / 2 + Math.random()
            };
          if (!clusters[i] || (r > clusters[i].radius)) clusters[i] = d;
          return d;
        };
    
    
    
        function tick(e) {
          node.each(cluster(10 * e.alpha * e.alpha))
            .each(collide(.5))
            .attr("transform", function(d) {
              var k = "translate(" + d.x + "," + d.y + ")";
              return k;
            })
    
        }
    
        // Move d to be adjacent to the cluster node.
        function cluster(alpha) {
          return function(d) {
            var cluster = clusters[d.cluster];
            if (cluster === d) return;
            var x = d.x - cluster.x,
              y = d.y - cluster.y,
              l = Math.sqrt(x * x + y * y),
              r = d.radius + cluster.radius;
            if (l != r) {
              l = (l - r) / l * alpha;
              d.x -= x *= l;
              d.y -= y *= l;
              cluster.x += x;
              cluster.y += y;
            }
          };
        }
    
        // Resolves collisions between d and all other circles.
        function collide(alpha) {
          var quadtree = d3.geom.quadtree(nodes);
          return function(d) {
            var r = d.radius + maxRadius + Math.max(padding, clusterPadding),
              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 + (d.cluster === quad.point.cluster ? padding : clusterPadding);
                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;
            });
          };
        }
      </script>

    【讨论】:

    • 虚幻!非常感谢,杰拉尔多。我将对此进行更多攻击,并且由于您的帮助,我将能够完成它。我真的很感激。
    猜你喜欢
    • 2019-01-15
    • 2013-09-07
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    相关资源
    最近更新 更多