【问题标题】:How To Align Text Inside SVG In D3.js如何在 D3.js 中对齐 SVG 内的文本
【发布时间】:2016-03-28 18:15:20
【问题描述】:

我创建了一个带有条形图的可视数据,但我无法对齐文本“国内生产总值”和“单位:十亿美元季节性调整:季节性调整,年利率说明:国民收入和产品指南美国账户 (NIPA) - (http://www.bea.gov/national/pdf/nipaguid.pdf)"

截至目前,它们在顶部重叠:

我想在顶部对齐“国内生产总值”和“单位:十亿美元季节性调整:季节性调整后的年利率注释:美国国民收入和产品账户指南 (NIPA) - (@ 987654323@)" 在底部喜欢

Here Is My Code Fiddle Link

var url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json";

//Fetch Data By .$getJSON Method
$.getJSON(url, function (d) {
    var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
    ];
    var data = d.data;
    /*test data by
    console.log(data[0][0]);
    */
    //create Margin
    var margin = { top: 40, right: 20, bottom: 30, left: 50 },
        width = 960 - margin.left - margin.right,
        height = 600 - margin.top - margin.bottom;
    /*
       Define Min & Max Data for Scale
    */
    console.log(d.description);
    var minDate = new Date(data[0][0]);
    var maxDate = new Date(data[d.data.length - 1][0]);
    /*
     test data by 
     console.log(minDate);
     console.log(maxDate);
    */
    /*
    define scale then followed by axis
    */
    // define x and y scales
    // define x and y scales
    var xScale = d3.time.scale().
        domain([minDate, maxDate]).
        range([0, width]);
    var yScale = d3.scale.linear().
        domain([0, d3.max(data, function (d) {
            return d[1];
        })]).
        range([height, 0]);
    // define x axis and y axis
    var xAxis = d3.svg.axis().
        scale(xScale).
        orient("bottom").
        ticks(d3.time.years, 5);
    var yAxis = d3.svg.axis().
        scale(yScale).
        orient("left").
        ticks(10, "");
    var thisDate = new Date(data[0][0]);
    /*
    Create Tooltip
    */
    var toolTip = d3.tip()
      .attr('class', 'd3-tip')
      .offset([-10, 0])
      .html(function (d) {
          return ('<strong>$' + d[1].toLocaleString() + ' Billion</strong><p>' + thisDate.getFullYear() + ' - ' + monthNames[thisDate.getMonth()] + '</p>');
      });
    /*
    create svg element then append height and width and g which act as a container
    */
    var svg = d3.select(".mainContainer").
      attr({
          "width": width + margin.right + margin.left,
          "height": height + margin.top + margin.bottom
      }).
    append("g").
      attr("transform", "translate(" + margin.left + "," + margin.right + ")");

    //call toolTip
    svg.call(toolTip);
    // Draw xAxis
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
    //Draw yAxis
    svg.append("g")
     .attr("class", "y axis")
     .call(yAxis)
   .append("text")
     .attr("transform", "rotate(-90)")
     .attr("y", 6)
     .attr("dy", ".71em")
     .style("text-anchor", "end")
     .text("Gross Domestic Product, USA");
    /*
  create bar or bind data
  */
    //bind data
    svg.selectAll(".bar")
      .data(data)
   //enter data
    .enter().
        append("rect")
   //update data
      .attr("class", "bar")
      .attr("x", function (d) { return xScale(new Date(d[0])); })
      .attr("width", Math.ceil(width / data.length))
      .attr("y", function (d) { return yScale(d[1]); })
      .attr("height", function (d) { return height - yScale(d[1]); })
      .on('mouseover', toolTip.show)
      .on('mouseout', toolTip.hide);
    //add description on top and bottom of svg
    svg.
        attr("class", "title").
        append("text").
        html("Gross Domestic Product </br>")
    svg.
        attr("class", "notes").
        append("text").
        text(d.description);
    

});
svg {
  
  margin-left: auto;
  margin-right: auto;
  display: block;
  background-color:antiquewhite;
}
body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}
.bar {
  fill: orange;
}

.bar:hover {
  fill: orangered ;
}
.d3-tip {
  line-height: 1;
  font-weight: bold;
  padding: 12px;
  background: rgba(0, 0, 0, 0.8);
  color: #fff;
  border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
  box-sizing: border-box;
  display: inline;
  font-size: 10px;
  width: 100%;
  line-height: 1;
  color: rgba(0, 0, 0, 0.8);
  content: "\25BC";
  position: absolute;
  text-align: center;
}

