代码之家  ›  专栏  ›  技术社区  ›  Marc Maxmeister

使用d3中的“dy”属性将标签与刻度对齐

  •  1
  • Marc Maxmeister  · 技术社区  · 6 年前

    这让我困惑。我正在尝试使用我的d3图表上的“dy”属性将标签与水平条形图上的刻度对齐。

    文件上说:

    dy属性表示元素位置或其内容沿y轴的移动。

    < /块引用>

    这是javascript。它从数组的“问题”部分提取文本。

    ticks.append(“文本”)。
    .attr(“类”,“依拉贝尔”)。
    .attr(“dy”,“0em”)。
    AtTr(“x”,- 9)
    .attr(“填充”,“000”)
    .style(“文本锚定”、“结束”)
    .style(“字体大小”,“x-small”)。
    .text(函数(d)返回d['问题'];)
    .call(包装,600);
    < /代码> 
    
    

    因为它更容易说明,当我在“dy”上使用“0em”、“1em”或“2em”时,会得到非常不同的效果。0em“太高了。”1em“将多行挤在一起(因为使用了换行功能),而”2em“将文本向上而不是向下换行。

    那么,如何移动标签以与图表上的刻度对齐呢?

    < H2>更新< /H2>

    通过系统地删除标题中的javascript行,我发现word_wrap函数以奇怪的方式上下推送此文本,使其难以与节点对齐。

    函数换行(文本,宽度){
    text.each(函数()。{
    var text=d3.选择(这个),
    words=text.text().split(/\s+/).reverse(),
    单词
    线=[]
    林数=0,
    lineheight=-2.0,//ems
    x=text.attr(“x”),//<--包括x!
    Y=文本。属性(“Y”),
    dy=parsefloat(text.attr(“dy”)),
    tspan=text.text(null).append(“tspan”).attr(“x”,x).attr(“y”,y).attr(“dy”,dy-2.5+“em”);
    while(word=words.pop()){
    行.推(字);
    tspan.text(line.join(“”);
    if(tspan.node().getComputedTextLength()>宽度){
    Pro();
    tspan.text(line.join(“”);
    线= [字];
    tspan=text.append(“tspan”).attr(“x”,x).attr(“y”,y).attr(“dy”,lineheight-dy+3+“em”).text(word);
    }
    }
    (});
    }
    
    函数cwrap(文本、宽度){
    text.each(函数()。{
    var text=d3.选择(这个),
    words=text.text().split(/\s+/).reverse(),
    单词
    线=[]
    行号=0,
    lineheight=1.1,//ems
    x=文本。属性(“x”),
    Y=文本。属性(“Y”),
    dy=parsefloat(text.attr(“dy”)),
    tspan=text.text(null).append(“tspan”).attr(“x”,x).attr(“y”,y).attr(“dy”,dy+“em”);
    while(word=words.pop()){
    行.推(字);
    tspan.text(line.join(“”);
    if(tspan.node().getComputedTextLength()>宽度){
    Pro();
    tspan.text(line.join(“”);
    线= [字];
    tspan=text.append(“tspan”).attr(“x”,x).attr(“y”,y).attr(“dy”,++linenumber*lineheight+dy+“em”).text(word);
    }
    }
    (});
    }
    < /代码> 
    
    

    通过使用cwrap而不是wrapI was able to make this work.这两种功能都不完善,只适用于有限大小的文本(最多3行或2行)。但它解决了我的问题。

    dy属性表示元素或其内容位置沿y轴的移动。

    这是javascript。它从数组的“问题”部分提取文本。

    ticks.append("text")
        .attr("class", "ylabel")        
        .attr("dy", "0em")
        .attr("x", -9)
        .attr("fill", "#000")
        .style("text-anchor", "end")
        .style("font-size", "x-small")
        .text(function(d) {  return d['Question']; })
        .call(wrap, 600); 
    

    因为它更容易说明,当我在“dy”上使用“0em”、“1em”或“2em”时,会得到非常不同的效果。0em“太高了。”1em“将多行挤在一起(因为使用了换行功能),而2em将文本向上而不是向下换行。

    enter image description here 那么,如何移动标签以与图表上的刻度对齐呢?

    更新

    通过系统地删除标题中的javascript行,我发现word_wrap函数以奇怪的方式上下推送文本,使其难以与节点对齐。

    function wrap(text, width) {
        text.each(function() {
            var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = -2.0, // ems
            x = text.attr("x"), //<-- include the x!
            y = text.attr("y"),
            dy = parseFloat(text.attr("dy")),
            tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy - 2.5 + "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", x).attr("y", y).attr("dy", lineHeight - dy + 3 + "em").text(word);
                }
            }
        });
    }
    
    function cwrap(text, width) {
      text.each(function() {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.1, // ems
            x = text.attr("x"),
            y = text.attr("y"),
            dy = parseFloat(text.attr("dy")),
            tspan = text.text(null).append("tspan").attr("x", x).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", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
          }
        }
      });
    }
    

    通过使用cwrap而不是wrap我能做到这一点。这两种功能都不完善,只适用于有限大小的文本(最多3行或2行)。但它解决了我的问题。

    2 回复  |  直到 6 年前
        1
  •  1
  •   A Zibuda    6 年前

    根据我的经验,在dx中,您需要进行动态设置,使事物在d3中相对于其他事物显示出来。下面是一个示例,说明如何让标签显示在力导向图上节点的旁边

    label = label.enter().append("text")
                .attr("class", "label")
                .attr("dx", function (d) { return d.radius * 1.25; })
                .attr("dy", ".35em")
                .attr("opacity", function (d) { if (d.radius <= 7) { return 0; } return 1; })
                .attr("font-weight", "normal")
                .style("font-size", 10)
                .text(function (d) { return d.id; })
                .merge(label);
    

    dx值是您希望基于正在绘制的内容的值,但是在看不到有关如何绘制图形其余部分的代码的情况下,我不确定应该基于其他元素的哪些属性。

        2
  •  0
  •   Marc Maxmeister    6 年前

    在我的特定情况下,wrap函数以奇怪的方式强制文本与图表上的刻度不对齐(如果“dy”偏移量为“2em”,则包括向上包装文本)。我必须调整wrap函数来解决“dy”问题。