首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在放大时显示全文,在缩小时截断

如何在放大时显示全文,在缩小时截断
EN

Stack Overflow用户
提问于 2016-12-02 20:11:54
回答 2查看 1.9K关注 0票数 17

我正在用d3.js创建一个树形图,它工作得很好…但我想让文本对缩放做出反应,这是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>

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-12-09 12:49:53

this jsfiddle中的代码是为了解决您在使用非常大的树形图表时遇到的性能问题。在缩放事件处理程序中使用setTimeout设置延迟,以允许在不调整文本大小的情况下以“全速”缩放。一旦缩放停止一小段时间,文本就会根据新的缩放比例重新排列:

var scaleValue = 1;
var refreshTimeout;
var refreshDelay = 0;

var zoom = d3.behavior.zoom()
    .scaleExtent([.1, 1.5])
    .on('zoom', function () {
        svg.attr("transform", "translate(" + d3.event.translate + ") scale(" + d3.event.scale + ")");
        scaleValue = d3.event.scale;
        if (refreshTimeout) {
            clearTimeout(refreshTimeout);
        }
        refreshTimeout = setTimeout(function () {
            wrapText();
        }, refreshDelay);
    })

延迟(以毫秒为单位)取决于树中的节点数量。您可以尝试使用该数学表达式,以便为树中预期的各种节点计数找到最佳参数。

// Calculate the refresh delay
refreshDelay = Math.pow(node.size(), 0.5) * 2.0;

您还可以在calcFontSize中设置参数以满足您的需要:

// Calculate the font size for the current scaling
var calcFontSize = function () {
    return Math.min(24, 10 * Math.pow(scaleValue, -0.25))
}

节点的初始化略有修改:

node.append("rect")
    .attr({
        x: 0,
        y: -(boxHeight / 2),
        width: boxWidth,
        height: boxHeight
    });

node.append("text")
    .attr("text-anchor", "start")
    .attr("dominant-baseline", "middle")
    .attr('class', 'name')
    .text(function (d) {
        return d.name;
    });

并且文本在wrapText中被处理

// Adjust the font size to the zoom level and wrap the text in the container
var wrapText = function () {
    d3.selectAll("text").each(function (d, i) {
        var $text = d3.select(this);
        if (!$text.attr("data-original-text")) {
            // Save original text in custom attribute
            $text.attr("data-original-text", $text.text());
        }
        var content = $text.attr("data-original-text");
        var tokens = content.split(/(\s)/g);
        var strCurrent = "";
        var strToken = "";
        var box;
        var lineHeight;
        var padding = 4;
        $text.text("").attr("font-size", calcFontSize());
        var $tspan = $text.append("tspan").attr("x", padding).attr("dy", 0);
        while (tokens.length > 0) {
            strToken = tokens.shift();
            $tspan.text((strCurrent + strToken).trim());
            box = $text.node().getBBox();
            if (!lineHeight) {
                lineHeight = box.height;
            }
            if (box.width > boxWidth - 2 * padding) {
                $tspan.text(strCurrent.trim());
                if (box.height + lineHeight < boxHeight) {
                    strCurrent = strToken;
                    $tspan = $text.append("tspan").attr("x", padding).attr("dy", lineHeight).text(strCurrent.trim());
                } else {
                    break;
                }
            }
            else {
                strCurrent += strToken;
            }
        }
        $text.attr("y", -(box.height - lineHeight) / 2);
    });
}
票数 8
EN

Stack Overflow用户

发布于 2016-12-06 03:06:40

我在这个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);
  });
}

还要注意,我已经在.person类中添加了样式dominant-baseline: hanging;

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40931946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档