/* Style northward tooltips differently */
.d3-tip.n:after {
  margin: -1px 0 0 0;
  top: 100%;
  left: 0;
}
.notes {
  font-size: 12px;
  font-family: sans-serif;
  color: steelblue;
  padding: 20px;
  text-align: center;
  vertical-align:bottom;
}
.title {
  font-size: 2.5em;
  font-family: sans-serif;
  color: steelblue;
  text-align: center;
  padding: 15px 0px 5px 0px;
}
<!DOCTYPE html>
<html>
<head>
    <title>D3-Zipline: GDP Bar Graph</title>
    <meta charset="utf-8" />
    <link href="../Content/bootstrap-theme.min.css" rel="stylesheet" />
    <link href="../Content/bootstrap.min.css" rel="stylesheet" />
    <script src="../Scripts/d3/d3.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.6.7/d3-tip.min.js"></script>
    <link href="demo.css" rel="stylesheet" />
</head>
<body>
    
    <div class="container-fluid text-center">
        <br /><br />
        <svg class="mainContainer">
        </svg>
    </div>
    <script src="../Scripts/jquery-2.2.1.min.js"></script>
    <script src="../Scripts/bootstrap.min.js"></script>
    <script src="demo.js"></script>
</body>
</html>

【问题讨论】:

    标签: json d3.js


    【解决方案1】:

    这里有几件事要解决:

    1. 创建正确对齐的 x 轴标签
    2. 将长 x 轴标签分成多行(否则会太长)
    3. 为标题、注释和其他文本元素正确设置 CSS 类

    按顺序排列:

    轴下的X轴标签,居中

    最简单的方法是在绘制 x 轴和 y 轴的代码之间附加文本。

    svg.append("text")    // text label for the x axis
      .attr("class", "notes")
      .attr("transform", "translate(" + width/2 + ")")
      .attr("y",  height + margin.bottom)
      .text(d.description)
      .call(splitLongLabel);    // The next section explains this bit...
    

    将长 x 轴标签分成多行

    为此,我从这个答案中借了一点:https://stackoverflow.com/a/13275930/3442309

    看起来分割d.description 文本最明智的位置是在“-”字符处:这是在您希望图表外观的屏幕截图上完成的。

    要实现拆分,用户tspan元素

    var insertLinebreaks = function (d) {
        var el = d;    // Get the current element
        var words = d.text().split("-");    // Split text  at the hyphen
        el.text('');
        for (var i = 0; i < words.length; i++) {    // Then build up the tspans
            var tspan = el.append('tspan')
                .attr('x', 0)
                .text(words[i])
                .style("text-anchor", "middle");
            if (i > 0)
                tspan
                    .attr('x', 0)
                    .attr('dy', '15')
                    .style("text-anchor", "middle");
        }
    };
    

    要更改此标签的拆分方式和位置,或者使其更通用(例如基于长度而不是特定字符的拆分),只需修改 split 的定义方式

    为文本设置 CSS 类

    在您的示例中,标题未使用 title CSS 类,因此未获得预期的样式。原因是脚本末尾的以下代码:

    svg.
        attr("class", "notes").
        append("text").
        text(d.description);
    

    这样做是为 svg 中的 all 文本设置 notes 样式。更准确地说,您应该在 附加文本之后设置类属性。

    对此进行更正,对于标题,我们现在有:

    svg.
        //attr("class", "title"). <- Removed from here
        append("text").
        attr("class", "title").    // <- added here
        html("Gross Domestic Product </br>")
    

    我已经在 javascript 中为 `title 添加了一些定位,而不是在 CSS 中:

        ....
        .attr('x', width / 2)
        .attr('y', 20)
        .style("text-anchor", "middle");
    

    最后,我更正了您的 CSS,它使用 color 来应用文本颜色,而不是 fill,这是正确的方法

    这是一个包含所描述的所有更改的小提琴:https://jsfiddle.net/henbox/nuwzxoz8/1/

    【讨论】:

    • 谢谢,这正是我想要的,如果您看到工具提示日期部分一直到 1947 年 1 月,我刚刚注意到另一个问题,您能帮我解决这个问题,再次感谢
    • 您只需要更改设置thisdate 的位置,使其位于toolTip 函数内(以确保每次将鼠标悬停在新柱上时都会重新初始化)。我在这里进行了更改:jsfiddle.net/henbox/nuwzxoz8/2
    猜你喜欢
    • 2017-05-14
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 2019-06-22
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    相关资源
    最近更新 更多