javascript - 如何在放大时显示全文并在缩小时 chop 它

标签 javascript css d3.js

我正在使用 d3.js 创建一个树形图,它工作正常......但我希望文本对缩放使用react,这是 JSFiddle .

请看第一个节点...它有很多字符(在我的例子中最大为 255)

当放大或缩小时,我的文字保持不变,但我想在放大时看到所有内容。

var json = {
  "name": "Maude Charlotte Licia  Fernandez Maude Charlotte Licia  Fernandez Maude Charlotte Licia  Fernandez Maude Charlotte Licia  FernandezMaude Charlotte Licia  Fernandez Maude Charlotte Licia  Fernandez Maude Charlotte Licia  Fernandez Maude asdlkhkjh asd asdsd",
  "id": "06ada7cd-3078-54bc-bb87-72e9d6f38abf",
  "_parents": [{
    "name": "Janie Clayton Norton",
    "id": "a39bfa73-6617-5e8e-9470-d26b68787e52",
    "_parents": [{
      "name": "Pearl Cannon",
      "id": "fc956046-a5c3-502f-b853-d669804d428f",
      "_parents": [{
        "name": "Augusta Miller",
        "id": "fa5b0c07-9000-5475-a90e-b76af7693a57"
      }, {
        "name": "Clayton Welch",
        "id": "3194517d-1151-502e-a3b6-d1ae8234c647"
      }]
    }, {
      "name": "Nell Morton",
      "id": "06c7b0cb-cd21-53be-81bd-9b088af96904",
      "_parents": [{
        "name": "Lelia Alexa Hernandez",
        "id": "667d2bb6-c26e-5881-9bdc-7ac9805f96c2"
      }, {
        "name": "Randy Welch",
        "id": "104039bb-d353-54a9-a4f2-09fda08b58bb"
      }]
    }]
  }, {
    "name": "Helen Donald Alvarado",
    "id": "522266d2-f01a-5ec0-9977-622e4cb054c0",
    "_parents": [{
      "name": "Gussie Glover",
      "id": "da430aa2-f438-51ed-ae47-2d9f76f8d831",
      "_parents": [{
        "name": "Mina Freeman",
        "id": "d384197e-2e1e-5fb2-987b-d90a5cdc3c15"
      }, {
        "name": "Charlotte Ahelandro Martin",
        "id": "ea01728f-e542-53a6-acd0-6f43805c31a3"
      }]
    }, {
      "name": "Jesus Christ Pierce",
      "id": "bfd1612c-b90d-5975-824c-49ecf62b3d5f",
      "_parents": [{
        "name": "Donald Freeman Cox",
        "id": "4f910be4-b827-50be-b783-6ba3249f6ebc"
      }, {
        "name": "Alex Fernandez Gonzales",
        "id": "efb2396d-478a-5cbc-b168-52e028452f3b"
      }]
    }]
  }]
};

var boxWidth = 250,
  boxHeight = 100;

// Setup zoom and pan
var zoom = d3.behavior.zoom()
  .scaleExtent([.1, 1])
  .on('zoom', function() {
    svg.attr("transform", "translate(" + d3.event.translate + ") scale(" + d3.event.scale + ")");
  })
  // Offset so that first pan and zoom does not jump back to the origin
  .translate([600, 600]);

var svg = d3.select("body").append("svg")
  .attr('width', 1000)
  .attr('height', 500)
  .call(zoom)
  .append('g')
  // Left padding of tree so that the whole root node is on the screen.
  // TODO: find a better way
  .attr("transform", "translate(150,200)");

var tree = d3.layout.tree()
  // Using nodeSize we are able to control
  // the separation between nodes. If we used
  // the size parameter instead then d3 would
  // calculate the separation dynamically to fill
  // the available space.
  .nodeSize([100, 200])
  // By default, cousins are drawn further apart than siblings.
  // By returning the same value in all cases, we draw cousins
  // the same distance apart as siblings.
  .separation(function() {
    return .9;
  })
  // Tell d3 what the child nodes are. Remember, we're drawing
  // a tree so the ancestors are child nodes.
  .children(function(person) {
    return person._parents;
  });

var nodes = tree.nodes(json),
  links = tree.links(nodes);

// Style links (edges)
svg.selectAll("path.link")
  .data(links)
  .enter().append("path")
  .attr("class", "link")
  .attr("d", elbow);

