在强制布局图d3.js中的矩形内添加文本

时间:2014-04-14 17:02:35

标签: text d3.js force-layout rect

这是我的图...我有矩形节点我想在节点中包含文本。 我试过了

node.append("text").text("hello");

但不起作用。我如何分组我的节点和文本。 我想在节点上添加和编辑功能。编辑文本我该怎么做?

<!DOCTYPE html>
<meta charset="utf-8">
<head>
<title>Force Editor</title>
<!-- <script src="d3.v2.min.js"></script> -->
<script src="http://d3js.org/d3.v2.min.js"></script>
<!-- <script src="jquery-1.8.3.min.js"></script> -->
<style>

body {
  font: 13px sans-serif;
  position: relative;
  width: auto;
  height: auto;
}

.node {
  fill: #000;
  cursor: crosshair;
}

.node_selected {
  fill: #ff7f0e;
  stroke: #ff7f0e;
}

.drag_line {
  stroke: #999;
  stroke-width: 5;
  pointer-events: none;
}

.drag_line_hidden {
  stroke: #999;
  stroke-width: 0;
  pointer-events: none;
}

.link {
  stroke: #999;
  stroke-width: 5;
  cursor: crosshair;
}

.link_selected {
  stroke: #ff7f0e;
}

</style>
<head>
<body>
  <div id="chart">
  </div>
<script>
var width = 1800,
    height = 800,
    fill = d3.scale.ordinal().range(["#ff0000", "#2ca02c","#ff0000"]);

// mouse event vars
var selected_node = null,
    selected_link = null,
    mousedown_link = null,
    mousedown_node = null,
    mouseup_node = null;

// init svg
var outer = d3.select("#chart")
  .append("svg:svg")
    .attr("width", width)
    .attr("height", height)
    .attr("pointer-events", "all");

var vis = outer
  .append('svg:g')
    .call(d3.behavior.zoom().on("zoom", rescale))
    .on("dblclick.zoom", null)
  .append('svg:g')
    .on("mousemove", mousemove)
    .on("mousedown", mousedown)
    .on("mouseup", mouseup);

vis.append('svg:rect')
    .attr('width', width)
    .attr('height', height)
    .attr('fill', 'white');

// init force layout
var force = d3.layout.force()
    .size([width, height])
    .nodes([{}]) // initialize with a single node
    .linkDistance(250)
    .charge(-1500)
    .on("tick", tick)
    ;

// line displayed when dragging new nodes
var drag_line = vis.append("line")
    .attr("class", "drag_line")
    .attr("x1", 0)
    .attr("y1", 0)
    .attr("x2", 0)
    .attr("y2", 0);

// get layout properties
var nodes = force.nodes(),
    links = force.links(),
    node = vis.selectAll(".node"),
    link = vis.selectAll(".link");

// add keyboard callback
d3.select(window)
    .on("keydown", keydown);

redraw();

// focus on svg
// vis.node().focus();

function mousedown() {
  if (!mousedown_node && !mousedown_link) {
    // allow panning if nothing is selected
    vis.call(d3.behavior.zoom().on("zoom"), rescale);
    return;
  }
}

function mousemove() {
  if (!mousedown_node) return;

  // update drag line
  drag_line
      .attr("x1", mousedown_node.x)
      .attr("y1", mousedown_node.y)
      .attr("x2", d3.svg.mouse(this)[0])
      .attr("y2", d3.svg.mouse(this)[1]);

}

function mouseup() {
  if (mousedown_node) {
    // hide drag line
    drag_line
      .attr("class", "drag_line_hidden")

    if (!mouseup_node) {
      // add node
      var point = d3.mouse(this),
        node = {x: point[0], y: point[1]},
        n = nodes.push(node);

      // select new node
      selected_node = node;
      selected_link = null;

      // add link to mousedown node
      links.push({source: mousedown_node, target: node});
    }

    redraw();
  }
  // clear mouse event vars
  resetMouseVars();
}

function resetMouseVars() {
  mousedown_node = null;
  mouseup_node = null;
  mousedown_link = null;
}

function tick() {
  link.attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });

  node.attr("x", function(d) { return d.x-10; })// for circle its cx
      .attr("y", function(d) { return d.y-10; });//for circle its cy
}

// rescale g
function rescale() {
  trans=d3.event.translate;
  scale=d3.event.scale;

  vis.attr("transform",
      "translate(" + trans + ")"
      + " scale(" + scale + ")");
}

// redraw force layout
function redraw() {

  link = link.data(links);

  link.enter().insert("line", ".node")
      .attr("class", "link")
      .on("mousedown", 
        function(d) { 
          mousedown_link = d; 
          if (mousedown_link == selected_link) selected_link = null;
          else selected_link = mousedown_link; 
          selected_node = null; 
          redraw(); 
        })

  link.exit().remove();

  link
    .classed("link_selected", function(d) { return d === selected_link; });

  node = node.data(nodes);

  //node.enter()//.insert("circle")

    /*node.enter().insert("circle")
    .attr("class","node")
    .attr("r", 5)*/

    var rectSize = 50;


    node.enter().append("svg:rect")
       .attr("class","node")
       .attr("width", rectSize)
       .attr("height", rectSize)    
       .style("fill","powderBlue")
       .attr("id", "hello")
       .attr("title", "hello")
    .style("fixed","true")
       //.text("hello")
       .on("mousedown", 
        function(d) { 
          // disable zoom
          vis.call(d3.behavior.zoom().on("zoom"), null);

          mousedown_node = d;
          if (mousedown_node == selected_node) selected_node = null;
          else selected_node = mousedown_node; 
          selected_link = null; 

          // reposition drag line
          drag_line
              .attr("class", "link")
              .attr("x1", mousedown_node.x)
              .attr("y1", mousedown_node.y)
              .attr("x2", mousedown_node.x)
              .attr("y2", mousedown_node.y);

          redraw(); 
        })
      .on("mousedrag",
        function(d) {
          // redraw();
        })
      .on("mouseup", 
        function(d) { 
          if (mousedown_node) {
            mouseup_node = d; 
            if (mouseup_node == mousedown_node) { resetMouseVars(); return; }

            // add link
            var link = {source: mousedown_node, target: mouseup_node};
            links.push(link);

            // select new link
            selected_link = link;
            selected_node = null;

            // enable zoom
            vis.call(d3.behavior.zoom().on("zoom"), rescale);
            redraw();
          } 
        })
    .transition()
      .duration(750)
      .ease("elastic")
      //.attr("r", 6.5);
     .attr("width", rectSize+1)
  .attr("height", rectSize+1);





  node.exit().transition()
      //.attr("r", 0)
    .remove();

  node
    .classed("node_selected", function(d) { return d === selected_node; });


  if (d3.event) {
    // prevent browser's default behavior
    d3.event.preventDefault();
  }

  force.start();

}

function spliceLinksForNode(node) {
  toSplice = links.filter(
    function(l) { 
      return (l.source === node) || (l.target === node); });
  toSplice.map(
    function(l) {
      links.splice(links.indexOf(l), 1); });
}

function keydown() {
  if (!selected_node && !selected_link) return;
  switch (d3.event.keyCode) {
    case 8: // backspace
    case 46: { // delete
      if (selected_node) {
        nodes.splice(nodes.indexOf(selected_node), 1);
        spliceLinksForNode(selected_node);
      }
      else if (selected_link) {
        links.splice(links.indexOf(selected_link), 1);
      }
      selected_link = null;
      selected_node = null;
      redraw();
      break;
    }
  }
}

</script>
</body>
</html>

2 个答案:

答案 0 :(得分:1)

首先请不要把大部分代码都放在那里,但要把你的例子放到一个简单的东西上,因为这样很难帮助你。

如果您真的想要显示代码,请将其放入fidd,以便我们可以看到它的结果(http://fiddle.jshell.net/)。

好吧,如果我明白你想要什么,你必须在追加之前选择你的元素。 试试这个:

// Here to update the text
node.selectAll('text')
    .text(function(d){ //what you want to do on update }

// Here the creation
rect.append('svg:text')
    .text('Hello wold')

但是你还需要替​​换你的节点输入,并且不要忘记更新它们,确实d3创建的常见模式是//更新//输入//退出:

// your node update
node.selectAll('rect')
// do what you want on update

// your node enter
var g = node.enter().append('svg:g')
g.append('svg:rect')
// all of your stuff

这样你就会有一个g元素,它包含你的节点元素和与节点相关联的文本元素,这就是我认为你想要的一个方便的结构

干杯

答案 1 :(得分:0)

您可以设置<text>的标准x,y属性并定义最大宽度,然后使用我在此处找到的这个很好的函数: http://bl.ocks.org/mbostock/7555321

自动为长文本svg。

换行
function wrap(text, width) {
  text.each(function() {
    var text = d3.select(this),
        words = text.text().split(/\s+/).reverse(),
        word,
        line = [],
        lineNumber = 0,
        lineHeight = 1.1, // ems
        y = text.attr("y"),
        dy = parseFloat(text.attr("dy")),
        tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
    while (word = words.pop()) {
      line.push(word);
      tspan.text(line.join(" "));
      if (tspan.node().getComputedTextLength() > width) {
        line.pop();
        tspan.text(line.join(" "));
        line = [word];
        tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
      }
    }
  });
}