// Style nodes    
var node = svg.selectAll("g.person")
  .data(nodes)
  .enter().append("g")
  .attr("class", "person")
  .attr("transform", function(d) {
    return "translate(" + d.y + "," + d.x + ")";
  });

// Draw the rectangle person boxes
node.append("rect")
  .attr({
    x: -(boxWidth / 2),
    y: -(boxHeight / 2),
    width: boxWidth,
    height: boxHeight
  });

// Draw the person's name and position it inside the box
node.append("text")
  .attr("text-anchor", "start")
  .attr('class', 'name')
  .text(function(d) {
    return d.name;
  });

// Text wrap on all nodes using d3plus. By default there is not any left or
// right padding. To add padding we would need to draw another rectangle,
// inside of the rectangle with the border, that represents the area we would
// like the text to be contained in.
d3.selectAll("text").each(function(d, i) {
  d3plus.textwrap()
    .container(d3.select(this))
    .valign("middle")
    .draw();
});


/**
 * Custom path function that creates straight connecting lines.
 */
function elbow(d) {
  return "M" + d.source.y + "," + d.source.x + "H" + (d.source.y + (d.target.y - d.source.y) / 2) + "V" + d.target.x + "H" + d.target.y;
}
body {
  text-align: center;
}
svg {
  margin-top: 32px;
  border: 1px solid #aaa;
}
.person rect {
  fill: #fff;
  stroke: steelblue;
  stroke-width: 1px;
}
.person {
  font: 14px sans-serif;
}
.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3plus/1.8.0/d3plus.min.js"></script>

最佳答案

我在这个 fiddle 中制作了您的要求样本

它可能需要更多的调整来定位文本垂直居中;但这可以作为您继续工作的基础。计算在函数 wrap() 中完成,并调用页面加载和缩放。

function wrap() {
  var texts = d3.selectAll("text"),
    lineHeight = 1.1, // ems
    padding = 2, // px
    fSize = scale > 1 ? fontSize / scale : fontSize,
    // find how many lines can be included
    lines = Math.floor((boxHeight - (2 * padding)) / (lineHeight * fSize)) || 1;
  texts.each(function(d, i) {
    var text = d3.select(this),
      words = d.name.split(/\s+/).reverse(),
      word,
      line = [],
      lineNumber = 0,
      tspan = text.text(null).append("tspan").attr("dy", "-0.5em").style("font-size", fSize + "px");
    while ((word = words.pop())) {
      line.push(word);
      tspan.text(line.join(" "));
      // check if the added word can fit in the box
      if ((tspan.node().getComputedTextLength() + (2 * padding)) > boxWidth) {
        // remove current word from line
        line.pop();
        tspan.text(line.join(" "));
        lineNumber++;
        // check if a new line can be placed
        if (lineNumber > lines) {
          // left align text of last line
          tspan.attr("x", (tspan.node().getComputedTextLength() - boxWidth) / 2 + padding);
          --lineNumber;
          break;
        }
        // create new line
        tspan.text(line.join(" "));
        line = [word]; // place the current word in new line
        tspan = text.append("tspan")
          .style("font-size", fSize + "px")
          .attr("dy", "1em")
          .text(word);
      }
      // left align text
      tspan.attr("x", (tspan.node().getComputedTextLength() - boxWidth) / 2 + padding);
    }
    // align vertically inside the box
    text.attr("text-anchor", "middle").attr("y", padding - (lineHeight * fSize * lineNumber) / 2);
  });
}

另请注意,我已将样式 dominant-baseline: hanging; 添加到 .person

关于javascript - 如何在放大时显示全文并在缩小时 chop 它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40931946/

相关文章:

javascript - 确认密码自定义指令在 Angular 中不起作用

javascript - 如何在不隐藏箭头的情况下隐藏幻灯片上的溢出?

jquery - style::-webkit-slider-thumb 与 jquery

php - 通过嵌套的 while 循环保证 div

javascript - 将 svg 元素定位在 div 上

javascript - 使用 D3js 循环遍历一组图像

javascript - 从 Javascript 中的 URL 为 d3.js 创建多嵌套 JSON

javascript - Chrome 开发者工具缓存旧版本的 JavaScript 文件

javascript - JqueryMobile 页面的结构?

html - 如何使用 CSS 变换伪造宽度动画?